开发者社区 问答 正文

播放2.5-@Transactional readOnly是否被忽略?

我有一个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作为数据库。

展开
收起
垚tutu 2019-12-04 17:04:43 720 分享 版权
阿里云 AI 助理回答

在Java Play框架中,使用@Transactional(readOnly = true)注解通常意味着你希望该事务以只读模式运行。然而,这个注解主要影响的是Spring框架管理的事务,而不是直接控制Hibernate的行为。Play框架虽然可以与Spring集成,但原生使用的事务管理可能不完全遵循Spring的这一特性。

对于你的问题,有几个可能的原因和解决方向:

  1. 确保事务管理配置正确:首先确认你的Play应用是否正确集成了Spring的事务管理。如果只是依赖于Play的原生JPA支持而没有特别配置Spring的事务管理,那么readOnly属性可能不会按预期工作。

  2. 查看数据库日志:虽然从提供的日志信息中没有直接显示事务是否为只读,你可以尝试查看数据库层面的日志(如PostgreSQL的日志),看看是否有指示事务为只读的标志。某些数据库驱动或JDBC连接参数允许标记事务为只读,并且这可能会反映在数据库的日志记录中。

  3. Hibernate配置:Hibernate自身对事务的只读标记可能需要特定的配置来生效。尽管@Transactional注解应该传递给Hibernate,但有时框架间的交互可能不够直接。检查Hibernate的配置文件或启动时的日志,看是否有与只读事务相关的设置或提示。

  4. 异常处理:即使事务被标记为只读,Hibernate或JDBC驱动可能不会阻止你修改对象的状态,但在提交这些更改到数据库时应该会抛出异常。确保你的代码逻辑正确捕获并处理了这类异常,特别是org.hibernate.TransientObjectException或任何与事务只读性冲突相关的异常。

  5. 手动验证事务状态:作为调试手段,你可以在代码中手动检查事务是否被正确标记为只读。例如,通过Spring的TransactionSynchronizationManager.isCurrentTransactionReadOnly()方法(如果你的应用确实集成了Spring)。

  6. 升级框架版本:考虑到你提到的版本较旧(Play 2.5.10, Hibernate 5.2.6),可能存在已知的问题或限制。考虑升级到更现代的版本,同时注意查阅相关更新日志,看是否有关于事务管理或只读事务处理的改进。

如果以上步骤都不能解决问题,建议深入阅读Play Framework和Hibernate的官方文档,或者在相应的社区论坛、Stack Overflow等平台寻求帮助,提供更详细的配置和代码示例以便获得更具体的解答。

有帮助
无帮助
AI 助理回答生成答案可能存在不准确,仅供参考
0 条回答
写回答
取消 提交回答