我有一个包含一个@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>”命令?为什么它比较所有的领域?感谢您的帮助! –