2017-07-05 65 views
1

我有一個Parent-Child重新分配,當我嘗試通過Parent上的更新添加新的Child時,我的問題就開始了。Java Hibernate + spring-data:父級持久化時Cascading Childs不工作

當我的父是短暫的,一切正常

CreditCard cc = new CreditCard("1234"); 

    //User 
    User u1 = new User("KILLER"); 
    u1.addCreditCard(cc); // bi-directional happens here inside. 

    // An autowired Spring Data repository that implements CrudRepository 
    userRepository.save(u1); 

    Assert.assertEquals(1, u1.getCreditCardCollection().size()); 
    Assert.assertNotNull 
    (
      u1.getCreditCardCollection() 
      .stream() 
      .findFirst() 
      .get() 
      .getIdCreditCard() 
    ); 

測試以上成功地執行,並且用於CC對象產生的ID。

但是當我做:

User u2 = new User("Foo Bar McLoud"); // u2 is transient 

    userRepository.save(u2); // Now u2 is persistent 

    u2 = userRepository.findOne(u2.getIdLogin());// just to be sure I´m working with a persistent object ;) 

    CreditCard ccNew = new CreditCard("77777"); 

    u2.addCreditCard(ccNew);// bidirectional happens here inside 

    userRepository.save(u2); // should insert a new credit card right??? 

    Assert.assertEquals("User should have 1 credit card.", 
      1, u2.getCreditCardCollection().size()); // PASS 

    Set<CreditCard> ccs = u2.getCreditCardCollection(); 
    for (CreditCard cc : ccs) { 
     Assert.assertNotNull("CreditCard ID is null", cc.getIdCreditCard()); // FAIL: id is not generated. The database entry was not set. Added credit card is still transient... 
    } 

所以,在我的第二個測試,我ccNew仍然是其母公司更新後短暫的。

爲什麼它仍然是瞬態的?

子配置:

@JoinColumn(name = "id_user") 
@ManyToOne(optional = false) 
private User user; 

父配置:

@OneToMany(mappedBy = "user",cascade=javax.persistence.CascadeType.ALL) 
    private Set<CreditCard> creditCardCollection = new HashSet<>(); 
+0

?你使用'getEntityManager()。merge(value)'或'getEntityManager()。persist(value)'? –

+0

無..只是使用spring-jpa ...只需將註釋接口UserRepository進行轉換並將其自動裝配到類屬性中。 – user3810036

回答

1

你一個事務內部測試工作,這和你一起工作(U2:

@OneToMany(mappedBy = "user") 
@org.hibernate.annotations.Cascade(org.hibernate.annotations.CascadeType.ALL) 
private Set<CreditCard> creditCardCollection = new HashSet<>(); 

的家長已經嘗試過.getCreditCardCollection())與對象的值不與實體(保存尚未執行):

Assert.assertEquals(「User should have 2 credit cards。」, 1,u2.getCreditCardCollection()。size());

當您遍歷u2.getCreditCardCollection()並檢查id時,它們爲null,因爲插入和id生成僅在commit階段或flush/clear上下文中出現。

您需要調用saveAndFlush()而不是save()。

u2 = userRepository.findOne(u2.getIdLogin()); 

    CreditCard ccNew = new CreditCard("77777"); 

    u2.addCreditCard(ccNew);// bidirectional happens here inside 

    userRepository.saveAndFlush(u2); 

    Assert.assertEquals("User should have 2 credit cards.", 
      1, u2.getCreditCardCollection().size()); // PASS 

    Set<CreditCard> ccs = u2.getCreditCardCollection(); 
    for (CreditCard cc : ccs) { 
     Assert.assertNotNull("CreditCard ID is null", cc.getIdCreditCard()); 
    } 

from api;

void flush()刷新數據庫的所有掛起更改。

小號saveAndFlush(S實體) 保存一個實體,你在使用`userRepository.save`方法立即刷新變化

+0

令人驚歎。我一直在使用「... UserRepository擴展CrudRepository ...」。 CrudRepository沒有saveAndFlush,所以我認爲CrudRepository可以執行自動刷新..或類似的東西。 我將CrudRepository更改爲JpaRepository,並且運行正常。 勘誤表:你在哪裏閱讀「Assert.assertEquals(」用戶應該有2張信用卡...「現在讀爲」Assert.assertEquals(「用戶應該有1張信用卡」) 非常感謝 – user3810036