JPA EntityManager finder 方法返回其他子 class 对象

JPA EntityManager finder method returning other sub class object

我遇到了 JPA EntityManager finder 方法的问题。 JPA 实体正在使用如下继承结构:

//Need to persist this table to database
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL)
@Table(name="Table1")
public class BaseEntity implements Serializable {
    @Id
    @Column(name="PRIMARY_ID")
    private long id;
    private String field1;
    .......
}

//This table will NOT persist and has parameters only for Sub classs
    @MappedSuperclass
    public abstract class MappedSuperClassEntity extends BaseEntity  {

      private String field2;
      private String field3;
      ........
    }

//This sub class is persisted and inherits fields form above class including Primary Key using TABLE_PER_CLASS strategy defined in BaseEntity
    @Entity
    @Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL)
    @Table(name="SubTable1")
    public class Sub1 extends MappedSuperClassEntity {
      private String field4;
      private String field5;
      ...............     
    }

//This sub class is persisted and inherits fields form above class including Primary Key using TABLE_PER_CLASS strategy defined in BaseEntity   
    @Entity
    @Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL)
    @Table(name="SubTable2")
    public class Sub2 extends MappedSuperClassEntity {
      private String field4;
      private String field5;
      ..............      
    }

如您所见,Sub1 和 Sub2 是可持久化的实体,它们都扩展了 MappedSuperClassEntity,后者用“@MappedSuperClass”注释。这个class进一步继承了描述了TABLE_PER_CLASS继承策略的BaseEntity。

我启用了休眠统计收集器,发现休眠正在使用父 class 的键存储子 class 对象。所以在上面的例子中,它在缓存中为 Sub1 finder 存储如下数据:

14:17:03,941 调试 [org.hibernate.cache.TransactionalCache] 缓存查找:com.abc.BaseEntity#10 14:17:03,943 DEBUG [org.hibernate.cache.TransactionalCache] 缓存未命中 14:17:03,948 调试 [org.hibernate.cache.TransactionalCache] 缓存:com.abc.BaseEntity#10

下次如果我为同一 ID (10) 查找 Sub2,hibernate 认为它在缓存中,因为它使用 Parent Class 作为键和 returns Sub1 对象,如下所示:

14:27:54,574 调试 [org.hibernate.cache.TransactionalCache] 缓存查找:com.abc.BaseEntity#10 14:27:54,575 调试 [org.hibernate.cache.TransactionalCache] 缓存命中

当您 运行 Sub1 和 Sub2 的发现者时,就会发生这种情况:

entityManager.find(Sub1.class, id);   //returns Sub1 object
entityManager.find(Sub2.class, id);   //returns Sub1 object (PROBLEM HERE).

请帮我解决这个问题(我不想在这些调用之间清除缓存)

问题是您在使用基础实体时没有任何意义。当您从基实体继承时,而不仅仅是从映射的超类继承时,您不仅仅是在继承字段和方法。您正在建立 关系。

下面是一个有意义的示例:Car 和 Bike 都继承了一个基础实体 Vehicle。在这种情况下,Car 实体是 Vehicle 实体。 Bike 实体是 Vehicle 实体。

如果汽车的 ID 为 42,那么自行车可能不会也有 ID 42,因为两辆车的 ID 相同。想象一个 Driver 实体与车辆有 ManyToOne 关联(即 driver 驾驶车辆)。如果我将 ID 42 存储在 driver table 的 vehicle_id 列中,则此 ID 42 必须唯一标识车辆。它可以是汽车,也可以是自行车,hibernate 会在两个 table 中查找,但不能同时在两者中查找。

你违反了这个继承概念。 BaseEntity 不应使用 Entity 进行注释。它应该只是一个 MappedSuperclass,它只允许继承字段和方法,但不建立这种语义是一个关联。