【问题标题】:Generic way to initialize a JPA 2 lazy association初始化 JPA 2 惰性关联的通用方法
【发布时间】:2014-08-19 11:19:41
【问题描述】:

因此,手头的问题是关于初始化“未知”实体的惰性集合,只要它们至少按名称已知即可。这是我在 JSF + Primefaces 中构建通用 DataTable -> RecordDetails 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();

但我不喜欢强迫我的 pojo 仅仅为此实现一些接口的想法。

【问题讨论】:

    标签: jpa jpa-2.0 lazy-loading


    【解决方案1】:

    使用反射解决方案,您将遭受此处详述的 N+1 效果:Solve Hibernate Lazy-Init issue with hibernate.enable_lazy_load_no_trans

    您可以改用 OpenSessionInView,您会受到 N+1 的影响,但您不需要使用反射。如果您使用此模式,您的事务将保持打开状态,直到事务结束,并且所有 LAZY 关系都将毫无问题地加载。

    对于这种模式,您需要做一个 WebFilter 来打开和关闭事务。

    【讨论】:

    • 是的,N+1 效应在这里不是问题。正如我在问题中所描述的,基本上只有当我需要“详细信息”视图时才会加载关联,所以它不会是 N 个查询,而是每个关联多 1 个。此外,无论如何,JPA 标准都不允许您检索多于一对多的关联,因此这是必需的。现在,关于 OpenSessionInView,问题不在于那个。这是关于在加载时以通用方式加载关联。应该强制加载这些关联的东西。
    • 您说“JPA 标准不允许您检索超过一对多关联”,您在哪里看到的?我已经执行了几个查询,例如:“select p from Person p join fetch p.cars join fetch p.pets”。
    猜你喜欢
    • 2012-09-28
    • 2013-11-24
    • 2014-05-28
    • 1970-01-01
    • 1970-01-01
    • 2021-11-21
    • 1970-01-01
    • 2013-05-22
    • 1970-01-01
    相关资源
    最近更新 更多