Java 具有Hibernate实体的奇怪Spring事务JUnit测试为空

Java 具有Hibernate实体的奇怪Spring事务JUnit测试为空,java,mysql,spring,hibernate,junit,Java,Mysql,Spring,Hibernate,Junit,我已经为这个问题烦恼了一段时间,终于想出了一个例子来说明发生了什么。希望其他人能知道发生了什么事 我有一个带有@Rollback(true)的Spring事务JUnit测试。测试被包装在一个HibernateTransaction中,该操作在单元测试结束时自动回滚数据库更改。这似乎是可行的,但是在这个奇怪的场景中,只有在我的单元测试中,这个@Transactional业务逻辑方法才会返回null @Test @Rollback(true) public void testObscureIssue

我已经为这个问题烦恼了一段时间,终于想出了一个例子来说明发生了什么。希望其他人能知道发生了什么事

我有一个带有
@Rollback(true)
的Spring事务JUnit测试。测试被包装在一个HibernateTransaction中,该操作在单元测试结束时自动回滚数据库更改。这似乎是可行的,但是在这个奇怪的场景中,只有在我的单元测试中,这个
@Transactional
业务逻辑方法才会返回null

@Test
@Rollback(true)
public void testObscureIssue() throws Exception {
    // Not important...
    l = createLeague();
    t1 = createTeam(l);
    User u = userBo.getUser(1L, false);

    Player player = TestUtils.getInstance().createTestData(Player.class, 1).get(0);
    player.setUser(u);
    player.setGender("M");
    player.setStartingActivityLevel(ActivityLevelEnum.Sedentary);
    playerBo.addOrUpdate(player);
    TeamPlayer tp = new TeamPlayer(t1, player);
    leagueStructureBo.addOrUpdate(tp);

    // This test will pass 10% of the time, seemingly random. Randomness only inside of unit test
    Team t = playerBo.getCurrentTeam(player.getPlayerID());
    if (t == null) throw new OutOfMemoryError("What is this... I don't even...");

    Team expected = playerBo.getCurrentTeam(player.getPlayerID());
    assertNotNull(expected);
    assertEquals(t1, expected);
}
因此,方法
playerBo.getCurrentTeam
在应用程序中始终正确返回,并且如果我在单元测试中的任何位置放置断点,则始终正确返回,然后一次一行地遍历代码。但是,当只运行单元测试而不进行调试时,大多数情况下都会失败

我想这里可能发生了一些赛车情况,但即使我放了一个
线程。sleep(400000L)语句调用此事务方法之前,它仍将失败

事务方法的代码:

@Override
@Transactional
public Team getCurrentTeam(long playerId) {
    String qry = "select t from Team as t inner join t.teamPlayers as tp " +
            "inner join tp.player as tpp where tpp.playerID = :playerId and (((current_timestamp() between tp.startDate and tp.endDate " +
            "and tp.endDate is not null) or (tp.endDate is null and current_timestamp() > tp.startDate)))";
    Object wtf = sessionFactory.getCurrentSession().createQuery(qry)
            .setParameter("playerId", new Long(playerId)).uniqueResult();
    return (Team)wtf;
}
事务属性都是Spring Hibernate4 TransactionManager的默认属性

您可以在代码示例中看到,我已经清楚地创建了这个团队实体,并且日志显示了为新记录生成的ID。我可以使用HQL直接通过该ID查询记录,它将返回,但是在这个事务性方法中,上面的这一个HQL查询仍然将返回null,除非我在调试模式下单步执行它,然后它才能工作

这是嵌套事务的问题吗?因为我的印象是,在回滚最外层的事务之前,不会回滚任何内容。为什么只有这一种方法?这是Hibernate4还是Spring3.1.1的bug?我使用的是MySQL InnoDB,这可能是MySQL InnoDB处理数据库事务的方式的问题吗


欢迎您提出任何关于其他尝试的建议,因为我在这里完全没有想法。

我猜问题是由于使用了
current\u timestamp()
。您可能创建了以now作为开始日期的TeamPlayer,如果设置断点,则当前时间戳系统性地小于开始日期,而如果不设置断点,则代码速度足够快(占时间的10%),使当前时间戳与团队成员的开始日期相等

现在看起来很明显,但这正是问题所在。谢谢你的帮助!