我有一些@Transactional(readOnly=true)
的服务层方法,这个方法会经常导致一些RuntimeException
(假设它有一些NotFoundException
异常)。
我正在使用ORM Hibernate进行数据库交互过程。
这样做是否合法?
在这种情况下,“回滚”行为意味着什么是默认行为?它能否以某种方式严重影响连接的状态或导致任何问题?
这不是“为什么不亲自尝试?”。在一些例外之后,我怀疑这个可能导致同一方法中出现Transaction rolled back because it has been marked as rollback-only
错误。这个可能是非常具体的JDBC PostgreSQL驱动程序错误。这就是为什么我一般都在想这个设计:这样做是合法的还是非法的?
答案 0 :(得分:1)
据我了解,你担心回滚。在这种情况下,readOnly
是select statement
,通常没有任何内容可以从read
回滚。这个方便的唯一地方就是当你在锁定下阅读时,当交易结束时你释放锁定。
AFAIK readOnly
会将flushmode设置为FlushMode.NEVER
,同时又好又坏。很好,因为没有脏检查,如here所述。不好,因为如果在readOnly
事务中调用读/写事务,事务将无提示失败,因为会话未刷新。这很容易被测试 - 我希望事情没有改变,因为我已经尝试过了。
然后是连接池。我知道C3P0
的默认策略是回滚任何未提交的工作。控制它的标志是autoCommitOnClose
。
然后有关于readOnly
和postgres
的{{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
}