【问题标题】:Two JPA/Spring Data entities with identical structure but different tables结构相同但表不同的两个 JPA/Spring Data 实体
【发布时间】:2017-03-15 01:57:04
【问题描述】:

我的应用程序需要存储一组“暂存数据”,这些数据具有与另一个“真实”表相同的数据库结构,但在人工查看暂存数据的内容之前无法将其写入真实表。这些不仅仅是对真实表的添加,而是对它的更新(因此,换句话说,临时表中的值与真实表具有相同的主键,因为它们引用了相同的实体实例)。

我的方法是让两个 JPA @Entity 对象具有相同的结构(即字段、列名等)但存储在不同的表中并与 Spring CrudRepository 透视图完全分开处理(即在没有发生联合查询以合并两个表中的查询结果的时间)。但是,我想使用继承来使它们可以互换处理,这样我的应用程序就不会真正知道/关心它是否正在处理真实的暂存数据,因此我不必编写大量样板文件getter/setter/converter 代码。

所以,我现在拥有的基本上是三个类:

  1. BaseEntity 使用 @MappedSuperclass 注释并通过 @Id 注释标识公共 id 属性
  2. 一个 Identifier 实体扩展 BaseEntity 并为其他一些属性添加一些其他 getter/setter 并具有 @Inheritance(strategy=InheritanceType.TABLE_PER_CLASS) 注释
  3. 一个 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=?

...所以上面的查询同时获取 IdentifierStagingIdentifier 对象 - 这解释了错误。

那么,我正在尝试做的事情可能吗?

【问题讨论】:

  • 抱歉没有注意到异常

标签: java hibernate jpa inheritance spring-data-jpa


【解决方案1】:

我最终做的是如下重组我的课程:

  1. BaseEntity = 我的问题没有改变
  2. AbstractIdentifier = 扩展 BaseEntity 的新抽象类,带有 @MappedSuperclass 注释,Identifier 类的所有属性、getter、setter 等都已移入
  3. IdentifierStagingIdentifier 现在几乎是扩展 AbstractIdentifier 的存根类,但具有不同的 @Table 注释值和它们自己的 Spring Data 存储库

然后我编写了一些方法来在需要时在IdentifierStagingIdentifier 之间进行转换(尽管我不想这样做)并进行单元测试以确保这些方法的正确性

【讨论】:

    猜你喜欢
    • 2019-04-18
    • 1970-01-01
    • 2018-07-31
    • 1970-01-01
    • 2018-05-20
    • 2015-07-06
    • 1970-01-01
    • 1970-01-01
    • 2013-11-27
    相关资源
    最近更新 更多