请教一个事务的问题

请教个问题,service中有两个方法A和B,A没有用@Transactional标记,B用了@Transactional标记,A调用B,B不起作用。只有A也加上@Transactional,B才回起作用。为啥?

aop使用的是动态代理,而你加上注解之后才代理你这个类,当不加注解就变成一个普通方法,当程序运行时,动态代理不会代理你这个方法,所以你里面调用带注解的方法一样时作为一个普通方法调用。

1 Like

你可以先去查看spring的Propagation枚举类,里面列举了spring所有的传播行为。。
spring的默认传播机制是REQUIRED(在Transactional注解中可以看到),意思是“如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中”。
在springmvc中,定义全局事务时,一般会对add,update,save,delete等增加事务,而get,query等可能就采用NEVER(以非事务方式执行,如果当前存在事务,则抛出异常)。为何要这样定义?在实际开发中,查询接口往往要快速返回,如果存在事务,必然会降低接口性能。
假如一个add接口的事务为REQUIRED,在add接口中要调用NEVER的get方法,会抛出异常。如果要正确访问,就需要变更get方法的事务机制,比如采用NOT_SUPPORTED(以非事务方式执行操作,如果当前存在事务,就把当前事务挂起)。
只要能区分清楚spring的事务传播行为,你就能解决普通方法->事务方法,事务方法->普通方法,事务方法->事务方法等问题。也能控制可能出现的问题,或者满足你应该要的结果(比如回滚)

2 Likes

我看了下您说的好像是回滚问题?可能我表述的不太清楚,我的意思是,B方法是一个保存数据的方法,B用了@Transactional标记,A方法没用@Transactional标记,A调用B,B并没有把数据保存到数据库中,而不是B没有回滚。因为我这个人比较笨,上网看了spring的事务传播机制后,觉得好像各种传播机制针对的是回不回滚的问题,和我这个好像不太一样?

你这是不是没自动提交事务?