初始化JPA2惰性关联的通用方法
因此,手头的问题是初始化“未知”实体的惰性集合,只要这些集合至少是通过名称已知的。这是我在JSF+Primefaces中构建通用DataTable->RecordDetails迷你框架的更广泛工作的一部分。初始化JPA2惰性关联的通用方法,jpa,jpa-2.0,lazy-loading,Jpa,Jpa 2.0,Lazy Loading,因此,手头的问题是初始化“未知”实体的惰性集合,只要这些集合至少是通过名称已知的。这是我在JSF+Primefaces中构建通用DataTable->RecordDetails迷你框架的更广泛工作的一部分。 因此,关联通常是惰性的,我需要加载它们的唯一时刻是当有人访问datatable中多条记录中的一条记录以查看/编辑它时。这里的问题是控制器是通用的,为此,我还使用了一个服务类来支持datatable的整个懒散加载和从details部分加载/保存记录。 到目前为止,我得到的是以下代码: publ
因此,关联通常是惰性的,我需要加载它们的唯一时刻是当有人访问datatable中多条记录中的一条记录以查看/编辑它时。这里的问题是控制器是通用的,为此,我还使用了一个服务类来支持datatable的整个懒散加载和从details部分加载/保存记录。 到目前为止,我得到的是以下代码:
public <T> T loadWithDetails(T record, String... associationsToInitialize) {
final PersistenceUnitUtil pu = em.getEntityManagerFactory().getPersistenceUnitUtil();
record = (T) em.find(record.getClass(), pu.getIdentifier(record));
for (String association : associationsToInitialize) {
try {
if (!pu.isLoaded(record, association)) {
loadAssociation(record, association);
}
} catch (..... non significant) {
e.printStackTrace(); // Nothing else to do
}
}
return record;
}
private <T> void loadAssociation(T record, String associationName) throws IntrospectionException, InvocationTargetException, IllegalAccessException, NoSuchFieldException {
BeanInfo info = Introspector.getBeanInfo(record.getClass(), Object.class);
PropertyDescriptor[] props = info.getPropertyDescriptors();
for (PropertyDescriptor pd : props) {
if (pd.getName().equals(associationName)) {
Method getter = pd.getReadMethod();
((Collection) getter.invoke(record)).size();
}
}
throw new NoSuchFieldException(associationName);
}
但我不喜欢强迫我的POJO为此实现一些接口的想法。使用反射解决方案,您将遭受此处详述的N+1效应: 您可以改为使用OpenSessionInView,您将受到N+1的影响,但不需要使用反射。如果使用此模式,您的事务将保持打开状态,直到事务结束,并且所有延迟关系都将毫无问题地加载
对于这种模式,您需要执行一个WebFilter来打开和关闭事务。是的,N+1效应在这里不是问题。正如我在问题中所描述的,基本上只有当我需要“详细信息”视图时才会加载关联,所以它不是N个查询,而是每个关联多加载1个查询。此外,JPA标准不允许您检索多个一对多关联,因此这是必需的。现在,关于OpenSessionInView,问题不是这个。它是关于在加载时以通用方式加载关联。应该强制加载这些关联的东西。你说“JPA标准不允许你检索多个一对多关联”,你在哪里看到的?我执行了几个查询,比如:“从Person p join fetch p.cars join fetch p.pets中选择p”。
Object getId();
void loadAssociations();