查找/合并JPA

时间:2015-06-11 21:09:49

标签: java multithreading hibernate jpa jta

我在我的方法上调用多线程时遇到问题,这些线程不能同时调用该方法,因为我在同步块中调用该方法,但每次线程都离开下一步进行的阻止。

被调用的方法使用我的实体ID(二进制)调用em.find(Class<T> entityClass, Object primaryKey),如果该对象存在于我的数据库中,我更新它并为了持久性目的而调用merge(),如果它没有'存在我用我的id创建一个新的,并调用merge()将其保存在我的数据库中,在我的情况下,我调用所有具有相同BinaryFile对象的线程,并且此BinaryFile的id不存在于我的数据库。

预期的行为是:

  1. 执行该方法的第一个线程创建对象并保存 它在数据库中。
  2. 剩余的线程不会创建新的 实例,但只需更新我的二进制对象的名称字段并调用 merge()在我的数据库中更新。
  3. 真正发生的事情:

    我得到了这个例外:

    org.hibernate.exception.ConstraintViolationException: ORA-00001: unique constraint (SCOM_DEV2.BINARY_ID_PK) violated
    
    org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:74)
    org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:47)
    org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:125)
    org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:110)
    org.hibernate.engine.jdbc.internal.proxy.AbstractStatementProxyHandler.continueInvocation(AbstractStatementProxyHandler.java:129)
    org.hibernate.engine.jdbc.internal.proxy.AbstractProxyHandler.invoke(AbstractProxyHandler.java:81)
    sun.proxy.$Proxy57.executeUpdate(Unknown Source)
    org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:56)
    org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2849)
    org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3290)
    org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:80)
    org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:272)
    org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:264)
    org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:186)
    org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:326)
    org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:52)
    org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1081)
    org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:315)
    org.hibernate.engine.transaction.synchronization.internal.SynchronizationCallbackCoordinatorImpl.beforeCompletion(SynchronizationCallbackCoordinatorImpl.java:104)
    org.hibernate.engine.transaction.synchronization.internal.RegisteredSynchronization.beforeCompletion(RegisteredSynchronization.java:53)
    com.arjuna.ats.internal.jta.resources.arjun
    

    调用方法的代码段

    CreateOrUpdate(BinaryFile binaryFile){
      Binary b = em.find(Binary.class, binarytmp.getId()); 
      if(b==null){
          b=new Binary();
          b.setID(id);
      }
      b.setName(binarytmp.getName());
      em.merge(b);
    
    }
    

    方法调用的代码段

    synchronized(binaryFile.getID().intern()){
       CreateOrUpdate(binaryFile);
    }
    

    我的实体的代码段

    @Entity
    @Table(name = "BINARY")
    public class Binary implements ScoBinary {
    
       /**
       * id field.
       */
      @Id
      @Column(name = "id")
      private String id;
    
      /**
       * name of the field
       */
      @Column(name = "name")
      private String name;
    
      public String getID(){
          return this.id;
      }
    
      public void setID(String){
          return this.id = id;
      }
    
      public Stirng getName(){
          return this.name;
      }
    
      public void setName(Stirng name){
          return this.name=name;
      }
    

    }

    当我用一个线程调用相同的方法时,一切都按预期运行,只有当我用多个线程调用方法时抛出此异常,我试图理解实际发生了什么,并且我发现当第一个线程执行时方法,它创建对象并持久化,但下一个线程在调用find()方法时获取null,尽管第一个线程已经调用merge()将其保存在我的数据库中,我试着调用{{1在我的em.flush()方法之后不确定对象是在从下一个线程调用find之前保存但是我仍然得到相同的结果,请你启发我。

0 个答案:

没有答案