2013-02-26 4 views
2

Я немного смущен двунаправленным отношением OneToOne, которое не может быть необязательным с обоих концов. Я использую JPA2 с Hibernate:Необязательные двунаправленные отношения OneToOne

@Entity 
@Table(name = "city") 
public class City { 

@Id 
@GeneratedValue 
@Column 
public Long _UID; 

    @OneToOne(mappedBy="city", optional=false, orphanRemoval = true, cascade=CascadeType.ALL) 
    public Mayor mayor; 
} 

@Entity 
@Table(name = "mayor") 
public class Mayor { 

@Id 
@GeneratedValue 
@Column 
public Long _UID; 

    @OneToOne(optional=false, cascade=CascadeType.ALL) 
    public City city; 
} 

И если я пытаюсь эту сделку:

Mayor m = new Mayor("Ed", "Lee"); 
City c = new City("San Francisco", 100000); 
m.setCity(c); 
c.setMayor(m); 

EntityTransaction et = this.getEm().get().getTransaction(); 
et.begin(); 

this.getEm().get().persist(c); 
this.getEm().get().flush(); 

et.commit(); 

я получаю следующее исключение:

javax.persistence.PersistenceException: org.hibernate.PropertyValueException: not-null property references a null or transient value: test.persistence.entity.Mayor.city 

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

С optional=false только на стороне города все в порядке.

ответ

1

Это потому, что у вас есть круговая зависимость от вашего отображения с помощью cascadeAll с обеих сторон.

Что происходит, что вы спасаете свой город, который спасает вашего мэра, который затем сохраняет ваш город, который еще не сохранился (поскольку вы пытаетесь сохранить его в первую очередь), и поэтому спящий режим не знает, как это сделать ссылка на город в БД.

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

[Изменить] кажется также, что ответственным за отношения является мэр (поскольку mappedby находится в городском классе). Я думаю, поскольку вы пытаетесь сохранить город, что город должен нести ответственность за отношения (и поэтому атрибут mappedBy должен находиться в классе мэра)

+0

Правильно ли я понимаю, я должен удалить 'Cascade.ALL' из «city city city», в сущности мэра и установите его аннотацию на '@OneToOne (optional = false)'. Я также пробовал это, получил такое же исключение. – speechkey

+0

Похоже, что ответственным за взаимоотношения является мэр (как указано в городском классе). Я думаю, поскольку вы пытаетесь сохранить город, что город должен нести ответственность за отношения (и поэтому атрибут mappedBy должен быть в классе мэра) – benzonico

+0

Спасибо benzonico, ваш последний комментарий сделал это. Если я не изменю ничего в своем коде, но отправлю на сохранение «Майор» (означает, что он владеет), он работает, как и ожидалось. Поэтому мой вопрос заключается в том, почему я не мог послать, чтобы сохранить «Город» (означает обратную сторону), во взаимоотношениях «один ко многим» это обычный случай? – speechkey

Смежные вопросы