为什么Hibernate Session会像这样行为

时间:2015-04-17 04:18:55

标签: java hibernate orm junit transactions

我有一个正在运行的 JUnit 测试代码测试我的hibernate数据库访问代码。对于每个数据库访问方法,我打开会话,并在finally块内的关闭。一切正常。

现在,我想打开一个会话,以进行多次访问,并让用户/来电/业务模块打开和关闭会话。

所以我的JUnit测试代码使用Session参数更改为以下内容。在每个数据库访问方法中,有一个 beginTransaction 提交 / 回滚

//session opened before here
System.out.println("step1, load back userAccount, expect success");
UserAccount user = DataMgmtMgrTest.dataMgr.findUserAccountByTblId(user2Id, errorInfo, session);
Assert.assertNotNull(user);
Assert.assertEquals(user.getUsername(), userName2);
Assert.assertEquals(errorInfo.getCode(), ErrorCode.No_ERROR);

System.out.println("step2, update userAccount, expect fail");
user.setUsername(userName3);
boolean rslt = DataMgmtMgrTest.dataMgr.updateUserAccount(user, errorInfo, session);
Assert.assertFalse(rslt);
Assert.assertNotEquals(errorInfo.getCode(), ErrorCode.No_ERROR);

System.out.println("step3, update userAccount, expect success");
user.setUsername(userName1);
rslt = DataMgmtMgrTest.dataMgr.updateUserAccount(user, errorInfo, session);
Assert.assertTrue(rslt);
Assert.assertEquals(errorInfo.getCode(), ErrorCode.No_ERROR);

System.out.println("step4, load back check, expect true");
UserAccount newUser = new UserAccount();
newUser.setUserAccountTblId(user2Id);
rslt = HibernateDBUtil.refreshFromDB(newUser, session, true, false, errorInfo);
Assert.assertTrue(rslt);
Assert.assertEquals(errorInfo.getCode(), ErrorCode.No_ERROR);
Assert.assertEquals(newUser.getUsername(),userName1);

//session closed after here

我的问题如下:

在第2步中,我尝试使用相同的备用键更新现有行(必须是唯一的),它按预期失败并且Hibernate完成回滚并且数据库也很好。

在步骤4之后, user.setUsername(userName1); 应将用户的userName更改为另一个值userName1,更新应该是成功完成。但结果是错误的。错误消息告诉我用户仍然具有步骤2的值。

我可以在步骤2中修改持久对象用户,但为什么不能在步骤3中进行修改?

如果我在步骤3之前关闭会话并重新打开下一行会话,那么它将起作用。

与步骤4类似,我创建了一个空的UserAccount, newUser ,并尝试将数据库值刷新到其中。但其 userName 为空。如果我在这些Assert.assertXXX()调用之前关闭会话,那么它将起作用。

这是否意味着我必须为每个数据库加入打开/关闭会话?

1 个答案:

答案 0 :(得分:1)

Hibernate会话应为discarded once you get an exception

  

如果Session抛出异常,则必须滚动事务   返回,会话被丢弃。会话的内部状态   发生异常后,可能与数据库不一致。

在测试中,一旦前一个会话生成异常,您需要使用新的会话。这模拟了现实生活中的行为,异常会中断当前的业务逻辑并通知用户出现了问题。然后,用户无论如何都会使用带有新Hibernate会话的新请求。