【问题标题】:Hibernate: Commiting MariaDB via JPAHibernate:通过 JPA 提交 MariaDB
【发布时间】:2016-02-08 17:27:46
【问题描述】:

我正在尝试编写一个应该提供宁静界面的小型应用程序。这在它自己的作品中与当前的hibernate版本相对较好。

尝试测试时,我的服务器端代码修改如下:

EntityManager manager = // [...]
manager.getTransaction.begin();
AEntity entity1 = manager.find(AEntity.class, 4711);

entity1.setSomething("whatever");
manager.merge(entity1);

manager.getTransaction.commit();
manager.close();

通常这应该有效。但是在使用 JUnit 进行测试时却没有。

EntityManager manager = // [...]
// insert some test data

Response r1 = target(url).request().put(someAEntityChangeInfo);
assertEquals(200, r1.getStatus());
manager.refresh(mAEntity);
assertEquals("whatever", mAEntity.getSomething()); // was set and commited on server-side

最后一个断言失败,说mAEntity(应该更新)包含旧数据。我也不确定这种行为是否可能是一种竞争条件,因为有一次(但只有一次)断言是可以的。

在断言之前如何确保数据真正被提交?

使用 MariaDB、MariaDB Connector/J、Hibernate 5.0.7 和 Jersey 2.22.1。

【问题讨论】:

  • 你为什么要开始一个事务,在事务中什么都没有的时候调用flush并提交它?!
  • 我需要同步EntityManager的“缓存”。对于正常使用,我在服务器端打开一个 EntityManager。为了验证书面数据,我需要在我的测试中使用第二个 EntityManager。如果在测试端不刷新(仅在事务中可能使用自身),实体将使用旧数据进行刷新。至少我是这么认为的。我错了吗?
  • 一个空事务将什么都不做,并且无论如何都会在提交中完成刷新,因此该行也没有任何价值。没有“同步”要做(并不是说 L1 缓存会“同步”任何东西)。我也没有在您的帖子中看到第一笔交易和第二笔交易之间的关系
  • 好的。我删除了它,没有效果。我想在我的测试中检查服务器端更改的实体,但它仍然包含(刷新后)旧数据。在数据库中,还有旧数据 -> 服务器端的提交似乎对数据库没有任何作用(但它应该写入更改)。

标签: hibernate jpa jersey mariadb jersey-test-framework


【解决方案1】:

问题似乎是刷新事务和连接隔离的混合。

解决这个问题:

  • 将刷新模式设置为提交:manager.setFlushMode(FlushModeType.COMMIT);
  • 将测试连接隔离设置为READ_COMMITED,以便测试连接能够看到测试代码对另一个EntityManager所做的更改。对于生产来说,更高的隔离度会更好。 JPA 属性:<property name="hibernate.connection.isolation" value="2" />

还有hibernate的autocommit属性。设置为 false 以更好地控制行为。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多