【发布时间】:2017-03-15 01:57:04
【问题描述】:
我的应用程序需要存储一组“暂存数据”,这些数据具有与另一个“真实”表相同的数据库结构,但在人工查看暂存数据的内容之前无法将其写入真实表。这些不仅仅是对真实表的添加,而是对它的更新(因此,换句话说,临时表中的值与真实表具有相同的主键,因为它们引用了相同的实体实例)。
我的方法是让两个 JPA @Entity 对象具有相同的结构(即字段、列名等)但存储在不同的表中并与 Spring CrudRepository 透视图完全分开处理(即在没有发生联合查询以合并两个表中的查询结果的时间)。但是,我想使用继承来使它们可以互换处理,这样我的应用程序就不会真正知道/关心它是否正在处理真实的暂存数据,因此我不必编写大量样板文件getter/setter/converter 代码。
所以,我现在拥有的基本上是三个类:
-
BaseEntity使用@MappedSuperclass注释并通过@Id注释标识公共 id 属性 - 一个
Identifier实体扩展BaseEntity并为其他一些属性添加一些其他 getter/setter 并具有@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)注释 - 一个
StagingIdentifier实体扩展Identifier但具有不同的@Table注释值(并且不添加其他字段或方法)
在某些条件下,我想从本质上获取包含 StagingIdentifier 对象的表的内容并将其合并(即更新现有条目、添加新条目等)到包含标识符对象的表中。我正在使用 Envers 进行数据库审计,所以我真的不想做任何低级数据库的事情,这意味着我会失去任何可审计性。
当我使用CrudRepository<Identifier, Integer> 尝试保存 Identifier 对象列表时,同时还有 StagingIdentifier 对象保存到数据库(具有相同的 ID 值),当 Hibernate 尝试进行合并时,我得到以下异常:
org.springframework.orm.ObjectRetrievalFailureException: 对象 [id=null] 不是指定的子类 [com.domain.Identifier] : 给定对象的类与持久副本的类不匹配;
嵌套异常是 org.hibernate.WrongClassException: Object [id=null] 不是指定的子类 [com.domain.Identifier] : 给定对象的类与持久副本的类不匹配
当我查看 Hibernate 生成的 SQL 时,我看到:
调试 org.hibernate.SQL - 选择 identifier0_.id 作为 id1_10_0_, identifier0_.level 作为 level2_10_0_, identifier0_.name 作为 name3_10_0_, identifier0_.parent_id 作为 parent_i4_10_0_,identifier0_.clazz_ 作为 clazz_0_ from ( select id, level, name, parent_id, 0 as clazz_ from identifiers union all select id, level, name, parent_id, 1 as clazz_ 来自 staging_identifiers ) identifier0_ where identifier0_.id=?
...所以上面的查询同时获取 Identifier 和 StagingIdentifier 对象 - 这解释了错误。
那么,我正在尝试做的事情可能吗?
【问题讨论】:
-
抱歉没有注意到异常
标签: java hibernate jpa inheritance spring-data-jpa