在并发请求的情况下,我遇到了重复插入的问题。
我有两张桌子:
create table tbl (
val varchar2(1000)
);
create table tbl2 (
val varchar2(1000)
);
我需要在表tbl2
中插入一些值,以防表tbl
为空。因此,在我的Java代码中,我在事务中使用隔离级别= READ COMMITED:
//start transaction
int result = jdbcTemplate.queryForInt("select count(*) from tbl");
if (result == 0) {
int update = jdbcTemplate.update("insert into tbl2(val) values(?)", "di" + UUID.randomUUID().toString());
}
//end transaction
这里的问题是:有人实际上可以在if (result == 0)
和我的更新语句之间插入数据。所以我会有重复的条目。
我的例子过于简单了,但我的实际情况要复杂得多,但基本思路是一样的:我需要在插入之前从Javacode中做出几个选择。
那么,如何避免这种情况(我对数据库端解决方案和java端解决方案感兴趣)?
P.S。数据库是Oracle。
答案 0 :(得分:1)
不太确定你为什么要做你正在做的事情,但你可以先锁定表。
LOCK TABLE tbl IN SHARE MODE;
记得COMMIT;释放锁。
答案 1 :(得分:1)
我认为处理这种情况的最佳方法可能是数据库级别。您可以使用如下查询:
insert into tbl2 values(xx) where not exists (select 1 from tbl1)
所以你的查询可能会变成这样的
int update = jdbcTemplate.update("insert into tbl2(val) values(?) where not exists (select 1 from tbl1)", "di" + UUID.randomUUID().toString());