0

我真的在休眠会话中苦苦挣扎,在对修改后的会话对象进行查询时,我从来没有得到我期望的结果。我认为我所有的问题都是相关的。最后一个如下:

final Session iSession = AbstractDAO.getSessionFactory().openSession();
try {
    iSession.beginTransaction();
    MyObject iObject = DAOMyObject.getInstance().get(iSession,ObjectId);
    iObject.setQuantity(0); //previously the quantity was different from zero
    DAOMyObject.getInstance().update(iSession,iObject);
    DAOMyObject.getInstance().deleteObjectWithZeroQuantities(iSession);
    iSession.getTransaction().commit();
} catch (final Exception aException) {
    iSession.getTransaction().rollback();
    logger.error(aException.getMessage(), aException);
    throw aException;
} finally {
    iSession.close();
}

我没有得到的是为什么没有删除该对象,因为我在会话中对其进行了修改,所以进行删除的查询应该找到它。我在会话中创建具有增量 id 的对象时遇到了同样的问题,然后在提交之前在同一个会话中创建另一个对象,使用select max(id)+1. 但是会话每次都会让我获得相同数量的 id。

4

2 回答 2

0

你必须做一个session.flush().

您的对象更改仅在内存中,并且只有在刷新之前它们才会在数据库中持久存在。或者,您可以将 设置FlushModeCOMMIT,并且每次提交也将刷新。不过,我建议每次手动冲洗。

于 2013-06-29T22:25:56.457 回答
0

我的猜测是,DAOMyObject.getInstance().deleteObjectWithZeroQuantities(iSession)您在内部进行了查询数据库。但是,在数据库中 your iObject.getQuantity()is still !=0,因此不会被删除。

为什么您的查询会命中数据库而不是使用iObject缓存中的实例Session

这是因为查询必须检索 的所有实体quantity != 0并且您没有缓存所有实体。当您通过 IDSession检索实体时,通常会使用第一级缓存,并使用表单查询。向查询的子句添加更多条件会强制 Hibernate 访问数据库。select * from MyEntity where id=123456where

请注意,无论条件是select查询的一部分还是update/的一部分,都会发生同样的情况delete。Hibernate 仍然需要访问数据库iObject并将被删除。

那么如何绕过呢?

  1. 进行两次交易。第一个将改变iObject的数量。第二个将删除所有数量为零的实体。
  2. 如果您必须在同一个事务中进行这两项操作,您可以iObject在删除所有其他零数量实体之前/之后显式删除。请记住,您知道它的 ID。

1 ,即使你这样做,Hibernate 也无法知道它,因为其他一些Session可能刚刚插入了查询也应该选择的新实体

编辑:

另一种选择是session.flush()改变iObject's 的数量......实际上我认为就是问题所在。在里面DAOMyObject.getInstance().update(iSession,iObject),改变数量和调用后iSession.save(),你应该调用iSession.flush()。这会将更改写入数据库,以便后续查询可以看到它。这是正确的方法。

于 2013-06-29T22:18:58.110 回答