2014-02-20 52 views
2

我有以下實體彈簧數據的JPA持續未引用實體

@Entity 
public class A { 
    @Id @GeneratedValue(strategy = GenerationType.AUTO) 
    private Long id; 
    // ... // 

    @ManyToOne(optional = false, fetch = FetchType.EAGER, cascade = { CascadeType.MERGE, CascadeType.PERSIST }) 
    @JoinColumn(name = "B_ID", nullable = false) 
    private B b; 
} 

@Entity 
public class B { 
    @Id @GeneratedValue(strategy = GenerationType.AUTO) 
    private Long id; 
    @Lob 
    private BitSet bitSet; 
    // ... // 

    @OneToMany(mappedBy = "b", cascade = CascadeType.ALL, fetch = FetchType.LAZY) 
    Set<A> as; 
} 

在我的代碼,我有以下序列中的代碼創建了一個A和分配一個新的B,後來當服務類去保存A,服務檢查數據庫中是否已經存在一個等價的B,如果是這樣,用數據庫中的A替換A的B.我知道有一點令人費解,但我們不希望創建A的代碼知道數據庫,而實際的代碼當然更復雜。

// Initialization code happens in one part 
A a = new A(); 
a.setB(new B()); // This new B get's saved even if it is replaced later! 

// Later a service is used to save the new A 
B repoB = bRepository.findOneByBitSet(a.getB().getBitSet()); 
if (repoB != null) { 
    a.setB(repoB); // Replace the temporary B 
} // Otherwise we will keep the original B. 
aRepository.save(a); 

好的,所以現在就是這個問題。 A的原始B被保存到數據庫,即使這個新的B沒有被任何對象引用。爲什麼Spring-Data會保存這個未被引用的B對象。

如果我直接使用Hibernate我可以像這樣不必要的B關於使用逐出(),但春的數據不公開這樣的電話:

// Later a service is used to save the new A 
B repoB = bRepository.findOneByBitSet(a.getB().getBitSet()); 
if (repoB != null) { 
    B unwantedB = a.getB(); 
    a.setB(repoB); // Replace the unwanted B 
    hibernate.evict(unwantedB); 
} // Otherwise we will keep the original B. 
aRepository.save(a); 

的一個更直接的例子情況是:

A a = new A(); 
B unwantedB = new B(); 
a.setB(unwantedB); 
B b = newB(); 
a.setB(b); 
repository.save(a); 

對象「A」應該有參考堅持反對「b」,但我認爲對象「unwantedB」不會被保存到數據庫。

回答

2

爲什麼Spring-Data會保存這個未被引用的B對象。

因爲你在你收藏協會

使用cascade = { CascadeType.MERGE, CascadeType.PERSIST })如果我直接使用Hibernate我可以使用像這樣不必要的B關於一個逐出() ,但是Spring的數據不揭露這樣的電話

這是正確的,所以考慮在關係中設置爲空B的字段。這意味着從A除去參考到B

a.setB(new B());a.setB(null);堅持之前如果沒有實體將被添加的持續時間

如果你不wanto存儲新實體B中刪除級聯選項。

+0

是集合上的級聯在那裏保存關聯的B,但後面的a.setB(repoB)應刪除對a.setB(new B())行中關聯的原始B的引用。這是newB()創建的對象,我不希望被保存。 –

+0

不刪除,因爲Cascade.REMOVE不存在,請考慮添加它 – Koitoer

+0

根據[@ManyToOne] [JPA/Hibernate Cascade.Remove用例(http://stackoverflow.com/questions/10620242/jpa-hibernate-cascade- remove-use-case-for-manytoone)和JPA 2.0規範是CascadeType.REMOVE僅適用於\ @OneToOne和\ @OneToMany。 –