JPA Hibernate merge 执行插入而非更新

17

我有一个简单的测试,我试图更新对象,但是合并似乎执行插入而不是更新。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:spring/app-context.xml","classpath:spring/testdb-context.xml"})
public class UserJPATest {
@Test
public void testUpdate() throws Exception {
    System.out.println("update");

    User entity = ObjectManager.USER_DAO.findById(3L);
    entity.setUsername("harryUpdate");

    ObjectManager.USER_DAO.update(entity);

    User selEntity = ObjectManager.USER_DAO.findById(3L);
    Assert.assertEquals(entity.getUsername(),selEntity.getUsername());
}

这是我的更新方法

@Override
@Transactional(propagation= Propagation.REQUIRES_NEW)
public T update(T entity) throws Exception {
    try {
        T merged = entityManager.merge(entity);
        return merged;
    } catch (Exception e) {
        e.printStackTrace();
        throw new Exception(e);
    }
}

更新代码

@Override
@Transactional(propagation= Propagation.REQUIRES_NEW)
public T update(T entity) throws Exception {
    try {
        T merged = null;
        BaseEntity baseEntity = null;
        if(entity instanceof BaseEntity){
            baseEntity = (BaseEntity)entity;
            merged = entityManager.find(entityClass, baseEntity.getId());
        }
        merged = entityManager.merge(entity);
        entityManager.flush();
        return merged;
    } catch (Exception e) {
        e.printStackTrace();
        throw new Exception(e);
    }
}

现在我遇到了以下错误:无法提交JPA事务;嵌套异常为javax.persistence.RollbackException:事务标记为rollbackOnly。

你如何确定它执行了插入操作? - axtavt
我不是特别喜欢 REQUIRES_NEW 传播机制,因为你可能会在一个事务中创建实体,然后在另一个不知道原始实体的事务中执行“合并或更新”操作。 - Augusto
我检查了日志,它试图进行插入操作。 - user373201
给Augusto...这很有道理。我改了代码,但现在我得到了标记为rollbackonly的事务。我已经更新了上面的代码。 - user373201
2个回答

29

我有一个版本列,但在插入种子数据时没有设置。因此,在更新和删除方面都会出现问题。


谢谢user373201,我一直在苦苦挣扎,然后看到了你的建议,一旦我更改了版本,它就开始按照预期工作了。谢谢。 - Richipal
版本列,哪一个?我也遇到了同样的问题,我已经设置了数据库的所有列,但它仍然会插入记录而不是更新。请帮忙。 - Mufrah
4
我知道这是一个旧的帖子,但即使在今天...许多开发人员仍然面临着同样的问题...所以我发布了一个可能导致这个问题的原因...http://www.programmingforfuture.com/2011/02/hibernate-merge-may-insert-new-record.html - Manan Shah
这个回答发布已经超过10年了,但它仍然很有帮助。 - wax

0

Merge 只有在数据库中找到 ID 时才会更新行,因此如果您创建了一个新对象并忘记将其 ID 设置为所需行的相同 ID,则会尝试插入新对象。如果您的数据库表没有任何唯一字段,则可能会成功插入,因为不会出现 SQL 错误。

一旦我使用该行的 ID 设置了新对象,我就能够更新所需的行。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接