【问题标题】:JPA: check whether an entity object has been persisted or notJPA:检查实体对象是否已持久化
【发布时间】:2013-04-12 02:27:29
【问题描述】:

有没有通用的方法可以

 if(entity is persisted before){
     entity = entity.merge();
 }else{
     entity.persist();
 }

那么包含上述逻辑的方法到处都是安全的吗?

【问题讨论】:

  • 为什么需要它? merge() 已执行此检查。
  • @axtavt 谢谢。所以如果实体从未持久化,那么merge() 会持久化实体吗?否则合并实体并返回合并后的副本?
  • 是的,但是对于瞬态对象,它也会返回持久副本,而不是保留原始对象。

标签: java jakarta-ee jpa ejb


【解决方案1】:

如果您需要知道对象是否已经在持久化上下文中,您应该使用EntityManagercontains 方法。

只有EntityManager可以告诉你实体是否持久化,实体没有这样的信息。

你可以在这里查看contains method的javadoc。

if (!em.contains(entity)) {
  em.persist(entity);
} else {
  em.merge(entity);
}

【讨论】:

  • 当然,这应该是 if (!em.contains(entity)) ?否则,您将保留一个已经“包含”在 em 中的实体...
  • 如果持久化的实体被分离,这个方法将不起作用。
  • 正如@Sunnyday 所说,这个答案具有误导性。根据 JPA 规范,EntityManagercontains(..) 方法未定义为 Entity 的实际 DB 状态的查找方法,而是作为持久性上下文中的查找。在我的回答中可以找到进一步的说明:stackoverflow.com/a/49114622/2849346
【解决方案2】:

要检查当前 PersistenceContext 是否已持久化实体对象,您可以使用 EntityManager 方法contains(Object entity)

【讨论】:

    【解决方案3】:

    也许为时已晚,但这是我的发现! 如果您有一个具有生成值的实体,则可以使用它来检查该实体是否已经在 DB 中,假设您没有手动修改此值。

    @Entity
    public class MyEntity {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Column(name = "id")
        private Integer id;
       
        // getter...
    }
    
    public class Main {
        public static void main() {
            MyEntity myEntity1 = new MyEntity();
            MyEntity myEntity2 = em.find(MyEntity.class, 4);
            em.detach(myEntity2); // or em.close()
    
            // other stuff and modifications
    
            // begin transaction
            persistEntity(myEntity1); // will use persist()
            persistEntity(myEntity2); // will use merge()
            // commit transaction
    
        }
    
        // This will manage correctly entities in different state
        public void persistEntity(MyEtity entity) {
            if (myEntity.getId() != null) em.merge(entity);
            else em.persist(entity);
        }
    }
    

    在这种情况下使用 em.contains(entity) 会失败:

    public static void main(){
        MyEntity myEntity = em.find(MyEntity.class, 5);
        
        em.detach(myEntity); // or em.close()
      
        // We are going to execute persist() because the entity is detached
        if (!em.contains(myEntity)) 
            // This call will produce an exception org.hibernate.PersistentObjectException
            em.persist(myEntity);
        else 
            em.merge(myEntity);
    }
    

    尝试实现 OP 的目标是出于性能原因。您当然可以使用 em.merge() 代替 em.persist(),但并非没有成本。

    em.merge() 的调用正在尝试使用 SELECT 查询从数据库中检索现有实体并对其进行更新。因此,如果实体从未被持久化,这将浪费一些 CPU 周期。另一方面,em.persist() 只会产生一个 INSERT 查询。

    【讨论】:

      猜你喜欢
      • 2018-03-18
      • 2017-10-10
      • 1970-01-01
      • 2011-11-28
      • 2017-06-22
      • 1970-01-01
      • 1970-01-01
      • 2011-07-16
      • 2015-11-02
      相关资源
      最近更新 更多