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>