[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

相關文章
相關標籤/搜索