我有一个Java Play 2.5应用程序,并且有一个标记为只读的事务(在控制器级别):
```js
@Transactional(readOnly = true) public Result list() { ...
(这是play.db.jpa.Transactional批注)。
因此,如果我为休眠事务打开日志记录:
```js
<logger name="org.hibernate.engine.transaction" level="TRACE"/>
然后,我看到事务正在完成并被提交。
019-12-03 23:42:23,754 [debug] from org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformInitiator in main - No JtaPlatform was specified, checking resolver
2019-12-03 23:42:23,755 [debug] from org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformResolverInitiator in main - No JtaPlatformResolver was specified, using default [org.hibernate.engine.transaction.jta.platform.internal.StandardJtaPlatformResolver]
2019-12-03 23:42:23,766 [debug] from org.hibernate.engine.transaction.jta.platform.internal.StandardJtaPlatformResolver in main - Could not resolve JtaPlatform, using default [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
2019-12-03 23:58:46,769 [debug] from org.hibernate.engine.transaction.internal.TransactionImpl in application-akka.actor.default-dispatcher-5 - begin
2019-12-03 23:58:46,878 [error] from application in application-akka.actor.default-dispatcher-5 - Transaction: org.hibernate.engine.transaction.internal.TransactionImpl@3d505ddd[transactionCoordinator=org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl@89a1241,exceptionConverter=org.hibernate.internal.ExceptionConverterImpl@76f0443c,transactionDriverControl=org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl@49f1518a]
2019-12-03 23:59:27,638 [debug] from org.hibernate.engine.transaction.internal.TransactionImpl in application-akka.actor.default-dispatcher-5 - committing
但是,我有一个问题-它不是只读的!我添加了一些修改对象的代码(obj.setField(“ changed value”)),并在事务结束时将其保存到数据库中!
我期待有一个异常告诉我该事务是只读的,并且无法提交!
为什么交易不是只读的? 我能否以某种方式在日志中看到Hibernate是否以只读方式创建事务? 其他信息:Java Play 2.5.10,Hibernate 5(5.2.6)和PostgreSQL作为数据库。
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
在Java Play框架中,使用@Transactional(readOnly = true)
注解通常意味着你希望该事务以只读模式运行。然而,这个注解主要影响的是Spring框架管理的事务,而不是直接控制Hibernate的行为。Play框架虽然可以与Spring集成,但原生使用的事务管理可能不完全遵循Spring的这一特性。
对于你的问题,有几个可能的原因和解决方向:
确保事务管理配置正确:首先确认你的Play应用是否正确集成了Spring的事务管理。如果只是依赖于Play的原生JPA支持而没有特别配置Spring的事务管理,那么readOnly
属性可能不会按预期工作。
查看数据库日志:虽然从提供的日志信息中没有直接显示事务是否为只读,你可以尝试查看数据库层面的日志(如PostgreSQL的日志),看看是否有指示事务为只读的标志。某些数据库驱动或JDBC连接参数允许标记事务为只读,并且这可能会反映在数据库的日志记录中。
Hibernate配置:Hibernate自身对事务的只读标记可能需要特定的配置来生效。尽管@Transactional
注解应该传递给Hibernate,但有时框架间的交互可能不够直接。检查Hibernate的配置文件或启动时的日志,看是否有与只读事务相关的设置或提示。
异常处理:即使事务被标记为只读,Hibernate或JDBC驱动可能不会阻止你修改对象的状态,但在提交这些更改到数据库时应该会抛出异常。确保你的代码逻辑正确捕获并处理了这类异常,特别是org.hibernate.TransientObjectException
或任何与事务只读性冲突相关的异常。
手动验证事务状态:作为调试手段,你可以在代码中手动检查事务是否被正确标记为只读。例如,通过Spring的TransactionSynchronizationManager.isCurrentTransactionReadOnly()
方法(如果你的应用确实集成了Spring)。
升级框架版本:考虑到你提到的版本较旧(Play 2.5.10, Hibernate 5.2.6),可能存在已知的问题或限制。考虑升级到更现代的版本,同时注意查阅相关更新日志,看是否有关于事务管理或只读事务处理的改进。
如果以上步骤都不能解决问题,建议深入阅读Play Framework和Hibernate的官方文档,或者在相应的社区论坛、Stack Overflow等平台寻求帮助,提供更详细的配置和代码示例以便获得更具体的解答。