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,它只允许继承字段和方法,但不建立这种语义是一个关联。
我遇到了 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,它只允许继承字段和方法,但不建立这种语义是一个关联。