@ManyToOne отображение не позволяет сохранить родительский идентификатор
Я использую JPA2 с реализацией EclipseLink
! [Простая структура таблицы] [1]
Вот две таблицы, которые я пытаюсь отобразить, и аннотации JPA.
public class Story implements Serializable{
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
Integer id;
@Temporal(TemporalType.TIMESTAMP)
@Column (name="DATE_CREATED")
Date dateCreated;
String title;
String description;
@Column(name="AUTHOR_ID")
Integer authorId;
@Column(name="COUNTRY_ID")
Integer countryId;
private String reviews;
@OneToMany(mappedBy = "story", cascade=CascadeType.ALL)
private List<Tip> tipList;
}
public class Tip implements Serializable{
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private Integer id;
private String description;
private Integer vote;
@ManyToOne (cascade=CascadeType.ALL)
@JoinColumn(name="STORY_ID", referencedColumnName="ID")
private Story story;
}
В качестве простого примера я хотел бы сохранить историю и некоторые связанные с ней советы в той же транзакции.
Вот раздел кода, который делает это:
Story newStory = new Story(title, body, ...);
EntityTransaction transaction = em.getTransaction().begin();
boolean completed = storyService.create(newStory);
//The tips are saved as a List<String>. This methods creates the needed List<Tip> from the Strings
List<Tip> tips = TipUtil.getTipList(tipList);
newStory.setTipList(tips)
transaction.commit();
У меня нет ошибок, и все сущности сохраняются в базе данных. Проблема в том, что в таблице tip поле story_id
всегда NULL
. Я могу представить, что JPA не может получить новый id
из таблицы рассказов. Какой правильный подход здесь?
LE
В текущем состоянии кода объекты Tip
сохраняются, но идентификатор страны остается нулевым.
Ответы
Ответ 1
С JPA всегда рекомендуется обновлять отношения на обеих сторонах в двунаправленном отношении. Это делается для того, чтобы данные были согласованы на вашем прикладном уровне и не имели ничего общего с базой данных.
Однако обязательно, чтобы вы обновили собственную сторону отношения в двунаправленном отношении.
Итак, установка/не настройка
story.setTipList(tips)
зависит от вас. Но если вы хотите, чтобы изменения правильно отражались в БД, вы месите вызов
tip.setStory(story)
поскольку Tip
- это собственная сторона здесь, в соответствии с вашим кодом.
Также ваш код выглядит неполным для меня. Причины,
- управляется объект, возвращаемый
storyService.create(newStory)
, но не newStory
. Поэтому просто установка newStory.setTipList(tips)
не обновит db
Ответ 2
Поскольку вам нужно обновить родительскую ссылку в каждом из своих дочерних элементов.
Как это делается, создайте метод addTip (подсказка) в классе Story.
Этот метод делает:
tip.setStory(this);
tipList.add(tip);
Если вам не нужен навигационный подход, вы можете удалить поле истории в подсказке, и оно решит вашу проблему.
Ответ 3
Удалите
@Column (name = "STORY_ID" ) private Integer storyId;
Вы уже объявляете это в @JoinColumn (name= "STORY_ID", referedColumnName = "ID" )
Вот почему вы получаете ошибку. Для поля существуют разные записи для записи [tip.STORY_ID]
Ответ 4
Вы не должны использовать PrimaryKeyJoinColumn, просто JoinColumn, но ваш полный класс поможет дать определенный ответ.
PrimaryKeyJoinColumn будет использоваться только в том случае, если story_id также является идентификатором Tip (без id в Tip), и для него было дублирующее базовое сопоставление. Его редко следует использовать и больше не требуется в JPA 2.0, поскольку дублирование сопоставлений идентификаторов больше не требуется.