我正在编写一个Web应用程序(Tomcat 7),因此没有JTA,并希望显示一个项目列表,包括与JSF页面中每个项目相关的任务。
有2个实体 - 包含任务集合的项目。从我的Managed Bean中,我调用一个方便的方法来检索所有活动的项目,然后在这个项目集合上迭代(ui:repeat),并希望显示每个项目的任务。当我尝试这样做时,我得到一个持久性异常,因为持久性上下文不再在范围内。
没有创建Project和Task的后台bean,也没有使用扩展上下文,我还有其他选项。
答案 0 :(得分:1)
经过一番思考和研究后,我回过头来正确描述我所处的情况,然后提供一种方法来解决问题。
发生的事情是Project实体将Tasks关系指定为Lazy Loaded。 JPA使用代理对象,在请求获取数据之前等待对集合的请求。这成为一个问题,因为我们试图在Persistent上下文分离实体后访问信息。
解决:强>
触发延迟加载 - 当Persistent Context仍在范围内时,调用集合getter和您希望数据所用的任何其他方法,这会触发数据被提取并添加实体。
使获取类型为Eager - 查看使用延迟加载的原因并将获取类型更改为急切。 “FetchType.EAGER”
获取联接 - 将关联添加为JP QL的一部分,以与查询一起提取。这样可以优化查询和在一次调用中加载的关联,同时仍然只返回单个实体。 “SELECT p FROM Project p LEFT JOIN FETCH p.tasks”
希望这有助于下一个人找到解决问题的方法。
答案 1 :(得分:0)
手动打开EntityManager
(使用工厂)并启动一个事务,然后提交它并关闭实体管理器。
但这不是一个好的选择 - 看看像CDI,Seam或Spring这样的东西来管理你的事务和会话(如果你不想使用EJB3)
答案 2 :(得分:0)
您的便捷方法是否也可以获取任务,例如通过在查询中加入该关联?如果任务已加载,则在访问集合时JPA不需要获取它们。
编辑:JPA 2.0 specification写入第4.4.5.3节:
FETCH JOIN允许获取关联或元素集合作为执行查询的副作用。
获取连接的语法是
fetch_join ::= [ LEFT [OUTER] | INNER ] JOIN FETCH join_association_path_expression
FETCH JOIN子句右侧引用的关联必须是从实体引用的关联或元素集合,或者作为查询结果返回的可嵌入对象。
不允许为FETCH JOIN子句右侧引用的对象指定标识变量,因此对隐式获取的实体或元素的引用不能出现在查询的其他位置。
以下查询返回一组部门。作为副作用,即使它们不是显式查询结果的一部分,也会检索这些部门的关联员工。由于获取连接而检索的对象的持久状态或关系字段或属性的初始化由该类的元数据确定 - 在此示例中为Employee实体 类。
SELECT d FROM Department d LEFT JOIN FETCH d.employees WHERE d.deptno = 1
提取连接具有与对应的内部或外部连接相同的连接语义,除了在连接操作的右侧指定的相关对象不在查询结果中返回或以其他方式在查询中引用。因此,例如,如果部门1有五名员工,则上述查询将返回对部门1实体的五个引用。
不得在子查询的FROM子句中使用FETCH JOIN结构。