2016-07-25 199 views
1

我有兩個實體類之間的下列雙向關係中刪除:級聯使用Spring數據JPA(雙向)

用戶

@Entity 
@Table(name = "USER") 
public class User { 
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "user") 
    @Cascade({CascadeType.REMOVE, CascadeType.SAVE_UPDATE}) 
    private Set<Book> books; 
} 

圖書

@Entity 
@Table(name = "BOOKS") 
public class Book { 
    @ManyToOne(optional = false) 
    @JoinColumns({ 
      @JoinColumn(name = "ID", referencedColumnName = "ID"), 
      @JoinColumn(name = "NAME", referencedColumnName = "NAME"), 
    }) 
    private User user; 

}

我想下來刪除User與級聯刪除與用戶相關的所有圖書。然而,當我使用一個Spring數據CrudRepository

myDAO.delete(String userId) // interface extending CrudRepository<User, UserPK> 

我越來越:

Caused by: org.hsqldb.HsqlException: integrity constraint violation: foreign key no action; FK_IN88FEHUXOOYQK0YE71USPIEP table: USER 

我試圖用orhpanRemoval,都挺CascadeTypesorg.hibernatejavax.persistence。我不想實現像@Query(Delete from User....)這樣的本機查詢我想知道異常說明外鍵沒有動作是否直接指定級聯選項。

+0

如何生成數據庫模式?爲什麼你從'Book'到'User'有'@Cascade(CascadeType.REMOVE)'?當然,當你刪除那本書(或者你)時,你不想刪除所有擁有'Book'的'用戶',因爲這就是級聯所要做的。 – manish

+0

嗨@manish,我已經從書中刪除級聯,仍然沒有改變。至於架構我沒有使用任何的SQL腳本,我創建LocalContainerEntityManagerFactoryBean與設置爲「更新」標誌「hibernate.hbm2ddl.auto」。 – ServerSideCat

回答

0

BookUser有多對一的關係。因此,Book表只需要一個列來捕獲User表的外鍵。

代碼:

@ManyToOne(optional = false) 
@JoinColumns({ 
     @JoinColumn(name = "ID", referencedColumnName = "ID"), 
     @JoinColumn(name = "NAME", referencedColumnName = "NAME"), 
}) 
private User user; 

應該簡單地:

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

當你使用Hibernate架構生成工具(HBM2DDL),外鍵約束產生如下:

ALTER TABLE 
    BOOK 
ADD CONSTRAINT 
    FK_IN88FEHUXOOYQK0YE71USPIEP 
FOREIGN KEY 
    (USER_ID) REFERENCES USER (ID) 
ON UPDATE NO ACTION 
ON DELETE NO ACTION; 

注意事項ON DELETE NO ACTION。這意味着,如果User實例被刪除,則Book實例不會發生與其關聯的實例(NO ACTION)。這實際上意味着User不應被允許刪除。

如果你想用UserUser被刪除,被刪除相關Book情況下,DDL應該是:

ALTER TABLE 
    BOOK 
ADD CONSTRAINT 
    FK_IN88FEHUXOOYQK0YE71USPIEP 
FOREIGN KEY 
    (USER_ID) REFERENCES USER (ID) 
ON UPDATE NO ACTION 
ON DELETE CASCADE; 

這可以通過添加特定於Hibernate的註解域模型生成:

class User { 
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "user") 
    @Cascade({CascadeType.REMOVE, CascadeType.SAVE_UPDATE}) 
    @OnDelete(OnDeleteAction.CASCADE) 
    private Set<Book> books; 
}