javax.persistence.TransactionRequiredException的workaround方案
1. 背景
springboot升级到2.5.3 之后,hibernate update/save db操作会报javax.persistence.TransactionRequiredException 异常;
2. 问题排查
有说启动了两个tomcat实例的,第二个实例里没有transaction, 后来细看了代码报错的地方如下:
javax.persistence.TransactionRequiredException: no transaction is in progress at org.hibernate.internal.AbstractSharedSessionContract.checkTransactionNeededForUpdateOperation(AbstractSharedSessionContract.java:422) at org.hibernate.internal.SessionImpl.checkTransactionNeededForUpdateOperation(SessionImpl.java:3397) at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1354) at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1349)
再翻一下 checkTransactionNeededForUpdateOperation 方法:
public void checkTransactionNeededForUpdateOperation(String exceptionMessage) { if (this.fastSessionServices.disallowOutOfTransactionUpdateOperations && !this.isTransactionInProgress()) { throw new TransactionRequiredException(exceptionMessage); } }
看到这个变量可以控制 TransactionRequiredException是否抛出,而
this.disallowOutOfTransactionUpdateOperations = !sessionFactoryOptions.isAllowOutOfTransactionUpdateOperations();
sessionFactoryOptions.allowOutOfTransactionUpdateOperations = ConfigurationHelper.getBoolean("hibernate.allow_update_outside_transaction", configurationSettings, false);
3. 解决方案
设置hibernate allow_update_outside_transaction 属性为true。
<prop key="hibernate.allow_update_outside_transaction">true</prop>
4. 结语
如果引入的hibernate 包,在checkTransactionNeededForUpdateOperation处,不再有该属性字段,只有isTransactionInProgress那只能再update / save 处设置transaction 。