一:目標對象的內部調用無法實施切面
二:實驗
1.接口定義
public interface UserManager {
Integer insert(User user);
void updateUser(User user);
}
2.實現類
@Component("userManager")
public class UserManagerImpl implements UserManager {
@Resource
private UserDao userDao;
@Override
@Transactional(propagation = Propagation.REQUIRED)
public Integer insert(User user) {
insert = userDao.insert(user);
updateUser(user);
return insert;
}
@Transactional(propagation = Propagation.REQUIRED)
@Override
public void updateUser(User user) {
userDao.update(user);
System.out.println(1 / 0);
}
}
爲了方便測試,update的執行sql如下,更新一下修改人,如下
UPDATE tb_user SET update_user = '1026' where id = #{id,jdbcType=BIGINT}
3.測試方法
@Test
public void testInsert() {
User user = new User();
user.setUserName("201808232313");
user.setPassWord("201808232313");
user.setTelPhone("201808232313");
user.setEmail("[email protected]");
user.setCreateUser("201808232313");
user.setUpdateUser("蒼生1");
Integer insert = userManager.insert(user);
logger.debug("testInsert" + insert);
}
4.執行結果,msyql默認可重複讀隔離級別,猜測測試方法執行過後數據庫的情況,
- 數據插入失敗
- 數據插入成功,更新失敗
- 數據插入成功,更新成功
5.執行test方法,數據庫沒有插入記錄。到此還沒結束,不過一般我們這樣寫不會什麼問題。
三:修改實現類的方法,測試其他情況
1.insert方法中,對update的方法,異常進行處理,沒有把異常再次拋出
@Override
@Transactional(propagation = Propagation.REQUIRED)
public Integer insert(User user) {
Integer insert = 0;
insert = userDao.insert(user);
try {
//對方法進行異常處理
updateUser(user);
} catch (Exception e) {
e.printStackTrace();
// throw new RuntimeException(e);
}
return insert;
}
結果發現update方法居然執行成功了,數據被更新,事務失效了。
2.再次修改實現類的方法
@Override
@Transactional(propagation = Propagation.REQUIRED)
public Integer insert(User user) {
Integer insert = 0;
insert = userDao.insert(user);
try {
//對方法進行異常處理
// updateUser(user);
((UserManager) AopContext.currentProxy()).updateUser(user);
} catch (Exception e) {
e.printStackTrace();
// throw new RuntimeException(e);
}
return insert;
}
結果發現update方法的數據被回滾了
3.修改配置文件,在原有的<tx:annotation-driven/> 後增加一句 <aop:config expose-proxy="true"></aop:config>
如下
<tx:annotation-driven/>
<!--配置文件增加下面一行-->
<aop:config expose-proxy="true"></aop:config>
測試發現insert和update都被回滾了
四:總結
事務控制,最簡單的方式就是加了註解的方法不對異常處理,發生異常就回滾數據。如果事務比較複雜,就需要考慮事務調用方法,異常處理和事務配置。防止目標對象內部的方法調用失效。
使用AopContext.currentProxy() 配置文件 <aop:config expose-proxy="true"></aop:config>