【问题标题】:Hibernate query subtyped entity by natural-idHibernate 通过 natural-id 查询子类型实体
【发布时间】:2015-03-11 11:18:12
【问题描述】:

我使用 Hibernate 并希望通过实体标识符查询实体。但是,似乎不可能在子类型上使用自然 id。我有两个类 A 和 B,其中 B 扩展 A:

class A {
  long id;
}

class B extends A {
  String naturalId;
}

A 在 Hibernate 中使用自己的标识符进行映射。 B 被映射为连接的子类。但是,在 Hibernate 中无法映射 B 的自然标识符,因为 B 的映射是子类映射。

  • 为什么不能在子类B 上有一个自然标识符?请注意,我不希望 Hibernate 生成我的数据库架构,我只想拥有自然 id 以实现快速缓存命中。

  • 有没有办法/最佳实践在子类型上使用自然 id 以进行快速二级缓存查询?

    • 当自然 ID 在极少数情况下可能会更新(更改)并且必须在集群 Java EE 环境中维护缓存时,这是否仍然可行?

【问题讨论】:

    标签: java hibernate caching jpa natural-key


    【解决方案1】:
    1. NaturalId 仅对基类有意义,因为没有基类信息就无法检索子类。

      假设您可以使用 natural-id 映射基类和子类:

      class A {
        long id;
        String baseId;
      }
      
      class B extends A {
        String naturalId;
      }
      
      A a = session.bySimpleNaturalId( A.class ).load( "abc" );
      

      如果我们检索到的实体是 B 类型,则不清楚将使用哪个 natural-id 变体。

    2. 如果不获取基类信息,您将无法获取子类。因此,当您从缓存加载子类时,也会检索相关的基类信息。因此,您可以让基类存储自然 ID,或者简单地使用主键进行缓存。

    3. 您可以更新自然 ID,尽管 business key 应该是不可变的。对于可变 natural-ids,您需要使用mutable 属性。

    【讨论】:

    • 感谢您的回答。但是,我不明白为什么 Hibernate 不应该知道要使用哪个自然 ID,因为我们明确地给出了要查询的实体的类型。此外,很容易禁止定义与父类的自然 ID 具有相同签名的自然 ID。
    • 我认为这个决定是为了简单起见。从实现的角度来看,实现一些变通方法以从子类覆盖基类 natural-id 是可行的。您可以在 Hibernate JIRA 上针对这种情况提交 Hibernate 问题。
    【解决方案2】:

    根据13.3. Entity inheritance and second-level cache mapping:

    从 Hibernate ORM 5.3 开始,您现在可以覆盖基类 @Cacheable 或子类级别的@Cache 定义。

    因此您可能有机会重置B 上的缓存注释。
    我从未尝试过,所以请通过评论确认解决方案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-06-20
      • 2013-08-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-28
      • 1970-01-01
      • 2021-01-15
      相关资源
      最近更新 更多