我将尝试用JPA事务隔离级别来描述我的问题。
数据库结构:
Table1
-> 主键定义为日期('ddMMyyyy')Table2
-> 外键指向Table1
JPA(隔离级别:read_commited
)- 代码:
Query query = em.createQuery("from Table1 trd where trd.id = :d");
query.setParameter("d", date);
Table1 t = null;
try{
t = (Table1) query.getSingleResult();
}catch(javax.persistence.NoResultException e){
t = null;
}
if(t==null){
t=new Table1 (date);
em.persist(trd);
}
for(Table2 q:tables2){
q.setTable1(t);
em.merge(q);
}
检查过程如下:如果记录在数据库中不存在,则创建新的记录。如果系统只基于一个线程,该方法是完全正确的。否则可能会出现这种情况:
- 线程1:检查日期表示的实体是否存在于数据库中
- 线程2:执行完全相同的操作
他们两个都认为这样的记录尚不存在,因此添加新记录。在提交事务之前一切正常。第一个将被提交而没有任何异常,但第二个将引发与主键重复相关的异常。
除了将隔离级别更改为SERIALIZABLE
,还有什么办法可以保留这种情况吗?