1

我有这个测试设置,我正在使用 spring、derby 和 JPA,我想测试更新是否有效。

我真的不能以标准方式做到这一点,也就是说。创建实体对象,持久化,再次查找对象,更改对象中的某些字段,再次持久化,查找是否已更改。

这种方法的问题是我没有得到实体的新实例。它总是一样的。所以我不能真正判断更新是否正常工作,因为我总是在更改同一个对象,所以任何更改都会过早地反映出来。

如果我对某个对象进行更改而不将其与持久性上下文合并,然后尝试在该对象上进行查找,则更改已经存在于查找中,因为它始终使用同一个对象。

有什么方法可以让我失去上下文并进行真正的测试以确保更新正常工作?

这是我当前的代码:

@Test
public void canUpdate() {

    JsonTestEntity entity1 = new JsonTestEntity();
    JsonTestEntity entity2 = new JsonTestEntity();

    String message = "OmegaCV1";
    String message2 = "OmegaCV2";

    entity1.setMessage(message);
    entity2.setMessage(message2);

    em.persist(entity1);
    em.persist(entity2);

    em.flush();

    JsonTestEntity jsonTestEntity = em.find(JsonTestEntity.class, entity2.getId());

    assertNotNull("Could not find persisted entity", jsonTestEntity);
    assertEquals("Was not same entity", message2, jsonTestEntity.getMessage());

    String changeMessage = "Changed message";
    jsonTestEntity.setMessage(changeMessage);

    JsonTestEntity unChangedEntity = em.find(JsonTestEntity.class, entity2.getId());

    assertEquals("Message was prematurely changed", message2, unChangedEntity.getMessage());
    em.merge(jsonTestEntity);

    JsonTestEntity changedEntity = em.find(JsonTestEntity.class, entity2.getId());
    assertEquals("Message was not changed", changeMessage, changedEntity.getMessage());
}
4

4 回答 4

3

如果有可能禁用 EntityManager 的一级缓存 - 它会解决您的问题 :)

所以我有几个想法:

  1. 如果您的 EntityManager 是每笔交易 - 只需在不同的交易中执行persist()and 。find()

  2. 使用em.clear()- 它将分离所有托管实体。不要忘记em.flush()在此之前提交更改。

  3. 如果您使用 Hibernate - 在persist().flush()它之前清除 Session:

    会话会话 = em.unwrap(Session.class); session.flush(); session.clear();

  4. 您也可以使用重新加载实体的状态Session.refresh()

文档:

于 2013-10-03T13:35:49.207 回答
2

我在单元测试中看到的另一种替代方法是使用本机查询,它可以保证直接访问数据库。

Query query = em.createNativeQuery("select ... from ....");
List list = query.getResultList(); // or getSingleResult();

这将返回一个对象列表 []

于 2013-10-03T23:04:27.110 回答
0

让 JPA “哑巴”并再次读取数据库通常是非常令人沮丧的。

我想你可以通过调用得到你想要的EntityManager.refresh(entity2);

您还可以添加@Cacheable(false)到 JsonTestEntity 类。当然,这有一个很大的缺点,就是您必须稍后将其放回原处。

于 2013-10-03T13:55:35.910 回答
0

所以这里是如何解决它:

@Test
public void canUpdate() {

    JsonTestEntity entity1 = new JsonTestEntity();
    JsonTestEntity entity2 = new JsonTestEntity();

    String message = "OmegaCV1";
    String message2 = "OmegaCV2";

    entity1.setMessage(message);
    entity2.setMessage(message2);

    em.persist(entity1);
    em.persist(entity2);

    em.clear(); // Clears the entitymanager so jsonTestEntity != entity2

    JsonTestEntity jsonTestEntity = em.find(JsonTestEntity.class, entity2.getId());

    assertNotNull("Could not find persisted entity", jsonTestEntity);
    assertEquals("Was not same entity", message2, jsonTestEntity.getMessage());

    String changeMessage = "Changed message";
    jsonTestEntity.setMessage(changeMessage);

    em.clear(); // same reason as above, I cannot however use flush here as that would commit the changed message

    JsonTestEntity unChangedEntity = em.find(JsonTestEntity.class, entity2.getId());

    assertEquals("Message was prematurely changed", message2, unChangedEntity.getMessage());
    em.merge(jsonTestEntity);

    em.flush(); // since merge performs an update in this case, I need to flush to commit the update, after the flush --> unchangedEntity.getMessage().equals(jsonTestEntity.getMessage())
    em.clear(); // I clear again to get separate objects

    JsonTestEntity changedEntity = em.find(JsonTestEntity.class, entity2.getId());
    assertEquals("Message was not changed", changeMessage, changedEntity.getMessage());


}
于 2013-10-03T21:30:08.293 回答