Я пытаюсь исправить отношения @OneToMany и @ManyToOne.

Класс 1:

@Entity
public class IdeaProfile {

@Id
@GeneratedValue
private int ideaProfileId;

private String name;

Date dateConcieved;

@OneToOne
@JoinColumn(name="statusCode")  
private Status status;


@OneToMany(fetch=FetchType.EAGER, targetEntity=Pitch.class, cascade=CascadeType.ALL)
@JoinColumn(name = "ideaProfileId") 
private List<Pitch> pitchs;

    ....getters and setters....

Класс2:

@Entity
public class Pitch {

@Id
@GeneratedValue
private int id;

@ManyToOne
@JoinColumn(name = "ideaProfileId")
private IdeaProfile ideaProfile;

private Date date;

private String notes;

 ....getters and setters....

Эта связь, кажется, работает нормально, когда я загружаю или сохраняю новую запись:

Hibernate: insert into IdeaProfile (dateConcieved, genreCode, name, statusCode) values (?, ?, ?, ?)
Hibernate: insert into Pitch (date, ideaProfileId, notes) values (?, ?, ?)
Hibernate: update Pitch set ideaProfileId=? where id=?

Однако, когда я пытаюсь обновить эту запись, он пытается установить для IdeaProfileId значение null:

Hibernate: update IdeaProfile set dateConcieved=?, genreCode=?, name=?, statusCode=?,  where ideaProfileId=?
Hibernate: update Pitch set date=?, ideaProfileId=?, notes=? where id=?
Hibernate: update Pitch set ideaProfileId=null where ideaProfileId=?

Когда я отлаживаю, я вижу, что IdeaProfileId действительно установлен на Pitch Object ...

К вашему сведению, я не обновляю напрямую исходные объекты, загруженные из БД. Эти домены сопоставляются с классом модели, который обновляется пользовательским интерфейсом. Поэтому при сохранении / обновлении я сопоставляю значения с новыми объектами домена, включая идентификаторы, подобные следующим:

IdeaProfile domain = new IdeaProfile();
domain.setId(model.getIdeaProfileId());
domain.setName(model.getName());
domain.setStatus(model.getStatus());
domain.setDateConcieved(Date.valueOf(model.getDateConvieved()));
for (PitchModel pitch : model.getPitches()) {
     Pitch pitchDomain = new Pitch();
     pitchDomain.setId(pitch.getId());
     pitchDomain.setDate(Date.valueOf(pitch.getDate()));
     pitchDomain.setNotes(pitch.getNotes());
     pitchDomain.setIdeaProfile(domain);
     if(domain.getPitchs() == null ) {
        domain.setPitchs(new ArrayList<Pitch>());
     }
     domain.getPitchs().add(pitchDomain);
 }

openSession();
session.beginTransaction();
session.saveOrUpdate(domain);
session.getTransaction().commit();
closeSession();

Кто-нибудь знает, что я сделал неправильно, поэтому Hibernate заставляет обновление пытаться установить IdeaProfileId равным нулю?

Очень признателен.

4
rioubenson 23 Мар 2014 в 17:44

1 ответ

Лучший ответ

Здесь нет двунаправленной ассоциации. У вас есть две независимые ассоциации, каждая из которых неправильно сопоставлена ​​с одним и тем же столбцом.

В двунаправленной ассоциации у вас всегда должна быть сторона владельца и обратная сторона. Обратная сторона помечается атрибутом mappedBy. В ассоциации OneToMany обратная сторона должна быть односторонней:

@OneToMany(mappedBy="ideaProfile", fetch=FetchType.EAGER, cascade=CascadeType.ALL)
private List<Pitch> pitchs;

...

@ManyToOne
@JoinColumn(name = "ideaProfileId")
private IdeaProfile ideaProfile;
16
Martin Konecny 31 Мар 2017 в 01:27
Проблема здесь в производительности: если вы используете EAGER, вам следует изучить таблицу Pitch, если есть много строк, но это неплохая практика, если это только диктат значений.
 – 
Guillermo Diaz
5 Дек 2019 в 10:22