Использование JPA 2.1 и Hibernate 4.3.6.Final, я следующий простой сущности:JPA рекурсивный один-к-одному ленивых нагруженных ссылки не обновляется
@Entity
@Table(name = "CONTACT")
public class Contact {
@Id
@Column(name = "ID")
private String id = UUID.randomUUID().toString();
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "PARTNER_ID")
private Contact partner;
Contact() {
}
public void assignPartner(final Contact other) {
this.partner = Objects.requireNonNull(other);
other.partner = this;
}
public void unassignPartner() {
if (partner != null) {
partner.partner = null;
}
partner = null;
}
}
Уведомление ленивых нагруженных взаимно одна рекурсивная связь с партнером Contact. Также обратите внимание, как assignPartner() и unassignPartner() управляют двунаправленными отношениями.
И следующие методы:
private static void assignPartner(final EntityManager entityManager) {
entityManager.getTransaction().begin();
final Contact contact1 = entityManager.find(Contact.class, CONTACT1_ID);
final Contact contact2 = entityManager.find(Contact.class, CONTACT2_ID);
contact1.assignPartner(contact2);
entityManager.getTransaction().commit();
}
private static void unassignPartner(final EntityManager entityManager) {
entityManager.getTransaction().begin();
final Contact contact1 = entityManager.find(Contact.class, CONTACT1_ID);
contact1.unassignPartner();
entityManager.getTransaction().commit();
}
Предполагая, что существующие строки для CONTACT1_ID и CONTACT2_ID, после запуска assignPartner(), а затем unassignPartner(), состояние базы данных показывает, что контакт1 имеет нулевую partner_id и Contact2 до сих пор имеет не- null partner_id.
Однако, если я изменил тип выборки Contact.partner для EAGER, после запуска assignPartner(), то unassignPartner(), состояние базы данных показывает, что оба контакта1 и contact2 имеют null partner_id.
Почему? Почему изменения в объекте партнера не очищаются от базы данных?
РЕДАКТИРОВАТЬ 1
Изменения в партнерской ссылке путем прямого доступа к полю, например, partner.firstName = "DUMPED", также не распространяются. Изменения в ссылке партнера через доступ к методу, например. partner.setFirstName ("DUMPED"), распространяются. Ни один партнер .partner = null или partner.setPartner (null) не распространяется.
РЕДАКТИРОВАТЬ 2
Как было предложено Rat2000, перемещая unassignment логику вне метода Contact.unassignPartner(), так и внутри метода unassignPartner (EntityManager), кажется, работает должным образом. Так что это действительно связано с тем, как Hibernate имеет дело с прокси-сервером contact1.partner и, в частности, с прокси-сервером contact1.partner.partner.
final Contact contact1 = entityManager.find(Contact.class, CONTACT1_ID);
contact1.getPartner().unassignPartner();
contact1.unassignPartner();
Спасибо за предложение, я попробовал и результаты одинаковы. При совершении транзакции автоматически очищается EntityManager, поэтому это не имеет значения. Кроме того, изменения в контакте 1 сбрасываются в базу данных, но не меняются на контакт2. Вот чего я не понимаю. – Spiff
Я думаю, что вы меня смутили ... Итак, когда вы сохраняете базу данных, изменения появляются в базе данных для контакта 1, но если вы вернете контакт объекта 2 (ведьма должна иметь ссылку на контакт1) из базы данных, свяжитесь с нами партнер равен нулю? – Mihai
Contact.unassignPartner() переназначает партнера для текущего экземпляра (this), а также для ссылочного экземпляра (партнера). Поэтому после вызова contact1.unassignPartner() и совершения транзакции я ожидаю, что contact1.partner = null и contact2.partner = null, как в памяти, так и в базе данных. Я наблюдаю contact1.partner = null и contact2.partner = null в памяти, но contact1.partner = null и contact2.partner = contact1 в базе данных. – Spiff