spring事物无法回滚
?
PROPAGATION_REQUIRED
When the propagation setting is PROPAGATION_REQUIRED, a logical transaction scope is created for each method upon which the setting is applied. Each such logical transaction scope can determine rollback-only status individually, with an outer transaction scope being logically independent from the inner transaction scope. Of course, in case of standard PROPAGATION_REQUIRED behavior, all these scopes will be mapped to the same physical transaction. So a rollback-only marker set in the inner transaction scope does affect the outer transaction's chance to actually commit (as you would expect it to).
?
However, in the case where an inner transaction scope sets the rollback-only marker, the outer transaction has not decided on the rollback itself, and so the rollback (silently triggered by the inner transaction scope) is unexpected. A corresponding UnexpectedRollbackException is thrown at that point. This is expected behavior so that the caller of a transaction can never be misled to assume that a commit was performed when it really was not. So if an inner transaction (of which the outer caller is not aware) silently marks a transaction as rollback-only, the outer caller still calls commit. The outer caller needs to receive an UnexpectedRollbackException to indicate clearly that a rollback was performed instead.
?
当事务传播性设置为PROPAGATION_REQUIRED的时候,Spring将为每一个应用了这个设置的方法创建一个逻辑上的事务(相对于物理事务而言)。每一个这样的逻辑事务都能够单独地决定rollback-only状态(即决定该事务是否回滚),这是与逻辑上独立于内部事务的外部事务一起的(这里的逻辑上独立是指内部事务和外部事务都拥有自己的逻辑事务属性)。当然,对于标准的PROPAGATION_REQUIRED行为,所有这些事务(无论是内部事务还是外部事务)都会对应为同一个物理事务。如果内部事务里面设置了rollback-only标志的话将会影响到外部事务的提交(这其实也是你期望的行为)。
?
这段话其实就是说如果一个外部事务和它的内部事务设置的属性都是PROPAGATION_REQWUIRED的话,那么这些事务实际上都处在同一个物理事务中,每一个事务都能够单独地决定该物理事务是否回滚,只需要将该自己设置为rollback-only。?
?
然而,有这样的一种情况,当一个内部事务设置了rollback-only标识(这样的话整个物理事务就需要回滚了),而外部事务却决定不回滚(如果这个内部事务抛出异常的话外部事务可以通过在代码中捕获这个异常来防止因抛出异常而回滚,但是外部事务却不能干涉内部事务将其自己设置为rollback-only),这样的话,这个回滚就不是外部事务所期望的了。在这个节骨眼上将会抛出一个一个相应的UnexpectedRollbackException。这是符合预期的行为,因为这样的话事务的调用者就不会误认为这个事务是已提交的(因为某个内部事务已经标识为rollback-only了,所以外部事务不应该提交的)。因此如果一个内部事务(外部调用者并不知道)默默地标识为rollback-only,外部调用者仍旧称为commit。外部调用者需要接收到一个
UnexpectedRollbackException来明明白白地知道发生了一个回滚而不是commit。
?
这段话其实就是说如果某个内部事务将其自己标识为rollback-only了,那么整个物理事务就需要回滚,如果外部事务尝试去提交整个物理事务,那么就会抛出UnexpectedRollbackException,只有这样外部事务的调用者才会知道某个内部事务要求回滚,不应该提交整个物理事务。?
?
总之:spring事务回滚默认是回滚运行时异常(可以配置所有异常回滚),如果事务配置在service层,在一个action中只能调用一个保存或修改数据的service方法,同时在service方法中不要捕获异常(采用向action中抛异常).