Reputation: 692
In my test case I have transactional method that creates user and then invokes async method in different thread that retrieves this user from database. In code below the user cannot be found in db and dao returns null. How to be sure that data will be there for different threads? It seems that flushing does not help. Do I need to manually commit? Setting isolation level to READ_UNCOMMITED also does not help.
@Transactional public void createUser() { User user = new User(); user.setLogin("test"); userService.save(user); userService.flush(); logger.debug("New user id {}", user.getId()); //id=1 transactionalService.getUser(user.getId()); }
TransactionalService
@Async @Transactional public void getUser(Long id) { User user = userDao.getById(id); assertNotNull(user); }
Upvotes: 1
Views: 1551
Reputation: 692
Transaction is committed after whole transactional method is finished. Create user transaction can't be committed if it is in the main transaction. Changing previous code to something like this works.
@Transactional public void createUser() { User user = transactionalService.createUser(); transactionalService.getUser(user.getId()); }
And TransactionalService
@Transactional(propagation=Propagation.REQUIRES_NEW) public void createUser() { User user = new User(); user.setLogin("test"); userService.save(user); logger.debug("New user id {}", user.getId()); //id=1 return user } @Async @Transactional public void getUser(Long id) { User user = userDao.getById(id); assertNotNull(user); }
Upvotes: 2
Reputation: 25986
Make sure that your database supports READ_UNCOMMITTED
isolation level (and, as a consequence, Dirty Reads)
Both databases you tested on (Postgres and Oracle) offer only higher isolation levels with less undesirable phenomena.
Postgres
https://www.postgresql.org/docs/9.3/sql-set-transaction.html
The SQL standard defines one additional level, READ UNCOMMITTED. In PostgreSQL READ UNCOMMITTED is treated as READ COMMITTED.
Oracle
Does oracle allow the uncommitted read option?
Upvotes: 0