我有一個包含一個@Lob以下嵌入類:爲什麼EclipseLink通過@ElementCollection支持@CascadeOnDelete?
@Embeddable
public class EntityState {
private Integer version;
@Lob
@XmlJavaTypeAdapter(CharArrayAdapter.class)
private char[] xmlState;
...
}
我也有包含上述嵌入以下嵌入類:
@Embeddable
public class EntityEvent {
@NotNull
private String note;
private EntityState entityState;
...
}
最後,我有一個包含許多實體類名爲歷史的屬性是EntityEvents的列表。下面是一個例子:
@Entity
public class Company {
@NotNull
@ElementCollection
private List<EntityEvent> history;
...
}
當我在GlassFish中4.1部署我的應用程序,創建的EclipseLink在我德比10.11.1.1數據庫下表:
- 公司
- COMPANY_HISTORY
當我創建一個新公司時,我的應用程序創建一個EntityEvent並將EntityEvent添加到公司歷史記錄。
當我修改公司,我的應用程序執行以下操作:
- 創建一個EntityState對象,並將xmlState屬性未修改實體的XML表示。
- 創建包含上述EntityState的EntityEvent對象。
- 將EntityEvent添加到公司歷史記錄。
的問題是,當我嘗試刪除具有多個EntityEvents我收到以下錯誤歷史的實體:
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.DatabaseException Internal Exception: java.sql.SQLSyntaxErrorException: Comparisons between 'CLOB (UCS_BASIC)' and 'CLOB (UCS_BASIC)' are not supported. Types must be comparable. String types must also have matching collation. If collation does not match, a possible solution is to cast operands to force them to the default collation (e.g. SELECT tablename FROM sys.systables WHERE CAST(tablename AS VARCHAR(128)) = 'T1')
Error Code: 20000 Call: DELETE FROM Company_HISTORY WHERE ((((((((((CHANGES = ?) AND (CLIENTTYPE = ?)) AND (CREATED = ?)) AND (IPADDRESS = ?)) AND (NOTE = ?)) AND (TYPE = ?)) AND (VERSION = ?)) AND (XMLSTATE = ?)) AND (CREATER_ID = ?)) AND (Company_ID = ?)) bind => [10 parameters bound]
我發現下面的鏈接問題談幾點參考:
- Hibernate - @ElementCollection - Strange delete/insert behavior
- http://eclipse.1072660.n5.nabble.com/Customizing-delete-calls-before-updating-a-ElementCollection-td7312.html
我嘗試了上面引用的stackoverflow文章中描述的@OrderColumn技術,但是這在EclipseLink中不起作用。
,對我的工作是對的EclipseLink非標準@CascadeOnDelete註釋添加到我的實體,如下所示的解決方案:
@Entity
public class Company {
@NotNull
@ElementCollection
@CascadeOnDelete
private List<EntityEvent> history;
...
}
執行這一變化,並重建我的數據庫後,我COMPANY_HISTORY表中有一個新的定義:
- 沒有@CascadeOnDelete
- ALTER TABLE COMPANY_HISTORY添加約束CMPNYHISTORYCMPNYD FO REIGN KEY(COMPANY_ID)參考公司(ID);
- 隨着@CascadeOnDelete
- ALTER TABLE COMPANY_HISTORY添加約束CMPNYHISTORYCMPNYD外鍵(COMPANY_ID)參考COMPANY(ID)ON DELETE CASCADE;
解決我的問題,讓我感到驚訝,因爲它似乎重複。我的理解是JPA應刪除實體時與實體關聯的所有可嵌入對象。是的EclipseLink有作爲記錄在以下鏈接這個非標準的註釋這一事實使我認爲的EclipseLink有缺陷,而不是固定的錯誤創造了一個新的@CascadeOnDelete註釋,這樣的bug將由數據庫級聯刪除功能被掩蓋。
所以我的問題是爲什麼。爲什麼EclipseLink通過@ElementCollection支持@CascadeOnDelete?
@CascadeOnDelete似乎是我的問題的完美解決方案,因爲它提供了所有的鏈接embeddables從COMPANY_HISTORY表中刪除時,本公司實體被刪除的環境,並減少了執行此任務所需的SQL。然而,我很困惑,爲什麼這是必要的。當實體被刪除時,必須刪除嵌入。爲什麼當公司實體被刪除時,EclipseLink不會簡單地發送「刪除COMPANY_HISTORY,其中company_id = <被刪除公司的ID>」命令?爲什麼它比較所有的領域?感謝您的幫助! –