當(dāng)使用 spring 的 AOP 為 web 應(yīng)用提供事務(wù)管理服務(wù)時(shí),我們需要指定事務(wù)策略,指定事務(wù)策略的格式如下:
1. 傳播行為, 隔離層級(jí), 只讀, +異常, -異常
2. 傳播行為必須設(shè)置,其他均可選擇性地設(shè)置,中間以英文逗號(hào)分隔,例如:PROPAGATION_REQUIRED,readOnly,-BusinessException, 注意:在 BusinessException 前面加上 - 號(hào)表示發(fā)生指定異常時(shí)回滾操作,如果加上 + 號(hào)則表示發(fā)生指定異常時(shí)立即提交操作。
3. 如果你沒(méi)有指定發(fā)生異常時(shí)事務(wù)該怎樣進(jìn)行,那么當(dāng)真的在某個(gè)事務(wù)中發(fā)生很?chē)?yán)重的異常時(shí)它不會(huì)回滾事務(wù)的。而這不是我們期望看到的,所以在這里應(yīng)該指定你的應(yīng)用異常(即業(yè)務(wù)邏輯異常)。
下面結(jié)合一個(gè)實(shí)例來(lái)總結(jié)一下指定事務(wù)策略時(shí)需要注意的問(wèn)題。這個(gè)實(shí)例模擬一個(gè) HR 系統(tǒng)中非常簡(jiǎn)單的一部分業(yè)務(wù)邏輯--新建一個(gè)員工信息的同時(shí)為其新建一個(gè)系統(tǒng)用戶(hù)。
服務(wù)層的代碼:

AnotherEmpService 類(lèi)源碼
1
public class AnotherEmpService extends ServiceAdapter
{
2
3


4
5
public void insert(Map map) throws Exception
{
6
try
{
7
Employee newEmp = (Employee)map.get("newEmp");
8
User newUser = (User)map.get("newUser");
9
// firstDAO 注入的是 EmployeeDAO 對(duì)象
10
firstDAO.insert(newEmp);
11
System.out.println(">>>>>>>>>>>>>>>>> is in AnotherEmpService");
12
// secondDAO 注入的是 UserDAO 對(duì)象
13
secondDAO.insert(newUser);
14
} catch(Exception e)
{
15
System.out.println(">>>>>>>>>>>>>>>>>>>>>>Exception was catched in AnotherEmpService");
16
}
17
}
18
}
EmployeeDAO 類(lèi)中的 insert 方法可以正常執(zhí)行成功,故該類(lèi)的源代碼省略。而在 UserDAO 類(lèi)中我人為地扔出了一個(gè) Exception 類(lèi)型的異常,其源碼如下:

UserDAO 類(lèi)源碼
1
public class UserDAO extends DAOAdapter<User>
{
2
3
public void insert(User po) throws Exception
{
4
5
System.out.println(">>>>>>>>>> is in UserDAO!!!!");
6
po.setUserPwd("123456");
7
String sql = "insert into user (userName, userPwd, empID) values(?, ?, ?)";
8
Object[] args =
{po.getUserName(), po.getUserPwd(), po.getEmpID()};
9
if(1 == 1)
{
10
throw new Exception();
11
}
12
int[] argTypes =
{Types.VARCHAR, Types.VARCHAR, Types.INTEGER};
13
this.jdbcTemplate.update(sql, args, argTypes);
14
}
15


16
17
}
18
聲明式事務(wù)的配置如下:

相關(guān)配置
1
<bean id="transactionInterceptor"
2
class="org.springframework.transaction.interceptor.TransactionInterceptor">
3
<property name="transactionManager">
4
<ref bean="transactionManager" />
5
</property>
6
<property name="transactionAttributes">
7
<props>
8
<prop key="save*">PROPAGATION_REQUIRED,-Exception</prop>
9
<prop key="create*">PROPAGATION_REQUIRED,-Exception</prop>
10
<prop key="insert*">PROPAGATION_REQUIRED,-Exception</prop>
11
<prop key="delete*">PROPAGATION_REQUIRED,-Exception</prop>
12
<prop key="*update*">PROPAGATION_REQUIRED,-Exception</prop>
13
<prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
14
</props>
15
</property>
16
</bean>
17
<bean
18
class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
19
<property name="interceptorNames">
20
<list>
21
<value>transactionInterceptor</value>
22
</list>
23
</property>
24
<property name="beanNames">
25
<value>*Service</value>
26
</property>
27
</bean>
也就是說(shuō),我們準(zhǔn)備在服務(wù)層進(jìn)行事務(wù)控制,并希望將新建員工、新建用戶(hù)這兩個(gè)原子性的操作作為一個(gè)完整的事務(wù)執(zhí)行。在這里有兩個(gè)重要的因素影響著它們能否作為一個(gè)完整的事務(wù)而執(zhí)行。下面我以一個(gè)表格的形式展示我的測(cè)試結(jié)果: