Java 如何使用JPA和Hibernate为关联的只读实体获取单个实例?
我有两个实体:Java 如何使用JPA和Hibernate为关联的只读实体获取单个实例?,java,spring,hibernate,spring-boot,orm,Java,Spring,Hibernate,Spring Boot,Orm,我有两个实体: @Entity @Immutable @Cacheable @Cache(region = "dosefrequency", usage = CacheConcurrencyStrategy.READ_ONLY) public class DoseFrequency{ ..... } @Entity public class PrescriptionDrug { ..... @ManyToOne(optional=false) @JoinCo
@Entity
@Immutable
@Cacheable
@Cache(region = "dosefrequency", usage = CacheConcurrencyStrategy.READ_ONLY)
public class DoseFrequency{
.....
}
@Entity
public class PrescriptionDrug {
.....
@ManyToOne(optional=false)
@JoinColumn(name="doseFrequency")
public DoseFrequency getDoseFrequency() {
return doseFrequency;
}
}
DoseFrequency是一个只读实体,PrescriptionDrug关联了一个DoseFrequency。我希望每次加载一个或多个处方药时,剂量顺序的实例不会重复
我知道DoseFrequency实例将缓存在hibernate的一级缓存中,但加载是在几个会话中完成的(这是一个web应用程序)。我使用了二级缓存,但该缓存不存储实例,只序列化实体
我使用Tuplizer在DoseFrequency中实现了这一行为,但我不知道是否有其他方法可以实现这一点
@Entity
@Immutable
@Cacheable
@Cache(region = "dosefrequency", usage = CacheConcurrencyStrategy.READ_ONLY)
@Tuplizer(impl=DoseFrequencyTuplizer.class)
public class DoseFrequency {
....
}
public class DoseFrequencyTuplizer extends PojoEntityTuplizer {
public DoseFrequencyTuplizer(EntityMetamodel entityMetamodel, PersistentClass mappedEntity) {
super(entityMetamodel, mappedEntity);
}
@Override
protected Instantiator buildInstantiator(EntityMetamodel entityMetamodel, PersistentClass persistentClass) {
return new DoseFrequencyInstantiator(DoseFrequency.class.getName(),entityMetamodel,persistentClass,null);
}
}
public class DoseFrequencyInstantiator implements Instantiator {
private final Class targetClass;
protected PojoEntityInstantiator pojoEntityInstantiator;
public DoseFrequencyInstantiator(String targetClassName, EntityMetamodel entityMetamodel,
PersistentClass persistentClass, ReflectionOptimizer.InstantiationOptimizer optimizer) {
try {
this.targetClass = Class.forName(targetClassName);
} catch (ClassNotFoundException e) {
throw new HibernateException(e);
}
pojoEntityInstantiator = new PojoEntityInstantiator(entityMetamodel, persistentClass, optimizer);
}
@Override
public Object instantiate(Serializable id) {
DoseFrequency df = MedereEMRCache.instance.findDoseFrequencyByID(Long.valueOf(id.toString()));
if (df == null) {
return pojoEntityInstantiator.instantiate(id);
}
return df;
}
@Override
public Object instantiate() {
return instantiate(null);
}
@Override
public boolean isInstance(Object object) {
try {
return targetClass.isInstance(object);
} catch (Throwable t) {
throw new HibernateException("could not get handle to entity as interface : " + t);
}
}
}
我知道这些实例将在应用程序的所有线程之间共享,但它们被视为只读,因此不应修改它们
这种方法正确吗
谢谢您也可以使用
LoadEventListener
始终为同一实例提供服务。然而,由于实体是不可变的,因此不需要此功能,因此,即使您有它的多个副本,它仍然是不可变的
而且,即使您实现了一个单例模式,它也只会在每个JVM中执行,所以我不明白您为什么要实现这个请求
仅根据
EntityManager
将实体视为单例。谢谢Vlad的回答。在VisualVM的采样器中,每次我加载inmutable对象时,它们的实例总是上升(当然GC会清理它们)。我希望避免像那些实体的单例一样实现。我将尝试LoadEventListener,再次感谢您