我们的应用程序最初使用的是hibernate,但切换到eclipselink为我们提供了额外的缓存功能和性能提升。在eclipselink中,我们现在面临一个奇怪的问题,我们无法确定某个功能。
问题的症状是,在极少数情况下(在成功运行应用程序数小时,有时几天之后),当应用程序尝试访问实体时,它会检索实体但不检索相关实体,即使它们与渴望的关系有关。相反,实体的字段只是空的。
在尝试找到原因时,我们发现了一个与hibernate配合得很好的优化,但可能会导致EclipseLink出现问题。
优化包括创建代理实体,如果我们想要关联两个实体而不必加载不维护关系的实体,因此不会更新。
例如,我们希望将Resource与ResourceType相关联。我们有ResourceType的id,但不是整个实体。我们加载Resource并使用setter设置ResourceType,但是我们只是给它一个我们用以下方式创建的代理实体,而不是给它实际的ResourceType实体:
public <T extends PersistentRecord> T proxy(Class<T> clazz, String id) {
if(id == null) {
return null;
} else {
try {
T record = clazz.newInstance();
record.setId(id);
return record;
} catch (InstantiationException | IllegalAccessException e) {
throw new IllegalArgumentException("Failed to create proxy record.", e);
}
}
}
所有实体都继承自PersistentRecord,并且所有实体都有一个名为entityId的主键。此外,实体具有与eclipse的多租户特征一起使用的租户id字段,以在同一表中存储不同的租户数据。我们通过为每个租户设置单独的实体经理工厂并设置了
,同时使用eclipselink的第一级和第二级缓存<property name="eclipselink.multitenant.tenants-share-emf" value="false"/>
。
当使用代理ResourceType元素持久化上述Resource元素时,如果我在另一个上下文中从缓存中再次检索它,例如检索具有Resource作为字段的元素,我将得到什么?根据我们的发现,ResourceType元素经常被正确检索,但在极少数情况下,我们根本不会检索ResourceType。相反,我们只是得到null。要修复它,我们必须在打开EntityManager会话时访问ResourceType,然后导致加载ResourceType。
m.getResource().getResourceType()
这里,m是另一个使用我们之前存储的ResourceType引用Resource的实体。
如果代理元素是导致问题的优化,那么任何想法都会受到赞赏。欢迎任何其他相关信息。如果您需要更多信息,请不要犹豫。
谢谢!