2011-05-15 168 views
7

這個問題已被問過很多次,但我沒有看到一個令人滿意的答案,因此,我再次問它。在休眠級聯刪除的問題

想象一下以下情況:

public class User { 
    ... 

    @Cascade(value= {CascadeType.DELETE}) 
    @OneToMany(fetch = FetchType.LAZY) 
    @JoinColumn(name="followerId") 
    public List<LocationFollower> followedLocations; 

    ... 
} 

public class LocationFollower { 
    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    @Column(name = "id", nullable = false) 
    public Long id; 

    @ManyToOne 
    @JoinColumn(name="locationId") 
    public Location followedLocation; 

    @ManyToOne 
    @JoinColumn(name="followerId") 
    public User follower; 

    @Column(name = "followerSince") 
    public Timestamp followerSince; 
} 

public class Location { 
    ... 

    @Cascade(value = {CascadeType.DELETE}) 
    @OneToMany(fetch= FetchType.LAZY) 
    @JoinColumn(name="locationId") 
    public List<LocationFollower> followers; 

    ... 
} 

所有我想要的是刪除用戶。從邏輯上講,會假設所有連接用戶和位置的相關「關注者」條目都將被刪除。如果我刪除一個位置條目,則相同的假設應該保持在這種狀態。

實際發生的事情是,Hibernate試圖更新(?!?)擁有關注者的表,並且因爲相關實體(用戶或位置)已被髮送刪除,所以嘗試設置外鍵followerId爲null。這會引發異常,並破壞所有後續操作。

我得到的錯誤: 服務器出現未處理的故障。無法執行JDBC批處理更新; SQL [update locationstofollowers set followerId = null where followerId =?];約束[null];嵌套異常是org.hibernate.exception.ConstraintViolationException:無法執行JDBC批量更新

P.S.我聽說有另一個級聯選項DELETE_ORPHAN。這似乎已被廢棄,即使我也嘗試過,效果也是一樣的。

+0

非常好的問題。可悲的是,在這方面沒有多少討論。 – pavanlimo 2011-08-03 12:53:59

回答

1

既然你已經做了雙向映射,你必須從兩個地方刪除對象。這應該工作:

user.followedLocations.remove(aLocation); 
session.update(user); 
session.delete(aLocation); 
+0

這將創建耦合不會吧。 – xantrus 2011-05-15 17:17:55

+1

不是不行,映射已經以雙向的方式完成,這裏的問題是位置中的用戶對象已被映射爲非空值..這是造成問題的原因......問題也可以通過取消設置該字段不爲空... – 2011-05-16 15:40:20

+0

工程很好。謝謝Anantha!我希望@xantrus接受這個答案並將其關閉。 – pavanlimo 2011-08-04 04:01:13

0

應設置@JoinColumn(name = 「followerId」,插入=假,可更新= FALSE)