我遇到了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是可持久的entites,它们都扩展了MappedSuperClassEntity,它用`@MappedSuperClass'注释。该类进一步继承了BaseEntity,它描述了TABLE_PER_CLASS继承策略。
我启用了hibernate stat收集器,发现hibernate使用Parent类的键存储子类对象。因此,在上面的例子中,它为Sub1 finder在缓存中存储如下数据:
14:17:03,941 DEBUG [org.hibernate.cache.TransactionalCache]缓存查找:com.abc.BaseEntity#10 14:17:03,943 DEBUG [org.hibernate.cache.TransactionalCache]缓存未命中 14:17:03,948 DEBUG [org.hibernate.cache.TransactionalCache]缓存:com.abc.BaseEntity#10
下次如果我为同一个id(10)查找Sub2,hibernate认为它在Cache中,因为它使用Parent Class作为键并返回Sub1对象,如下所示:
14:27:54,574 DEBUG [org.hibernate.cache.TransactionalCache]缓存查找:com.abc.BaseEntity#10 14:27:54,575 DEBUG [org.hibernate.cache.TransactionalCache]缓存命中
当您运行Sub1和Sub2的查找程序时,会发生这种情况:
entityManager.find(Sub1.class, id); //returns Sub1 object
entityManager.find(Sub2.class, id); //returns Sub1 object (PROBLEM HERE).
请帮我修复问题(我不想在这些调用之间清除缓存)
答案 0 :(得分:0)
问题是你在使用基本实体时没有意义。当您从基本实体继承而不仅仅是从映射的超类继承时,您不仅仅是继承字段和方法。您正在建立是关系。
一个有意义的例子如下:Car和Bike都继承了一个基本实体Vehicle。在这种情况下,Car实体是Vehicle实体。 Bike实体是Vehicle实体。
如果汽车的ID为42,那么自行车不也可以拥有ID 42,因为您将拥有两辆具有相同ID的车辆。想象一下具有与车辆的ManyToOne关联的驾驶员实体(即驾驶员驾驶车辆)。如果我将ID 42存储在驱动程序表的vehicle_id列中,则该ID 42必须唯一地识别车辆。它可能是一辆汽车,它可能是一辆自行车,而hibernate将会在两个表中看到,但它不能同时出现。
你违反了这种继承概念。不应使用Entity注释BaseEntity。它应该只是一个MappedSuperclass,它只允许继承字段和方法,但不会建立这种语义是关联。