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

AnotherEmpService 類源碼
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 對象
10
firstDAO.insert(newEmp);
11
System.out.println(">>>>>>>>>>>>>>>>> is in AnotherEmpService");
12
// secondDAO 注入的是 UserDAO 對象
13
secondDAO.insert(newUser);
14
} catch(Exception e)
{
15
System.out.println(">>>>>>>>>>>>>>>>>>>>>>Exception was catched in AnotherEmpService");
16
}
17
}
18
}
EmployeeDAO 類中的 insert 方法可以正常執行成功,故該類的源代碼省略。而在 UserDAO 類中我人為地扔出了一個 Exception 類型的異常,其源碼如下:

UserDAO 類源碼
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
聲明式事務的配置如下:

相關配置
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>
也就是說,我們準備在服務層進行事務控制,并希望將新建員工、新建用戶這兩個原子性的操作作為一個完整的事務執行。在這里有兩個重要的因素影響著它們能否作為一個完整的事務而執行。下面我以一個表格的形式展示我的測試結果: