【发布时间】:2016-05-24 15:45:28
【问题描述】:
我有以下包含 @Lob 的可嵌入类:
@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;
...
}
最后,我有许多实体类,它们包含一个名为 history 的属性,它是 EntityEvents 的列表。下面是一个例子:
@Entity
public class Company {
@NotNull
@ElementCollection
private List<EntityEvent> history;
...
}
当我在 GlassFish 4.1 中部署我的应用程序时,EclipseLink 会在我的 Derby 10.11.1.1 数据库中创建以下表:
- 公司
- COMPANY_HISTORY
当我创建一个新公司时,我的应用程序会创建一个 EntityEvent 并将 EntityEvent 添加到公司历史记录中。
当我修改公司时,我的应用程序会执行以下操作:
- 创建一个 EntityState 对象并将 xmlState 属性设置为未修改实体的 XML 表示形式。
- 创建一个包含上述 EntityState 的 EntityEvent 对象。
- 将 EntityEvent 添加到公司历史记录中。
问题是,当我尝试删除具有多个 EntityEvents 历史记录的实体时,我收到以下错误:
异常 [EclipseLink-4002] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.DatabaseException 内部异常: java.sql.SQLSyntaxErrorException: 'CLOB (UCS_BASIC)' 和不支持“CLOB (UCS_BASIC)”。类型必须具有可比性。字符串类型也必须有匹配的排序规则。如果排序规则不匹配,一个可能的解决方案是将操作数强制转换为默认排序规则(例如 SELECT tablename FROM sys.systables WHERE CAST(tablename AS VARCHAR(128)) = 'T1')
错误代码:20000 调用:DELETE FROM Company_HISTORY WHERE ((((((((((CHANGES = ?) AND (CLIENTTYPE = ?)) AND (CREATED = ?)) AND (IPADDRESS = ?)) AND (注意 = ?)) AND (TYPE = ?)) AND (VERSION = ?)) AND (XMLSTATE = ?)) AND (CREATER_ID = ?)) AND (Company_ID = ?)) bind => [10 个参数绑定]
我在以下链接中找到了对该问题的一些参考:
- 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 外键 (COMPANY_ID) 引用公司 (ID);
- 使用@CascadeOnDelete
- ALTER TABLE COMPANY_HISTORY 添加约束 CMPNYHISTORYCMPNYD 外键 (COMPANY_ID) 引用公司 (ID) 删除级联;
我的问题的解决方案让我感到惊讶,因为它似乎是重复的。我的理解是,当实体被删除时,JPA 应该删除与实体关联的所有可嵌入对象。 EclipseLink 具有以下链接中记录的非标准注释这一事实使我认为 EclipseLink 有一个错误,而不是修复该错误,而是创建了一个新的 @CascadeOnDelete 注释,以便该错误将被数据库级联删除功能所掩盖。
所以我的问题是为什么。为什么 EclipseLink 支持 @CascadeOnDelete 和 @ElementCollection?
【问题讨论】:
标签: jpa eclipselink cascade