合并有时在 JPA Hibernate 中失败,但在同一事务中 PERSIST 有效

Posted

技术标签:

【中文标题】合并有时在 JPA Hibernate 中失败,但在同一事务中 PERSIST 有效【英文标题】:Merge fails sometime in JPA Hibernate but in same transaction PERSIST works 【发布时间】:2016-05-09 12:14:28 【问题描述】:

我已经按照我的理解经历了分离和附加的实体

User user=entityManager.find(User.class,1);

这里的用户是一个附加实体,对此的任何更改都将反映在数据库中

而分离的实体是新创建的实体,您可以使用合并而不是通过以下方式持久化@

 User userDetached=new User;
 user.setID(1);
 User userattahed=entityManger.merge(userDetached);
 userattahed.setName("cool");

这里的名字会反映在数据库中...如果我没记错的话

下面是我的代码,其中几次 (100/10) 合并不起作用,而坚持 100% 起作用...

            entityManager = JPAUtil.getEntityManager();
            UsersModel user=entityManager.find(UsersModel.class,getMobile_num());
            TrackModel track=new TracksModel();
            user.setBalance(user.getBalance().add(getAmount()));
            track.setMobile_Num(getMobile_num());
            track.setTransaction_Type(getTransaction_Type());
            track.setAmount(getAmount());
            entityManager.merge(user);//doesn't update few times 
            entityManager.persist(track); //works 100%
            JPAUtil.commit();  

【问题讨论】:

为什么要合并处于“托管”状态的实体?毫无意义,因为更新将是“已知的”。 @NeilStockton 我明白你的意思,但它有什么影响吗?? 这意味着你的调用是没有意义的(就像在不同的对象上使用持久化一样毫无意义)。如果您想调试您的问题,那么您可以查看日志以了解您选择的 JPA 提供程序。 【参考方案1】:

这行有点奇怪:

user.setBalance(user.getBalance().add(getAmount()));

这是您实际对用户进行的唯一更改。它有什么作用?什么是余额,添加有什么作用?在某些情况下可能根本没有变化,所以没有什么可存储的。

由于它无论如何都在会话中(它之前已加载),因此您无需调用任何东西来持久化它。最迟将在提交时刷新。

还请注意,当您调用persist of merge 或类似的方法时,更改不一定会刷新到数据库中。它可能会在提交时刷新。因此,在您决定刷新什么之前,请始终将事务运行到结束。

【讨论】:

感谢您的回复...Balance 属性是 BigDecimal 数据类型...。我需要将 Amount(getAmount) 添加到用户当前余额,所以我这样做 user.setBalance(user. getBalance().add(getAmount())); Amount 仍然可能是零?您如何确定“它是否有效”? 你看到 track.setAmount(getAmount());在数据库中获取 PERSIST 的行...告诉最后一笔交易 AMOUNT 是这个 track.getAmount【参考方案2】:

我遇到了类似的问题,即持续存在和合并失败;这是破坏的代码示例:

public MyType persistMyType(MyType myType) 
        MyType merge = em.merge(myType);
        em.persist(merge);
        return merge;

一旦我删除了合并,我就再也没有这个问题了。

PS:MyType 是 MyParent 的子对象,其注释如下:

@OneToMany(mappedBy="myParent", cascade = CascadeType.ALL, fetch = FetchType.EAGER)

我很高兴找到了解决方法,但我仍然不知道出了什么问题。我倾向于认为这个问题与脏物有关。 SQL 日志记录显示在持久化之前发生的大量 SELECT,这可以让您了解 hibernate 正在做什么。

【讨论】:

以上是关于合并有时在 JPA Hibernate 中失败,但在同一事务中 PERSIST 有效的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 JPA 和 Hibernate 设置默认查询超时?

jpa在save失败后service端catch不到异常原因(Hibernate的一级缓存)

Cascade保存子实体失败了JPA(Spring数据+ Hibernate)?

使用 JPA/Hibernate 将 Spring Boot 连接到 PostgreSql 数据库时失败

为啥hibernate乐观锁有时候成功有时失败?

JPA 不生成外键