[spring transaction],service实现类中非事务方法直接调用自身事务方法导致事务无效的原因

首先,准备service接口,两个

public interface AccountService {

    public void createAccount(Account account, int throwExpFlag) throws Exception;

    public void createAccountShell(Account account, int i) throws Exception;

}
public interface RoleService {
    
    public void createAccountShell(Account account, int i) throws Exception;

}

 

相关impl

@Service
public class AccountServiceImpl implements AccountService {

    @Resource
    private AccountDAO accountDAO;
    
    @Override
    @Transactional
    public void createAccount(Account account, int throwExpFlag) throws Exception {
        accountDAO.save(account);
        RoleServiceImpl.throwExp(throwExpFlag);
    }

    @Override
    public void createAccountShell(Account account, int i) throws Exception {
        this.createAccount(account, i);
    }

}
@Service
public class RoleServiceImpl implements RoleService {

    @Autowired
    AccountService accountService;
    
    public static void throwExp(int throwExpFlag) throws Exception {
        if (throwExpFlag == 0) {
            throw new RuntimeException("<< rollback transaction >>");
        } else if (throwExpFlag != 1) {
            throw new Exception("<< do not rollback transaction >>");
        }
    }

    @Override
    public void createAccountShell(Account account, int i) throws Exception {
        accountService.createAccount(account, i);        
    }

}

 

测试类

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:spring/spring-dao.xml", "classpath:spring/spring-service.xml"})
public class ServiceTransactionTest extends TestCase {

        public static Account account;

        static {
                account = new Account();
        account.setId(779);
        account.setUsername("779 USER");
        account.setPassword("0123456");
        }

    @Autowired
    AccountService accountService;
    
    @Autowired
    RoleService roleService;
    
    @Test
    public void test_1() throws Exception {
        this.accountService.createAccount(account, 0);
    }

        @Test
    public void test_2() throws Exception {
        this.accountService.createAccountShell(account, 0);
    }

        @Test
    public void test_3() throws Exception {
        roleService.createAccountShell(account, 0);
    }

}

(一)对测试类的test_1方法进行单元测试时,由于AccountServiceImpl.createAccount方法显示配置了事务(@Transactional),所以spring正常接管事务。

 

(二)对测试类的test_2方法进行单元测试时,AccountServiceImpl.createAccountShell方法并没有显示配置事务,但其却调用了AccountServiceImpl.createAccount方法(已配事务)。然并卵,当抛出RuntimeException时,没有rollback,说明spring没有接管事务。(猜测原因:AccountServiceImpl.createAccountShell 被显示调用时,spring是知道的,但由于AccountServiceImpl.createAccountShell没有显示配置事务,spring并没有对此进行事务的管理,在AccountServiceImpl.createAccountShell内部虽然调用了配置了事务的createAccount方法,但spring并不知道或无法确定事务上下文,所以结果是并没有因为抛出的运行时异常而进行rollback)。

 

(三)测试test_3,虽然RoleServiceImpl.createAccountShell同样没有配置事务,但抛出RuntimeException时,spring接管了事务并rollback。(猜测原因:虽然RoleServiceImpl.createAccountShell没有配置事务,但其内部调用另一个service实例的方法,即AccountService.createAccount时,spring对此是获知的,又因为AccountServiceImpl.createAccount显示配置了事务,所以spring接管了事务)。

 

(四)如果在AccountServiceImpl.createAccountShell配置了事务,那么在执行test_2时,spring是可以接管事务的。

posted @ 2017-03-24 15:02  格德米斯  阅读(6539)  评论(0编辑  收藏  举报