2016-02-13 45 views
0

我有一个包含一个@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]

我发现下面的链接问题谈几点参考:

我尝试了上面引用的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?

回答

1

CascadeOnDelete是一个简单的功能,指定你所指定的“关于级联删除”选项,在你的表格,让JPA不需要发出SQL删除相应的引用。这个SQL可以应用于任何引用,这就是CascadeOnDelete处理元素集合映射和任何其他参考映射的原因。

您的问题与数据库中lob比较限制有关,并且由于没有用于唯一标识元素集合行的ID字段,因此此限制会干扰EclipseLink尝试确保仅删除所需行的方式。如果您愿意在您的表格中添加订单栏,为什么不直接将EntityEvent设置为实体?或描述here,以便它使用外键和排序依据字段或作为主键来唯一地标识,而不是包括LOB字段行字段的任意组合,你可以自定义的EclipseLink。

+0

@CascadeOnDelete似乎是我的问题的完美解决方案,因为它提供了所有的链接embeddables从COMPANY_HISTORY表中删除时,本公司实体被删除的环境,并减少了执行此任务所需的SQL。然而,我很困惑,为什么这是必要的。当实体被删除时,必须删除嵌入。为什么当公司实体被删除时,EclipseLink不会简单地发送“删除COMPANY_HISTORY,其中company_id = <被删除公司的ID>”命令?为什么它比较所有的领域?感谢您的帮助! –

相关问题