Java 查找/合并JPA的多线程问题

Java 查找/合并JPA的多线程问题,java,multithreading,hibernate,jpa,jta,Java,Multithreading,Hibernate,Jpa,Jta,我在方法上调用多线程时遇到了一个问题,这些线程不能同时调用该方法,因为我在一个同步块中调用该方法,但每次线程离开该块时,下一步都会继续 被调用的方法调用em.findClass entityClass,Object primaryKey,ID为我的EntityBinary,如果该对象存在于我的数据库中,我会更新该对象并调用merge以实现持久性,如果该对象不存在,我会使用我的ID创建一个新对象并调用merge将其保存在我的数据库中,在我的例子中,我使用同一个BinaryFile对象调用所有线程,

我在方法上调用多线程时遇到了一个问题,这些线程不能同时调用该方法,因为我在一个同步块中调用该方法,但每次线程离开该块时,下一步都会继续

被调用的方法调用em.findClass entityClass,Object primaryKey,ID为我的EntityBinary,如果该对象存在于我的数据库中,我会更新该对象并调用merge以实现持久性,如果该对象不存在,我会使用我的ID创建一个新对象并调用merge将其保存在我的数据库中,在我的例子中,我使用同一个BinaryFile对象调用所有线程,而这个BinaryFile的id在我的数据库中不存在

预期的行为是:

执行方法的第一个线程创建对象并保存 它在数据库中。 其余线程将不会创建新线程 实例,但只需更新二进制对象的名称字段并调用 合并以更新我的数据库。 实际发生的情况:

我得到一个例外:

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
被调用方法的代码段

方法调用的代码段

我的实体的代码片段

}


当我用一个线程调用同一个方法时,一切都按照预期进行,只有当我用几个线程调用该方法时才会引发此异常,我试图了解实际发生的情况,我发现当第一个线程执行该方法时,它会创建对象并将其持久化,但是下一个线程在调用find方法时得到一个null,虽然第一个线程已经调用merge将其保存在我的数据库中,但我尝试在我的merge方法之后调用em.flush,以确定在从下一个线程调用find之前是否保存了对象,但我仍然得到相同的结果,您能否告诉我。

如何配置事务?调用flush会将更改写入数据库,但取决于事务隔离级别,在提交此事务之前,其他线程可能看不到更改:提交与flush不同。我使用的是JTA事务类型:,这是否回答了您的问题?
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;
  }