目前我做了个小小的试验,证明了Spring的jdbc事务的问题。我的环境:
使用jakarta commons dbcp 的 org.apache.commons.dbcp.BasicDataSource,作为DataSource.
xml中的配置如下:
<bean id="datasource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost/TransactionTest" />
<property name="username" value="zc" />
<property name="password" value="zc" />
<property name="defaultAutoCommit" value="false" />
</bean>
my sql 数据库TransactionTest中有2个表,一个account, 一个accountprofile,分别弄了2个dao
<bean id="accountdao"
class="test.AccountDaoImp" >
<property name="dataSource" ref="datasource" />
</bean>
<bean id="accountprofiledao"
class="test.AccountProfileDaoImp" >
<property name="dataSource" ref="datasource" />
</bean>
事务管理器配置:
<bean id="dbTransactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="datasource" />
</bean>
业务门面:
<bean id="accountservice_target"
class="test.AccountService" >
<property name="accountDao" ref="accountdao" />
<property name="accountProfileDao" ref="accountprofiledao" />
</bean>
最后配置Spring的事务代理(其实就是利用了AOP):
<bean id="accountservice" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" >
<property name="transactionManager" ref="dbTransactionManager" />
<property name="target" ref="accountservice_target" />
<property name="transactionAttributes" >
<props>
<prop key="register*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
我的业务门面实现有个方法:
public void registerAccount(Account a, AccountProfile ap){
accountDao.insert(a);
accountProfileDao.insert(ap);
}
分别调用2个dao的insert()方法,Account, AccountProfile是值对象。
测试代码:
public static void main(String[] args) {
FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext("beans.xml");
AccountService service = (AccountService) context.getBean("accountservice");
Account a = new Account();
a.setId("U001");
a.setName("zc");
a.setPhone("123");
AccountProfile ap = new AccountProfile();
ap.setName(a.getName()); // "zc"
ap.setPassword("abcdef");
service.registerAccount(a,ap);
a = new Account();
a.setId("U002");
a.setName("zc");
a.setPhone("123");
ap = new AccountProfile();
ap.setName(a.getName()); // "zc"
ap.setPassword("12345");
service.registerAccount(a,ap);
context.close();
}
由于表accountprofile 的name 字段是唯一的,所以第2次registerAccount()要出现异常。
也就是在第2次执行registerAccount()时
{
accountDao.insert(a);
accountProfileDao.insert(ap); // 这要抛出异常
}
但前面的 accountDao.insert(a) 无法回滚呢?
数据库结果:account有2条记录,id不同,但name相同, accountprofile有1条记录.
数据库不一致, 事务没起到作用。