2014-08-30 2 views
0

Использование 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(); 

ответ

0

Попробуйте это:

@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.UPDATE) 
@JoinColumn(name = "PARTNER_ID") 
private Contact partner; 
+0

Спасибо за предложение, я попробовал и результаты одинаковы. При совершении транзакции автоматически очищается EntityManager, поэтому это не имеет значения. Кроме того, изменения в контакте 1 сбрасываются в базу данных, но не меняются на контакт2. Вот чего я не понимаю. – Spiff

+0

Я думаю, что вы меня смутили ... Итак, когда вы сохраняете базу данных, изменения появляются в базе данных для контакта 1, но если вы вернете контакт объекта 2 (ведьма должна иметь ссылку на контакт1) из базы данных, свяжитесь с нами партнер равен нулю? – Mihai

+0

Contact.unassignPartner() переназначает партнера для текущего экземпляра (this), а также для ссылочного экземпляра (партнера). Поэтому после вызова contact1.unassignPartner() и совершения транзакции я ожидаю, что contact1.partner = null и contact2.partner = null, как в памяти, так и в базе данных. Я наблюдаю contact1.partner = null и contact2.partner = null в памяти, но contact1.partner = null и contact2.partner = contact1 в базе данных. – Spiff

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