Java 查找/合并JPA的多线程问题
我在方法上调用多线程时遇到了一个问题,这些线程不能同时调用该方法,因为我在一个同步块中调用该方法,但每次线程离开该块时,下一步都会继续 被调用的方法调用em.findClass entityClass,Object primaryKey,ID为我的EntityBinary,如果该对象存在于我的数据库中,我会更新该对象并调用merge以实现持久性,如果该对象不存在,我会使用我的ID创建一个新对象并调用merge将其保存在我的数据库中,在我的例子中,我使用同一个BinaryFile对象调用所有线程,而这个BinaryFile的id在我的数据库中不存在 预期的行为是: 执行方法的第一个线程创建对象并保存 它在数据库中。 其余线程将不会创建新线程 实例,但只需更新二进制对象的名称字段并调用 合并以更新我的数据库。 实际发生的情况: 我得到一个例外:Java 查找/合并JPA的多线程问题,java,multithreading,hibernate,jpa,jta,Java,Multithreading,Hibernate,Jpa,Jta,我在方法上调用多线程时遇到了一个问题,这些线程不能同时调用该方法,因为我在一个同步块中调用该方法,但每次线程离开该块时,下一步都会继续 被调用的方法调用em.findClass entityClass,Object primaryKey,ID为我的EntityBinary,如果该对象存在于我的数据库中,我会更新该对象并调用merge以实现持久性,如果该对象不存在,我会使用我的ID创建一个新对象并调用merge将其保存在我的数据库中,在我的例子中,我使用同一个BinaryFile对象调用所有线程,
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;
}