我在使用mybatis运行oracle函数时遇到java.sql.SQLIntegrityConstraintViolationException:ORA-00001:唯一约束错误。我将spring事务配置为在Serializable中运行,并且readOnly为false。下面是我的mapper类
public interface ILockMapper {
@Transactional(isolation=Isolation.SERIALIZABLE, readOnly=false)
String aquireLock(final SpInOutFields input);
@Transactional(isolation=Isolation.SERIALIZABLE, readOnly=false)
String releaseLock(final SpInOutFields input);
}
我的aquireLock
方法运行我的oracle函数,oracle函数有两个insert语句。在插入数据之前,我使用给定数据的select count(*)来检查数据是否存在。如果存在,我不会插入示例pl sql语句在下面的数据
SELECT COUNT(*) INTO rowcount FROM kp_lock WHERE device_id = deviceId;
if rowcount = 0 then
INSERT INTO kp_lock(device_id,lock_flag,request_time) values ( deviceId, 'YES', CURRENT_TIMESTAMP);
status := threadSysId;
else
status := '';
end if;
当我从oracle运行该函数时,它工作正常。当我运行单个线程时它工作正常但是当我运行多线程时失败。
我的JUNIT测试类在下面,
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:config/spring-context.xml"})
public class TestSerialization {
@Autowired
ApplicationContext context;
@Test
public void testSerialize() throws InterruptedException{
MultiThread multithread = context.getBean(MultiThread.class);
MultiThread multithread1 = context.getBean(MultiThread.class);
Thread thread = new Thread(multithread);
Thread thread1 = new Thread(multithread1);
thread.start();
if(multithread == multithread1){
System.out.println("Both refer same instance");
}
thread1.start();
try {
thread.join();
thread1.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
有些人可以帮我配置以同步方式运行的事务。不知道我哪里出错了
答案 0 :(得分:2)
问题在于导致竞争条件的功能的非原子性。在多线程环境中,如果记录存在且插入发生,则可以在检查之间执行某些其他线程。
您无法仅通过事务配置解决此问题。您需要做的是insert conditionally。
看起来您正在尝试实现自定义锁。考虑使用User Defined Locks