事务注解写在控制层引发的错误

之前遇到了一个事务错误,我认为还算是比较稀有和有意义的,现在有时间了正好写一下。下面是异常

org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Transaction marked as rollbackOnly
	at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:526)
	at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:761)
	at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:730)
	at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:518)
	at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:292)
	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:673)
	at com.kq.highnet2.openApi.mobile.framework.base.loginInfo.LoginInfoAction$$EnhancerBySpringCGLIB$$87638463.login(<generated>)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)

这个错误的原因是子事务抛出异常并回滚,但是外层事务依然提交造成的

下面是错误代码

	@PostMapping("/POST/Login")
	@ResponseBody
	@Transactional
	public MobileWebApiBaseResult login(
			@RequestParam(value="type",required = true)String type
			,@RequestParam(value="LoginCode",required = true)String loginCode
			,@RequestParam(value = "PhoneNumber",required = true)String mobile
			,@RequestParam(value = "PassWord",required = true)String password
			,@RequestParam(value = "localphone",required = false)String localPhone
			,@RequestParam(value = "version",required = false)String version
						) {
		MobileWebApiBaseResult baseResult = new MobileWebApiBaseResult();
		LoginInfoModel loginInfoModel = new LoginInfoModel();
		//TOKEN值用UUID表示
		String token  = UUID.randomUUID().toString();
		TransactionStatus s = transactionManager.getTransaction(new DefaultTransactionDefinition());
		try {
			boolean notNewAccessKey = false;
			//1:取得参数并调用业务层的方法 
			BaseUserModel baseUser = baseUserRuntimeService.checkAppLogin(mobile, password, loginCode, localPhone, type, version);
			//删除loginInfo
			loginInfoService.loginOut(baseUser.getUserId());
			loginInfoModel.setToken(token);
			loginInfoModel.setUserId(baseUser.getUserId());
			loginInfoModel.setLoginTime(new Date());
			loginInfoModel.setDeviceType(type);
			loginInfoService.login(loginInfoModel);
			baseUserRuntimeService.updateLoginCode(token, mobile);
			baseResult.setMsg("登录成功!");
			List<Map> list = new ArrayList<>();
			Map map = new HashMap<String, String>();
			map.put("key", token);
			map.put("RealName", baseUser.getRealName());
			map.put("UserImage", baseUser.getUserImage());
			list.add(map);
			baseResult.setData(list);
			transactionManager.commit(s);
		}catch (Exception e) {
			transactionManager.rollback(s); 
			logger.error(e.getMessage(),e);
			baseLogService.saveSysLog("APP接口", "", e.getMessage(), "Login");
//			LogUtils.addSysLog("APP接口", "", e.getMessage(), "Login");
			baseResult.setCode("0");
			baseResult.setMsg(e.getMessage());
		}
		return baseResult;
	}

当时因为写手机接口,想直接调用service层方法,因为用了不同的service,所以需要在外层加上事务,但是发现@transactional注解加在controller层上不起作用,现在想想原因应该是我已经用try-catch捕捉了异常,所以我就使用transactionManager来实现编程事务,结果当service层报错以后就报了上面的错误。我一直以为是transactionManager层的问题,后来发现其实是@transactional注解忘了去掉,因为action层捕捉了异常@transactional注解的事务以为事务是正常的就提交了,于是就报错了。

总结,事务里面最好不要有try-catch,有异常直接抛到最外层,即使有try-catch,try-catch里面不能有事务存在

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值