Spring JPA @Transactional-在不同线程中不可见的数据

时间:2019-04-30 23:15:17

标签: java spring jpa

在我的测试案例中,我有一个事务方法,该方法创建用户,然后在另一个线程中调用异步方法,该线程从数据库中检索该用户。在下面的代码中,无法在db中找到用户,并且dao返回null。如何确保不同线程的数据在那里?似乎冲洗无济于事。我需要手动提交吗?将隔离级别设置为READ_UNCOMMITED也无济于事。


    @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);
    } 

2 个答案:

答案 0 :(得分:1)

整个事务方法完成后,事务便被提交。如果创建用户事务在主事务中,则无法提交。将先前的代码更改为类似的效果。


    @Transactional
    public void createUser()  {

         User user = transactionalService.createUser();

         transactionalService.getUser(user.getId());

    }

和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);
    }


答案 1 :(得分:0)

确保您的数据库支持READ_UNCOMMITTED隔离级别(并因此导致脏读)

您测试过的两个数据库(Postgres和Oracle)仅提供较高的隔离级别,并减少了不良现象。

Postgres

https://www.postgresql.org/docs/9.3/sql-set-transaction.html

SQL标准定义了一个附加级别,即READ UNCOMMITTED。在PostgreSQL中,READ UNCOMMITTED被视为READ COMMITTED。

Oracle

Does oracle allow the uncommitted read option?