Reputation: 1087
I'm having following issue with duplicated inserts in case of concurrent requests.
I have two tables:
create table tbl (
val varchar2(1000)
);
create table tbl2 (
val varchar2(1000)
);
I need to insert some value in table tbl2
only in case if table tbl
is empty. So, in my Java code I do in transaction with isolation level = 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
The problem here is: Somebody could actually insert data between if (result == 0)
and my update statement. So I'll have duplicate entries.
My example is oversimplified, but my real case is much more complicated, but the basic idea is the same: I need to make several selects from within of Javacode before inserting.
So, how is it possible to avoid such kind of situation(I'm interested in db side solution and in java side solution)?
P.S. Database is Oracle.
Upvotes: 0
Views: 1305
Reputation: 6783
I think the best way to handle such a situation might be in database level. You can use a query like:
insert into tbl2 values(xx) where not exists (select 1 from tbl1)
So your query might become something like this
int update = jdbcTemplate.update("insert into tbl2(val) values(?) where not exists (select 1 from tbl1)", "di" + UUID.randomUUID().toString());
Upvotes: 2
Reputation: 1640
Not quite sure why you would want to do what you are doing, but you could lock the table first.
LOCK TABLE tbl IN SHARE MODE;
Remember to COMMIT; to release the locks.
Upvotes: 1