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

首先,准备service接口,两个spring

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;

}

 

相关implide

@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)。this

 

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

 

(四)若是在AccountServiceImpl.createAccountShell配置了事务,那么在执行test_2时,spring是能够接管事务的。code

相关文章
相关标签/搜索