目前我做了个小小的试验,证明了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条记录.
数据库不一致, 事务没起到作用。