首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

Nutz DAO与spring集成议论

2012-10-18 
Nutz DAO与spring集成讨论关注Nutz已经有段时间了,一直没有时间仔细研究Nutz。这几天抽空研究了下Nutz DAO

Nutz DAO与spring集成讨论
    关注Nutz已经有段时间了,一直没有时间仔细研究Nutz。这几天抽空研究了下Nutz DAO部分,总体上觉得Nutz的质量令人振奋,Nutz DAO部分也非常好用。
    目前个人觉得Nutz DAO在事务管理方面设计得不够好,有待改进,可以参考Nutz 网站上本人提的Issue(http://code.google.com/p/nutz/issues/detail?id=162)。主要的问题是:事务控制的代码和业务逻辑代码耦合在一起。解决的方法应该大致有两种:
    1、通过Issue中讨论的,采用@Tran注解;
    2、和Ioc部分配合,采用声明式事物管理;
    个人更喜欢声明式事物管理方式,而spring提供了非常好的声明式事物管理方案,所以在这里主要讨论下Nutz DAO和spring集成的细节问题。

    Nutz DAO和spring集成也有两种方式:
    1、采用spring的Ioc,但是事务还是采用Nutz自己管理控制;
    2、采用spring的声明式事务管理控制;
    接下来我们仔细讨论下这两种方式。
    方式1:方式1非常简单,Nutz DAO不需要做任何修改即能完成,你可以在你的项目的spring配置文件中添加如下配置即可:

<!-- the DataSource --><bean id="dataSource" 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" ref="dataSource"/></bean><!-- your service object that refer to the Nutz DAO --><bean id="petService" ref="dao"/></bean>

    这种模式下,spring只提供了Ioc,事务还是有Nutz自己管理和控制。

    方式2:
    我们要在spring中声明事务管理,大致可以如下:
<!-- Nutz DAO --><bean id="dao" ref="dataSource"/></bean><bean id="petDao" ref="dao"/></bean><!-- this is the service object that we want to make transactional --><bean id="petService" 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 executionof 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" 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" 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;elsethrow 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;elsethrow 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_DEFAULT2010-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 transaction2010-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 commit2010-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_pet2010-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_pet2010-04-30 13:12:33,502 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Initiating transaction commit2010-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 transaction2010-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_DEFAULT2010-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 transaction2010-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 commit2010-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_pet2010-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_pet2010-04-30 13:15:17,442 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Initiating transaction rollback2010-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 transaction2010-04-30 13:15:17,465 [main] DEBUG org.springframework.jdbc.datasource.DataSourceUtils - Returning JDBC Connection to DataSourcejava.lang.RuntimeException: 测试Nutz DAO和spring集成事务回滚异常at cn.zj.pubinfo.nutz.pet.PetService.createTwoCat(PetService.java:35)......

    日志表明,并查询了数据库证明,spring声明式事物工作正常。

    本人对Nutz的研究还很肤浅,有不正确之处请大家指正。

    最后我想说一下对Nutz的感受:虽然很小(代码量少),但是很强大,很灵活。而且Nutz的开发团队非常积极和活跃,相信Nutz会越来越好!

感谢对Nutz的支持~~~

我改改代码,然后给你看看import java.sql.Connection;import org.nutz.dao.ConnCallback;import org.springframework.jdbc.datasource.DataSourceUtils;/** * @author hzzdong * */public class SpringNutDao extends NutDao {@Overridepublic void run(ConnCallback callback) {Connection con = DataSourceUtils.getConnection(getDataSource());try {callback.invoke(con);} catch (Exception e) {if (e instanceof RuntimeException)throw (RuntimeException) e;elsethrow new RuntimeException(e);} finally {DataSourceUtils.releaseConnection(con, getDataSource());}}}
因为感觉这样对使用者更直观,使用者不用关注NutDao内部实现细节就能知道在spring中该如何配置。
一点愚见,有兴趣的可提出自己的看法,谢谢! 7 楼 sunshine_boy 2011-09-26   5 楼 hzzdong  的方法比较认同。不需要修改(破坏)原nutz包,而且符合面向对象。 8 楼 江恂泽 2012-06-27   还是很多雾水.....望给联系方式.

热点排行