这与Forcing a transaction to rollback on validation error类似的问题 场景是这样的: 用户编辑页面,事务设置为MANUAL,因此只有当我们调用flush时才会将其提交到数据库。现在用户想要取消更改。很容易,因为你还没有冲洗它。
现在考虑这种情况:用户编辑页面上有很多ajax。其中一些ajax回调需要数据库查询(例如,使用richFaces建议框等)。还进行了一些验证,需要进行数据库查找。问题是Hibernate会在您执行查询时自动发出刷新。因此用户不按下取消按钮时的保存按钮(这将刷新交易)。你现在做什么?
如果您不做任何操作,更改将写入数据库 - 而不是用户期望的内容。
您可以抛出使用
注释的异常@ApplicationException(rollback=true)
这会回滚交易。然后,您可以重定向到另一个页面。但是在这里我遇到了另一个问题,在某些页面上你重定向到你会得到一个懒惰的初始化异常。我指定了
<exception class="com.mycomp.BookingCancelException">
<end-conversation before-redirect="true"/>
<redirect view-id="/secure/Bookings.xhtml">
<message severity="INFO">#{messages['cancel.rollback']}</message>
</redirect>
</exception>
在pages.xml中,所以在我们进行重定向之前,对话应该结束。应该开始新的对话(使用新的交易),但似乎并非在所有情况下都会发生?为什么呢?
我在其他地方读过你可以简单地使用
Transaction.instance().rollback();
这是首选,因为您不必通过异常(当Seam处理异常时重定向总是需要很长时间),但问题是事务实际上没有回滚。我无法弄清楚为什么。如果我检查事务的状态,它表示它不处于回滚状态。
您如何最好地处理取消请求。在这种情况下,纯MANUAL刷新不起作用。您可以使用分离的实体,但页面包含多个链接的实体,因此这变得很混乱。
更新:我现在发现抛出ApplicationException并不会在所有情况下回滚事务。所以现在很困惑。
更新2 :当您拥有使用ajax更新值的页面时,回滚事务当然不起作用。每笔交易仅涵盖一个请求。所以如果你这样做,使用ajax请求进行5次编辑,回滚事务只会回滚上一次ajax请求的更改,而不是之前的4次更改。
因此解决方案实际上是使用冲洗模式MANUAL。
即使您指定MANUAL,也有一些事情会导致刷新。
您可能希望将MANUAL指定为components.xml
中的默认模式<core:manager concurrent-request-timeout="10000"
conversation-id-parameter="cid" conversation-timeout="600000" default-flush-mode="MANUAL"/>
答案 0 :(得分:0)
你试过吗
@Begin(flushMode=MANUAL)
someRandomValidationMethodHere(){ ... }
或设置
<core:manager conversation-timeout="120000" default-flush-mode="manual" />
在components.xml中?
答案 1 :(得分:0)
知道您可以使用属性bypassUpdates
告诉ajax验证组件不要刷新可能会有所帮助。这是一篇文章explaining。
答案 2 :(得分:0)
您可以管理交易并使用激活的按钮进行管理。
protected void doGet(HttpServletRequest request,
HttpServletResponse response, String butonPressed)
throws ServletException, IOException {
try {
// Begin unit of work
HibernateUtil.getSessionFactory()
.getCurrentSession().beginTransaction();
} catch (Exception ex) {
HibernateUtil.getSessionFactory()
.getCurrentSession().getTransaction().rollback();
throw new ServletException(ex);
}
finally
{
if ("SAVE".equals(butonPressed))
{
// Process request and render page...
// End unit of work
HibernateUtil.getSessionFactory()
.getCurrentSession().getTransaction().commit();
}
else
{
HibernateUtil.getSessionFactory()
.getCurrentSession().getTransaction().rollback();
}
}
}