我有以下實體彈簧數據的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」不會被保存到數據庫。
是集合上的級聯在那裏保存關聯的B,但後面的a.setB(repoB)應刪除對a.setB(new B())行中關聯的原始B的引用。這是newB()創建的對象,我不希望被保存。 –
不刪除,因爲Cascade.REMOVE不存在,請考慮添加它 – Koitoer
根據[@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。 –