1、采用spring的Ioc,但是事务还是采用Nutz自己管理控制;
2、采用spring的声明式事务管理控制;
接下来我们仔细讨论下这两种方式。
方式1:方式1非常简单,Nutz DAO不需要做任何修改即能完成,你可以在你的项目的spring配置文件中添加如下配置即可:
- <!-- the DataSource -->
- <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://127.0.0.1:3306/zdtest"/>
- <property name="username" value="root"/>
- <property name="password" value="root"/>
- </bean>
- <!-- Nutz DAO -->
- <bean id="dao" class="org.nutz.dao.impl.NutDao">
- <property name="dataSource" ref="dataSource"/>
- </bean>
- <!-- your service object that refer to the Nutz DAO -->
- <bean id="petService" class="cn.zj.pubinfo.nutz.pet.PetService">
- <property name="dao" ref="dao"/>
- </bean>
<!-- the DataSource -->
<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://127.0.0.1:3306/zdtest"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
<!-- Nutz DAO -->
<bean id="dao" class="org.nutz.dao.impl.NutDao">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- your service object that refer to the Nutz DAO -->
<bean id="petService" class="cn.zj.pubinfo.nutz.pet.PetService">
<property name="dao" ref="dao"/>
</bean>
这种模式下,spring只提供了Ioc,事务还是有Nutz自己管理和控制。
方式2:
我们要在spring中声明事务管理,大致可以如下:
- <!-- Nutz DAO -->
- <bean id="dao" class="org.nutz.dao.impl.NutDao">
- <property name="dataSource" ref="dataSource"/>
- </bean>
- <bean id="petDao" class="cn.zj.pubinfo.nutz.pet.PetDao">
- <property name="dao" ref="dao"/>
- </bean>
- <!-- this is the service object that we want to make transactional -->
- <bean id="petService" class="cn.zj.pubinfo.nutz.pet.PetService">
- <property name="petDao" ref="petDao"/>
- </bean>
- <!-- the transactional advice (what 'happens'; see the <aop:advisor/> bean below) -->
- <tx:advice id="txAdvice" transaction-manager="txManager">
- <!-- the transactional semantics... -->
- <tx:attributes>
- <!-- all methods starting with 'get' are read-only -->
- <tx:method name="get*" read-only="true"/>
- <!-- other methods use the default transaction settings (see below) -->
- <tx:method name="*"/>
- </tx:attributes>
- </tx:advice>
- <!-- ensure that the above transactional advice runs for any execution
- of an operation defined by the FooService interface -->
- <aop:config>
- <aop:pointcut id="petServiceOperation" expression="execution(* cn.zj.pubinfo.nutz.pet.PetService.*(..))"/>
- <aop:advisor advice-ref="txAdvice" pointcut-ref="petServiceOperation"/>
- </aop:config>
- <!-- don't forget the DataSource -->
- <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://127.0.0.1:3306/zdtest"/>
- <property name="username" value="root"/>
- <property name="password" value="root"/>
- </bean>
- <!-- similarly, don't forget the PlatformTransactionManager -->
- <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
- <property name="dataSource" ref="dataSource"/>
- </bean>
- <!-- other <bean/> definitions here -->
<!-- Nutz DAO -->
<bean id="dao" class="org.nutz.dao.impl.NutDao">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="petDao" class="cn.zj.pubinfo.nutz.pet.PetDao">
<property name="dao" ref="dao"/>
</bean>
<!-- this is the service object that we want to make transactional -->
<bean id="petService" class="cn.zj.pubinfo.nutz.pet.PetService">
<property name="petDao" ref="petDao"/>
</bean>
<!-- the transactional advice (what 'happens'; see the <aop:advisor/> bean below) -->
<tx:advice id="txAdvice" transaction-manager="txManager">
<!-- the transactional semantics... -->
<tx:attributes>
<!-- all methods starting with 'get' are read-only -->
<tx:method name="get*" read-only="true"/>
<!-- other methods use the default transaction settings (see below) -->
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<!-- ensure that the above transactional advice runs for any execution
of an operation defined by the FooService interface -->
<aop:config>
<aop:pointcut id="petServiceOperation" expression="execution(* cn.zj.pubinfo.nutz.pet.PetService.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="petServiceOperation"/>
</aop:config>
<!-- don't forget the DataSource -->
<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://127.0.0.1:3306/zdtest"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
<!-- similarly, don't forget the PlatformTransactionManager -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- other <bean/> definitions here -->
然后,我们对org.nutz.dao.impl.NutDao进行必要的修改,把NutDao中的run()方法:
- public void run(ConnCallback callback) {
- ConnectionHolder ch = Daos.getConnection(getDataSource());
- try {
- ch.invoke(callback);
- }
- catch (Throwable e) {
- try {
- ch.rollback();
- }
- catch (SQLException e1) {}
- if (e instanceof RuntimeException)
- throw (RuntimeException) e;
- else
- throw new RuntimeException(e);
- }
- finally {
- Daos.releaseConnection(ch);
- }
- }
public void run(ConnCallback callback) {
ConnectionHolder ch = Daos.getConnection(getDataSource());
try {
ch.invoke(callback);
}
catch (Throwable e) {
try {
ch.rollback();
}
catch (SQLException e1) {}
if (e instanceof RuntimeException)
throw (RuntimeException) e;
else
throw new RuntimeException(e);
}
finally {
Daos.releaseConnection(ch);
}
}
修改为:
- import org.springframework.jdbc.datasource.DataSourceUtils;
- public void run(ConnCallback callback) {
- Connection con = DataSourceUtils.getConnection(getDataSource());
- try {
- callback.invoke(con);
- } catch (Exception e) {
- if (e instanceof RuntimeException)
- throw (RuntimeException) e;
- else
- throw new RuntimeException(e);
- } finally {
- DataSourceUtils.releaseConnection(con, getDataSource());
- }
- }
import org.springframework.jdbc.datasource.DataSourceUtils;
public void run(ConnCallback callback) {
Connection con = DataSourceUtils.getConnection(getDataSource());
try {
callback.invoke(con);
} catch (Exception e) {
if (e instanceof RuntimeException)
throw (RuntimeException) e;
else
throw new RuntimeException(e);
} finally {
DataSourceUtils.releaseConnection(con, getDataSource());
}
}
OK,运行一下测试,得到如下日志,事务成功的日志:
- 2010-04-30 13:12:33,498 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Creating new transaction with name [cn.zj.pubinfo.nutz.pet.IPetService.createTwoCat]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
- 2010-04-30 13:12:33,498 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Acquired Connection [jdbc:mysql://127.0.0.1:3306/zdtest, UserName=root@localhost, MySQL-AB JDBC Driver] for JDBC transaction
- 2010-04-30 13:12:33,499 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Switching JDBC Connection [jdbc:mysql://127.0.0.1:3306/zdtest, UserName=root@localhost, MySQL-AB JDBC Driver] to manual commit
- 2010-04-30 13:12:33,499 [main] DEBUG org.nutz.dao.impl.NutDao - INSERT INTO t_pet(age,name) VALUES( 0, 'Cat 1')
- 2010-04-30 13:12:33,500 [main] DEBUG org.nutz.dao.impl.NutDao - SELECT MAX(id) FROM t_pet
- 2010-04-30 13:12:33,501 [main] DEBUG org.nutz.dao.impl.NutDao - INSERT INTO t_pet(age,name) VALUES( 0, 'Cat 2')
- 2010-04-30 13:12:33,501 [main] DEBUG org.nutz.dao.impl.NutDao - SELECT MAX(id) FROM t_pet
- 2010-04-30 13:12:33,502 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Initiating transaction commit
- 2010-04-30 13:12:33,502 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Committing JDBC transaction on Connection [jdbc:mysql://127.0.0.1:3306/zdtest, UserName=root@localhost, MySQL-AB JDBC Driver]
- 2010-04-30 13:12:33,529 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Releasing JDBC Connection [jdbc:mysql://127.0.0.1:3306/zdtest, UserName=root@localhost, MySQL-AB JDBC Driver] after transaction
- 2010-04-30 13:12:33,529 [main] DEBUG org.springframework.jdbc.datasource.DataSourceUtils - Returning JDBC Connection to DataSource
2010-04-30 13:12:33,498 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Creating new transaction with name [cn.zj.pubinfo.nutz.pet.IPetService.createTwoCat]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
2010-04-30 13:12:33,498 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Acquired Connection [jdbc:mysql://127.0.0.1:3306/zdtest, UserName=root@localhost, MySQL-AB JDBC Driver] for JDBC transaction
2010-04-30 13:12:33,499 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Switching JDBC Connection [jdbc:mysql://127.0.0.1:3306/zdtest, UserName=root@localhost, MySQL-AB JDBC Driver] to manual commit
2010-04-30 13:12:33,499 [main] DEBUG org.nutz.dao.impl.NutDao - INSERT INTO t_pet(age,name) VALUES( 0, 'Cat 1')
2010-04-30 13:12:33,500 [main] DEBUG org.nutz.dao.impl.NutDao - SELECT MAX(id) FROM t_pet
2010-04-30 13:12:33,501 [main] DEBUG org.nutz.dao.impl.NutDao - INSERT INTO t_pet(age,name) VALUES( 0, 'Cat 2')
2010-04-30 13:12:33,501 [main] DEBUG org.nutz.dao.impl.NutDao - SELECT MAX(id) FROM t_pet
2010-04-30 13:12:33,502 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Initiating transaction commit
2010-04-30 13:12:33,502 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Committing JDBC transaction on Connection [jdbc:mysql://127.0.0.1:3306/zdtest, UserName=root@localhost, MySQL-AB JDBC Driver]
2010-04-30 13:12:33,529 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Releasing JDBC Connection [jdbc:mysql://127.0.0.1:3306/zdtest, UserName=root@localhost, MySQL-AB JDBC Driver] after transaction
2010-04-30 13:12:33,529 [main] DEBUG org.springframework.jdbc.datasource.DataSourceUtils - Returning JDBC Connection to DataSource
事务失败的日志:
- 2010-04-30 13:15:17,438 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Creating new transaction with name [cn.zj.pubinfo.nutz.pet.IPetService.createTwoCat]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
- 2010-04-30 13:15:17,439 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Acquired Connection [jdbc:mysql://127.0.0.1:3306/zdtest, UserName=root@localhost, MySQL-AB JDBC Driver] for JDBC transaction
- 2010-04-30 13:15:17,439 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Switching JDBC Connection [jdbc:mysql://127.0.0.1:3306/zdtest, UserName=root@localhost, MySQL-AB JDBC Driver] to manual commit
- 2010-04-30 13:15:17,440 [main] DEBUG org.nutz.dao.impl.NutDao - INSERT INTO t_pet(age,name) VALUES( 0, 'Cat 1')
- 2010-04-30 13:15:17,440 [main] DEBUG org.nutz.dao.impl.NutDao - SELECT MAX(id) FROM t_pet
- 2010-04-30 13:15:17,441 [main] DEBUG org.nutz.dao.impl.NutDao - INSERT INTO t_pet(age,name) VALUES( 0, 'Cat 2')
- 2010-04-30 13:15:17,442 [main] DEBUG org.nutz.dao.impl.NutDao - SELECT MAX(id) FROM t_pet
- 2010-04-30 13:15:17,442 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Initiating transaction rollback
- 2010-04-30 13:15:17,442 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Rolling back JDBC transaction on Connection [jdbc:mysql://127.0.0.1:3306/zdtest, UserName=root@localhost, MySQL-AB JDBC Driver]
- 2010-04-30 13:15:17,465 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Releasing JDBC Connection [jdbc:mysql://127.0.0.1:3306/zdtest, UserName=root@localhost, MySQL-AB JDBC Driver] after transaction
- 2010-04-30 13:15:17,465 [main] DEBUG org.springframework.jdbc.datasource.DataSourceUtils - Returning JDBC Connection to DataSource
- java.lang.RuntimeException: 测试Nutz DAO和spring集成事务回滚异常
- at cn.zj.pubinfo.nutz.pet.PetService.createTwoCat(PetService.java:35)
- ......
2010-04-30 13:15:17,438 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Creating new transaction with name [cn.zj.pubinfo.nutz.pet.IPetService.createTwoCat]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
2010-04-30 13:15:17,439 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Acquired Connection [jdbc:mysql://127.0.0.1:3306/zdtest, UserName=root@localhost, MySQL-AB JDBC Driver] for JDBC transaction
2010-04-30 13:15:17,439 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Switching JDBC Connection [jdbc:mysql://127.0.0.1:3306/zdtest, UserName=root@localhost, MySQL-AB JDBC Driver] to manual commit
2010-04-30 13:15:17,440 [main] DEBUG org.nutz.dao.impl.NutDao - INSERT INTO t_pet(age,name) VALUES( 0, 'Cat 1')
2010-04-30 13:15:17,440 [main] DEBUG org.nutz.dao.impl.NutDao - SELECT MAX(id) FROM t_pet
2010-04-30 13:15:17,441 [main] DEBUG org.nutz.dao.impl.NutDao - INSERT INTO t_pet(age,name) VALUES( 0, 'Cat 2')
2010-04-30 13:15:17,442 [main] DEBUG org.nutz.dao.impl.NutDao - SELECT MAX(id) FROM t_pet
2010-04-30 13:15:17,442 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Initiating transaction rollback
2010-04-30 13:15:17,442 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Rolling back JDBC transaction on Connection [jdbc:mysql://127.0.0.1:3306/zdtest, UserName=root@localhost, MySQL-AB JDBC Driver]
2010-04-30 13:15:17,465 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Releasing JDBC Connection [jdbc:mysql://127.0.0.1:3306/zdtest, UserName=root@localhost, MySQL-AB JDBC Driver] after transaction
2010-04-30 13:15:17,465 [main] DEBUG org.springframework.jdbc.datasource.DataSourceUtils - Returning JDBC Connection to DataSource
java.lang.RuntimeException: 测试Nutz DAO和spring集成事务回滚异常
at cn.zj.pubinfo.nutz.pet.PetService.createTwoCat(PetService.java:35)
......
日志表明,并查询了数据库证明,spring声明式事物工作正常。