Hibernate 会话可用于查询但 lazyInit 无法在流程中工作
Hibernate session available for queries but lazyInit not working in flow
我正在使用 hibernate 4.3 和 SWF 2.4,在特定情况下遇到了导致 LazyInitializedException 的奇怪行为。
这里是流的配置:
<persistence-context />
<on-start>
<!-- attach enterprise to session if not provided -->
<evaluate expression="enterpriseInput ?: enterpriseDaoImpl.merge(externalContext.sessionMap.workingEnterprise)" result="flowScope.enterprise"/>
</on-start>
<view-state id="start" view="filiation/list">
<transition to="showBoardOrGoToList" on="save" />
</view-state>
<action-state id="showBoardOrGoToList">
<evaluate expression="flowController.displayBoard(event)" />
<transition on="yes" to="boardSubflow"/>
<transition on="no" to="something" />
</action-state>
<subflow-state id="boardSubflow" subflow="board">
<on-entry>
<evaluate expression="boardFlowController.initAdmins(enterprise)" result="flowScope.admins" />
</on-entry>
<input name="admins" value="flowScope.admins"/>
<output name="enterprise" value="flowScope.enterprise"/>
<transition on="save" to="end">
<evaluate expression="enterpriseDaoImpl.merge(enterprise)" result="flowScope.enterprise"/>
</transition>
<transition on="cancel" to="cancel"/>
</subflow-state>
...
当流量到达以下行时:
<evaluate expression="boardFlowController.initAdmins(enterprise)" result="flowScope.admins" />
它会触发 LazyInitializedException,方法 initAdmins() 基本上对列表的元素执行 Hibernate.initialize()。
for (Administrator administrator : enterprise.getAdministrators()) {
Hibernate.initialize(administrator);
}
如果就在该行之前调用 DAO 上的方法,它将毫无问题地执行数据库查询,因此这意味着休眠会话此时可用但是lazyInit 不工作。
但是,如果我在流程的 <on-start>
标记中调用 initAdmins(),它会起作用...
有效的流程配置:
<persistence-context />
<on-start>
<!-- attach enterprise to session if not provided -->
<evaluate expression="enterpriseInput ?: enterpriseDaoImpl.merge(externalContext.sessionMap.workingEnterprise)" result="flowScope.enterprise"/>
<evaluate expression="boardFlowController.initAdmins(enterprise)" result="flowScope.admins" />
</on-start>
<view-state id="start" view="filiation/list">
<transition to="showBoardOrGoToList" on="save" />
</view-state>
<action-state id="showBoardOrGoToList">
<evaluate expression="flowController.displayBoard(event)" />
<transition on="yes" to="boardSubflow"/>
<transition on="no" to="something" />
</action-state>
<subflow-state id="boardSubflow" subflow="board">
<input name="admins" value="flowScope.admins"/>
<output name="enterprise" value="flowScope.enterprise"/>
<transition on="save" to="end">
<evaluate expression="enterpriseDaoImpl.merge(enterprise)" result="flowScope.enterprise"/>
</transition>
<transition on="cancel" to="cancel"/>
</subflow-state>
...
问题是我只想在需要时初始化管理员,因为这是一项代价高昂的操作。
关于持久性上下文机制的信息很少,所以我找不到对此的解释。
对我来说,这真的像是一个错误。
有人可以突出显示我或解释为什么 lazyInit 在启动标签之外被破坏了吗?
谢谢
不确定是什么导致了这个问题。我以前经历过这种情况,我同意我认为这也是一个错误,但我认为不值得为此付出努力来解决问题,因为我们必须进入 WebFlow 代码(这样做了几次......不是乐趣需要几个小时)而且我总能找到一个简单且不打扰的工作(5 分钟或更短)。
尝试在以下转换中初始化管理员
<transition on="yes" to="boardSubflow"/>
看看它现在是否有效。 (就您的效率目标而言,与子流程内的启动效果相同)。
<transition on="yes" to="boardSubflow">
<evaluate expression="boardFlowController.initAdmins(enterprise)" result="flowScope.admins" />
</transition>
如果这不起作用,请尝试创建一个唯一目的是初始化管理员的操作状态。将此操作状态放在过渡 -> 子流调用的中间。确保在此操作状态的开始或退出时评估表达式。
<action-state id="initAdminsActionState">
<transition to="boardSubflow"/>
<on-exit>
<evaluate expression="boardFlowController.initAdmins(enterprise)" result="flowScope.admins" />
</on-exit>
</action-state>
我正在使用 hibernate 4.3 和 SWF 2.4,在特定情况下遇到了导致 LazyInitializedException 的奇怪行为。
这里是流的配置:
<persistence-context />
<on-start>
<!-- attach enterprise to session if not provided -->
<evaluate expression="enterpriseInput ?: enterpriseDaoImpl.merge(externalContext.sessionMap.workingEnterprise)" result="flowScope.enterprise"/>
</on-start>
<view-state id="start" view="filiation/list">
<transition to="showBoardOrGoToList" on="save" />
</view-state>
<action-state id="showBoardOrGoToList">
<evaluate expression="flowController.displayBoard(event)" />
<transition on="yes" to="boardSubflow"/>
<transition on="no" to="something" />
</action-state>
<subflow-state id="boardSubflow" subflow="board">
<on-entry>
<evaluate expression="boardFlowController.initAdmins(enterprise)" result="flowScope.admins" />
</on-entry>
<input name="admins" value="flowScope.admins"/>
<output name="enterprise" value="flowScope.enterprise"/>
<transition on="save" to="end">
<evaluate expression="enterpriseDaoImpl.merge(enterprise)" result="flowScope.enterprise"/>
</transition>
<transition on="cancel" to="cancel"/>
</subflow-state>
...
当流量到达以下行时:
<evaluate expression="boardFlowController.initAdmins(enterprise)" result="flowScope.admins" />
它会触发 LazyInitializedException,方法 initAdmins() 基本上对列表的元素执行 Hibernate.initialize()。
for (Administrator administrator : enterprise.getAdministrators()) {
Hibernate.initialize(administrator);
}
如果就在该行之前调用 DAO 上的方法,它将毫无问题地执行数据库查询,因此这意味着休眠会话此时可用但是lazyInit 不工作。
但是,如果我在流程的 <on-start>
标记中调用 initAdmins(),它会起作用...
有效的流程配置:
<persistence-context />
<on-start>
<!-- attach enterprise to session if not provided -->
<evaluate expression="enterpriseInput ?: enterpriseDaoImpl.merge(externalContext.sessionMap.workingEnterprise)" result="flowScope.enterprise"/>
<evaluate expression="boardFlowController.initAdmins(enterprise)" result="flowScope.admins" />
</on-start>
<view-state id="start" view="filiation/list">
<transition to="showBoardOrGoToList" on="save" />
</view-state>
<action-state id="showBoardOrGoToList">
<evaluate expression="flowController.displayBoard(event)" />
<transition on="yes" to="boardSubflow"/>
<transition on="no" to="something" />
</action-state>
<subflow-state id="boardSubflow" subflow="board">
<input name="admins" value="flowScope.admins"/>
<output name="enterprise" value="flowScope.enterprise"/>
<transition on="save" to="end">
<evaluate expression="enterpriseDaoImpl.merge(enterprise)" result="flowScope.enterprise"/>
</transition>
<transition on="cancel" to="cancel"/>
</subflow-state>
...
问题是我只想在需要时初始化管理员,因为这是一项代价高昂的操作。
关于持久性上下文机制的信息很少,所以我找不到对此的解释。
对我来说,这真的像是一个错误。
有人可以突出显示我或解释为什么 lazyInit 在启动标签之外被破坏了吗? 谢谢
不确定是什么导致了这个问题。我以前经历过这种情况,我同意我认为这也是一个错误,但我认为不值得为此付出努力来解决问题,因为我们必须进入 WebFlow 代码(这样做了几次......不是乐趣需要几个小时)而且我总能找到一个简单且不打扰的工作(5 分钟或更短)。
尝试在以下转换中初始化管理员
<transition on="yes" to="boardSubflow"/>
看看它现在是否有效。 (就您的效率目标而言,与子流程内的启动效果相同)。
<transition on="yes" to="boardSubflow">
<evaluate expression="boardFlowController.initAdmins(enterprise)" result="flowScope.admins" />
</transition>
如果这不起作用,请尝试创建一个唯一目的是初始化管理员的操作状态。将此操作状态放在过渡 -> 子流调用的中间。确保在此操作状态的开始或退出时评估表达式。
<action-state id="initAdminsActionState">
<transition to="boardSubflow"/>
<on-exit>
<evaluate expression="boardFlowController.initAdmins(enterprise)" result="flowScope.admins" />
</on-exit>
</action-state>