javax.persistence.TransactionRequiredException: No EntityManager with actual transaction available..

javax.persistence.TransactionRequiredException: No EntityManager with actual transaction available for current thread - cannot reliably process 'merge' call

今天用spring4.2.5版进行数据更新的时候出现了这个问题,粗略的看报错的应该是声明式事务有点问题,可是和以前用的3.0版本的配置一样,问题出在哪里呢,百度也找不到好的答案。

我们知道,在3.0版本中,service里面定义的方法名如果没有和advice里面一样也是可以的,最多就是执行的时候没有走事务,数据保存不进去而已。后来对比了下源码才知道在4.2中有这么一段

SharedEntityManagerCreator:
else if (transactionRequiringMethods.contains(method.getName())) {
				// We need a transactional target now, according to the JPA spec.
				// Otherwise, the operation would get accepted but remain unflushed...
				if (target == null || (!TransactionSynchronizationManager.isActualTransactionActive() &&
						!target.getTransaction().isActive())) {
					throw new TransactionRequiredException("No EntityManager with actual transaction available " +
							"for current thread - cannot reliably process '" + method.getName() + "' call");
				}
			}

transactionRequiringMethods:
static {
		transactionRequiringMethods.add("joinTransaction");
		transactionRequiringMethods.add("flush");
		transactionRequiringMethods.add("persist");
		transactionRequiringMethods.add("merge");
		transactionRequiringMethods.add("remove");
		transactionRequiringMethods.add("refresh");


		queryTerminationMethods.add("getResultList");
		queryTerminationMethods.add("getSingleResult");
		queryTerminationMethods.add("executeUpdate");
	}


只要是joinTransaction,flush,persist,merge等方法都会去验证是加入事务管理,如果没有的话会报错的。

所以只要把方法名写到advice里面就可以了。

<tx:advice id="txAdvice">
		<tx:attributes>
			<tx:method name="save*" propagation="REQUIRED" rollback-for="Exception" />
			<tx:method name="add" propagation="REQUIRED" rollback-for="Exception" />
			<tx:method name="create*" propagation="REQUIRED" rollback-for="Exception" />
			<tx:method name="update*" propagation="REQUIRED" rollback-for="Exception" />
			<tx:method name="delete*" propagation="REQUIRED" rollback-for="Exception" />
			<tx:method name="increment*" propagation="REQUIRED" rollback-for="Exception" />
			<tx:method name="query*" propagation="SUPPORTS" rollback-for="Exception" />
			<tx:method name="get*" propagation="SUPPORTS" rollback-for="Exception" />
			<tx:method name="*" propagation="SUPPORTS" rollback-for="Exception" />
		</tx:attributes>
	</tx:advice>
如上,之前的方法名是叫testXXX的显然不在这里面,换成update开头的就好啦。spring这点做的还是比较人性化的,有了验证机制。完毕!

你可能感兴趣的:(spring,事务)