Spring @Transactional只读模式回滚行为

时间:2017-05-02 16:11:38

标签: java spring postgresql hibernate transactions

我有一些@Transactional(readOnly=true)的服务层方法,这个方法会经常导致一些RuntimeException(假设它有一些NotFoundException异常)。

我正在使用ORM Hibernate进行数据库交互过程。

这样做是否合法?

在这种情况下,“回滚”行为意味着什么是默认行为?它能否以某种方式严重影响连接的状态或导致任何问题?

这不是“为什么不亲自尝试?”。在一些例外之后,我怀疑这个可能导致同一方法中出现Transaction rolled back because it has been marked as rollback-only错误。这个可能是非常具体的JDBC PostgreSQL驱动程序错误。这就是为什么我一般都在想这个设计:这样做是合法的还是非法的?

2 个答案:

答案 0 :(得分:1)

据我了解,你担心回滚。在这种情况下,readOnlyselect statement,通常没有任何内容可以从read回滚。这个方便的唯一地方就是当你在锁定下阅读时,当交易结束时你释放锁定。

AFAIK readOnly会将flushmode设置为FlushMode.NEVER,同时又好又坏。很好,因为没有脏检查,如here所述。不好,因为如果在readOnly事务中调用读/写事务,事务将无提示失败,因为会话未刷新。这很容易被测试 - 我希望事情没有改变,因为我已经尝试过了。

然后是连接池。我知道C3P0的默认策略是回滚任何未提交的工作。控制它的标志是autoCommitOnClose

然后有关于readOnlypostgres的{​​{3}} - 我没有合作过,也无法真实地表达我的观点。

现在谈谈Transaction rolled back because it has been marked as rollback-only。对于readOnly事务,可能没有像我之前所说的那样回滚,所以这个真的取决于你如何链接你的@Transactional方法IMO。

答案 1 :(得分:0)

我遇到了与作者所描述的相同的情况(UnexpectedRollbackException)。 我进行了一些研究,例如更改传播或noRollbackFor,但仍然无法正常工作。 最后,我找到了解决方法。创建一个自定义的异常(例如NotExistedException),该异常继承Exception(已检查的异常)。 然后,对于调用方,它决定捕获或引发运行时异常。 参见下面的代码。

@Transactional(readOnly = true)
public obj selectSth(String id) throws NotExistedException {
    obj = xxxDao.selectSth(id);
    if (obj == null)
        throw new NotExistedException('not found');
    else
        return obj ;
}

// caller
try {
    obj = xxxServ.selectSth('xx');
} catch (NotExistedException e) { // checked exception
    // do nothing or throw below exception
    throw new NotFoundException(e.getMessage()); // not checked (runtime) exception
}