【问题标题】:How to use Lazy Entity Loading in a Java EE Web Application?如何在 Java EE Web 应用程序中使用延迟实体加载?
【发布时间】:2011-09-10 21:24:48
【问题描述】:

在我的 Web 应用程序中,我加载了许多实体,以将它们显示在表格中。我可以单击每个表格行以获取有关特定实体的“详细信息”。

对我来说,很明显不加载 tableview 的“详细信息”,但只有当有人想要查看它时(单击一行)。

只是为这些字段设置(fetch = FetchType.LAZY) 不起作用,因为实体在获取后会分离,并且在我的 WebApp 中会有空值。

好的,接下来我要做的是通过将我的获取操作放入具有扩展 PersistenceContext 的 StatefulSessionBean 中来防止分离。

@PersistenceContext(unitName="unitname", type=PersistenceContextType.EXTENDED) private EntityManager em;

这可行,但也会产生奇怪的副作用(最值得注意的是某些页面重新加载时的 ConcurrentAccessExceptions,我可以通过设置一些 openjpa-property 来解决) Servlet 需要自己的 fetching-ejb,因为它们不与 SFSB 合作。 Atm 的大多数事情似乎都可以正常工作,但我希望这该死的很快就会成为粉丝。

我的问题是我是否走错了路。这一切对我来说似乎有点尴尬。当没有真正的对话并且用户可以随时离开而不触发某些@Remove-Method 时使用有状态bean。当用户早已离开时,必须在 Timeout 时关闭资源,从而导致许多打开未使用的 SFSB。

一般来说,延迟加载是一件非常简单的事情,但在 Java EE 环境中我不知道如何去做。最佳做法是什么?

谢谢。

更新

这就是我现在手动获取字段的方式

@SuppressWarnings("unchecked")
public <T extends BasicEntity> T loadLazyField(T entity, String field) throws NoSuchFieldException {
    if (!typeHasField(entity.getClass(), field)) {
        throw new NoSuchFieldException(entity.getClass().getSimpleName() + " has no field called " + field);
    }

    String queryString = String.format("SELECT x FROM %s x WHERE x = :entity LEFT JOIN FETCH x.%s", entity.getClass()
            .getSimpleName(), entity, field);
    Query q = em.createQuery(queryString);
    q.setParameter("entity", entity);
    return (T) q.getSingleResult();
}

@SuppressWarnings("unchecked")
public <T extends BasicEntity> T loadLazyFields(T entity, String[] fields) throws NoSuchFieldException {
    String queryString = String.format("SELECT x FROM %s x WHERE x = :entity", entity.getClass().getSimpleName());

    for (String field : fields) {
        if (!typeHasField(entity.getClass(), field)) {
            throw new NoSuchFieldException(entity.getClass().getSimpleName() + " has no field called " + field);
        }
        queryString += String.format(" LEFT JOIN FETCH x.%s", field);
    }
    Query q = em.createQuery(queryString);
    q.setParameter("entity", entity);
    return (T) q.getSingleResult();

}

private boolean typeHasField(Class<?> type, String field) {
    try {
        type.getDeclaredField(field);
        return true;
    } catch (NoSuchFieldException e) {
        return false;
    }
}

【问题讨论】:

    标签: java web-applications jpa jakarta-ee persistence


    【解决方案1】:

    您需要一种称为“在视图中打开会话”的设计模式,以在页面呈现阶段保持持久会话打开。此功能由 Seam 等集成框架提供。

    我不确定 JSF2 是否支持这一点,因为 Seam2 的许多功能都移到了 JavaEE6。无论如何,你应该看看 Seam(虽然很难用 Seam3 运行一些东西)。

    【讨论】:

    • 我很确定您将我指向完全正确的方向。但是我使用的是 Websphere AS 7.5(openJPA、ee5、jsf1.2),如果不进行大量配置(例如更改类加载器顺序),Hibernates OSiV 和 Seam 都不可用。我仍在尝试让 Seam 与我的 WAS 一起运行,如果这不起作用,可能需要手动实现该模式。 (如果我能在某个地方找到一个 HowTo 会很好)我​​也会在这里发布我的结果和解决方案。非常感谢您的提示。
    猜你喜欢
    • 2017-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-22
    • 2012-01-17
    • 2018-10-04
    • 2013-05-21
    • 2012-05-21
    相关资源
    最近更新 更多