java - 如何在 Java EE Web 应用程序中使用延迟实体加载?

标签 java web-applications jpa jakarta-ee persistence

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

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

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

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

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

这可行,但也会产生奇怪的副作用(最显着的是某些页面重新加载时的 ConcurrentAccessExceptions,我可以通过设置一些 openjpa-property 来解决这个问题) Servlet 需要它们自己的 fetching-ejbs,因为它们不与 SFSB 合作。 Atm 的大多数事情似乎都可以正常工作,但我希望很快就会遇到麻烦。

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

最佳答案

您需要一种称为“在 View 中打开 session ”的设计模式,使持久性 session 在页面呈现阶段保持打开状态。此功能由 Seam 等集成框架提供。

我不确定 JSF2 是否支持此功能,因为 Seam2 的许多功能已移至 JavaEE6。无论如何,您应该看看 Seam(尽管很难让某些东西与 Seam3 一起运行)。

关于java - 如何在 Java EE Web 应用程序中使用延迟实体加载?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6279506/

相关文章:

java - 为什么java中的String不覆盖readObject?

javascript - 在浏览器上访问本地文件系统

java - 使用 Hibernate/Spring 生成数据库更新脚本

java - 如何在 Jenkins 上的 Gradle 构建中过滤测试而无需提交?

java - JavaFX GUI 是否对性能影响很大?

java - hibernate 锁定模式/锁定选项

java - JSF 身份验证

python - 为什么我会收到 TypeError : get() takes exactly 2 arguments (1 given)? Google App Engine

java - Oracle 序列 - 'increment by' 和 'cache'

java - JTA 与 PersistenceUnit