При сопоставлении @ManyToOne не удается сохранить родительский идентификатор - PullRequest
13 голосов
/ 28 февраля 2012

Я использую 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 сохраняются, но идентификатор страны остается нулевым.

Ответы [ 4 ]

9 голосов
/ 02 марта 2012

В JPA всегда рекомендуется обновлять отношения с обеих сторон в двунаправленных отношениях. Это делается для того, чтобы данные были согласованы на уровне приложения и не имели отношения к базе данных.

Однако обязательно обновите сторону-владельца отношений в двунаправленных отношениях.

Итак, настройка / не настройка

story.setTipList(tips)

зависит от вас. Но если вы хотите, чтобы изменения правильно отражались в БД, вы должны вызвать

tip.setStory(story)

, как Tip является владельцем здесь, согласно вашему коду. Также ваш код выглядит неполным для меня. Причины есть,

  • сущность, возвращаемая storyService.create(newStory), управляется, но не newStory. Так что просто установка newStory.setTipList(tips) не обновит БД
6 голосов
/ 28 февраля 2012

Поскольку вам необходимо обновить историю родительских ссылок в каждом из ваших детей.

Способ сделать это - создать метод addTip (Tip tip) в вашем классе Story.

Этот метод делает:

tip.setStory(this);
tipList.add(tip);

Если вам не нужен ненаправленный подход, вы можете удалить поле истории в подсказке, и это решит вашу проблему

1 голос
/ 28 февраля 2012

Удалить

@ Column (name = "STORY_ID") приватный Integer storyId;

Вы уже объявляете это в @JoinColumn (name = "STORY_ID", referencedColumnName = "ID")

Вот почему вы получаете ошибку. Для поля существует несколько доступных для записи сопоставлений [tip.STORY_ID]

0 голосов
/ 28 февраля 2012

Вы не должны использовать PrimaryKeyJoinColumn, просто JoinColumn, но наличие вашего полного класса поможет дать определенный ответ.

PrimaryKeyJoinColumn будет использоваться только в том случае, если story_id также является идентификатором подсказки (без идентификатора в подсказке), и для него существует дублированное базовое сопоставление. Его следует использовать редко, и он больше не требуется в JPA 2.0, так как дублирование идентификаторов больше не требуется.

...