所以,手头的问题是关于初始化"未知"的懒惰集合。实体,只要这些至少通过名称已知。这是我构建通用DataTable的更广泛努力的一部分 - > RecordDetails JSF + Primefaces中的miniframework。
因此,关联通常是懒惰的,并且我需要加载的唯一时刻是有人访问数据表中的多个记录以便查看/编辑它。这里的问题是控制器是通用的,为此我还只使用一个服务类支持整个LazyLoading用于数据表并从详细信息部分加载/保存记录。
到目前为止,我所拥有的是以下代码:
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);
}
问题是,有没有人开始任何类似的努力,或者有没有人知道以JPA方式初始化集合的更愉快的方式(不是特定于Hibernate / Eclipselink)而不涉及反射?
我能想到的另一个选择是强制所有实体用
Object getId();
void loadAssociations();
但我不喜欢强迫我的pojos为此实现一些界面。
答案 0 :(得分:1)
使用反射解决方案,您将受到此处详述的N + 1效果:Solve Hibernate Lazy-Init issue with hibernate.enable_lazy_load_no_trans
您可以使用OpenSessionInView,您将受到N + 1的影响,但您不需要使用反射。如果您使用此模式,您的交易将保持打开直到交易结束,并且所有LAZY关系将被加载而没有问题。
对于此模式,您需要执行一个WebFilter来打开和关闭事务。