spring整合ibatis事务管理(各种AOP,比较乱)


Spring通过DAO模式,提供了对iBATIS的良好支持。SqlMapClient对象是iBATIS中的主要对象,我们可以通过配置让spring来管理SqlMapClient对象的创建。

 

与hibernate类似,Spring 提供了SqlMapClientDaoSupport对象,我们的DAO可以继承这个类,通过它所提供的SqlMapClientTemplate对象来操纵数据库。看起来这些概念都与hibernate类似。

 

通过SqlMapClientTemplate来操纵数据库的CRUD是没有问题的,这里面关键的问题是事务处理。Spring提供了强大的声明式事务处理的功能,我们已经清楚hibernate中如何配置声明式的事务,那么在iBATIS中如何获得声明式事务的能力呢?

 

第一,我们需要了解的是spring通过AOP来拦截方法的调用,从而在这些方法上面添加声明式事务处理的能力。典型配置如下:applicationContext-common.xml

 

Xml代码   收藏代码
  1. <!-- 配置事务特性 -->  
  2.   
  3. <tx:advice id="txAdvice" transaction-manager="事务管理器名称">  
  4.   
  5.     <tx:attributes>  
  6.   
  7.        <tx:method name="add*" propagation="REQUIRED"/>  
  8.   
  9.        <tx:method name="del*" propagation="REQUIRED"/>  
  10.   
  11.        <tx:method name="update*" propagation="REQUIRED"/>  
  12.   
  13.        <tx:method name="*" read-only="true"/>  
  14.   
  15.    </tx:attributes>  
  16.   
  17. </tx:advice>  
  18.   
  19.   
  20.   
  21. <!-- 配置哪些类的方法需要进行事务管理 -->  
  22.   
  23. <aop:config>  
  24.   
  25.    <aop:pointcut id="allManagerMethod" expression="execution(* com.ibatis.manager.*.*(..))"/>  
  26.   
  27.    <aop:advisor advice-ref="txAdvice" pointcut-ref="allManagerMethod"/>  
  28.   
  29. </aop:config>  

 

 

这些事务都是声明在业务逻辑层的对象上的。

 

第二,我们需要一个事务管理器,对事务进行管理。

 

Xml代码   收藏代码
  1. <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">  
  2.   
  3.     <property name="dataSource" ref="dataSource"/>  
  4.   
  5.     </bean>  
  6.   
  7.     <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">  
  8.   
  9.         <property name="driverClassName" value="com.mysql.jdbc.Driver"/>  
  10.   
  11.         <property name="url" value="jdbc:mysql://127.0.0.1/ibatis"/>  
  12.   
  13.         <property name="username" value="root"/>  
  14.   
  15.         <property name="password" value="mysql"/>  
  16.   
  17.     </bean>  

 

 

 

此后,我们需要让spring来管理SqlMapClient对象:

 

 

 

Xml代码   收藏代码
  1. <bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">  
  2.   
  3.        <property name="configLocation"><value>classpath:sqlMapConfig.xml</value></property>  
  4.   
  5.     </bean>  

 

 

我们的sqlMapConfig.xml就可以简写为:

 

 

Xml代码   收藏代码
  1. <?xml version="1.0" encoding="UTF-8" ?>  
  2.   
  3. <!DOCTYPE sqlMapConfig        
  4.   
  5.     PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"        
  6.   
  7.     "http://ibatis.apache.org/dtd/sql-map-config-2.dtd">  
  8.   
  9. <sqlMapConfig>  
  10.   
  11.     <settings   
  12.   
  13.        lazyLoadingEnabled="true"  
  14.   
  15.         useStatementNamespaces="true" />  
  16.   
  17.     <!-- 使用spring之后,数据源的配置移植到了spring上,所以iBATIS本身的配置可以取消 -->  
  18.   
  19.   <sqlMap resource="com/ibatis/dao/impl/ibatis/User.xml"/>  
  20.   
  21. </sqlMapConfig>  

 

 

User.xml:如下

 

Xml代码   收藏代码
  1. <?xml version="1.0" encoding="UTF-8" ?>  
  2.   
  3. <!DOCTYPE sqlMap        
  4.   
  5.     PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"        
  6.   
  7.     "http://ibatis.apache.org/dtd/sql-map-2.dtd">  
  8.   
  9. <sqlMap namespace="User">  
  10.   
  11.  <!-- Use type aliases to avoid typing the full classname every time. -->  
  12.   
  13.  <typeAlias alias="User" type="com.ibatis.User"/>  
  14.   
  15.  <!-- Select with no parameters using the result map for Account class. -->  
  16.   
  17.  <select id="selectAllUsers" resultClass="User">  
  18.   
  19.     select * from t_user  
  20.   
  21.  </select>  
  22.   
  23.    
  24.   
  25.  <select id="selectUser" resultClass="User" parameterClass="int">  
  26.   
  27.   select * from t_user where id=#id#  
  28.   
  29.  </select>  
  30.   
  31.    
  32.   
  33.  <insert id="insertUser" parameterClass="User">  
  34.   
  35.   insert into t_user values (  
  36.   
  37.        null,#username#,#password#  
  38.   
  39.   )  
  40.   
  41.  </insert>  
  42.   
  43.    
  44.   
  45.  <update id="updateUser" parameterClass="User">  
  46.   
  47.   update t_user set username = #username#,password=#password#  
  48.   
  49.   where id=#id#  
  50.   
  51.   </update>  
  52.   
  53.    
  54.   
  55.  <delete id="deleteUser" parameterClass="int">  
  56.   
  57.   delete from t_user where id=#id#  
  58.   
  59.  </delete>  
  60.   
  61. </sqlMap>  

 

 

我们的DAO的编写:

 

Java代码   收藏代码
  1. package com.iabtis.dao.impl.ibatis;  
  2.   
  3. import java.util.List;  
  4.   
  5. import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport;  
  6.   
  7. import com.ibatis.dao.UserDAO;  
  8.   
  9. import com.ibatis.crm.model.User;  
  10.   
  11. public class UserDAOImpl extends SqlMapClientDaoSupport implements UserDAO {  
  12.   
  13.     public void select(User user) {  
  14.   
  15.               getSqlMapClientTemplate().delete("selectUser ",user.getId());  
  16.   
  17.        }  
  18.   
  19.    public List findAll() {  
  20.   
  21.               return getSqlMapClientTemplate().queryForList("selectAllUsers ");  
  22.   
  23.        }  
  24.   
  25.        public void delete(User user) {  
  26.   
  27.               getSqlMapClientTemplate().delete("deleteUser ",user.getId());  
  28.   
  29.        }  
  30.   
  31.        public void save(User user) {  
  32.   
  33.               getSqlMapClientTemplate().insert("insertUser ",user);  
  34.   
  35.        }  
  36.   
  37.        public void update(User user) {  
  38.   
  39.               getSqlMapClientTemplate().update("updateUser ",user);  
  40.   
  41.        }  
  42.   
  43. }  

 

 

 

继承SqlMapClientDaoSupport,要求我们注入SqlMapClient对象,因此,需要有如下的DAO配置:

 

Xml代码   收藏代码
  1. <bean id="userDAO" class="com.ibatils.dao.impl.ibatis.UserDAOImpl">  
  2.   
  3.      <property name=”sqlMapClient” ref=”sqlMapClient”/>  
  4.   
  5. </bean>  

 

 

 

这就是所有需要注意的问题了,此后就可以在业务逻辑层调用DAO对象了!


<?xml version="1.0" encoding="UTF-8"?>
<beans  
xmlns="http://www.springframework.org/schema/beans"  
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
xmlns:aop="http://www.springframework.org/schema/aop"  
xmlns:tx="http://www.springframework.org/schema/tx"  
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd  
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd  
http://www.springframework.org/schema/tx 
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">  
    
    <!-- 数据源配置 -->
    <bean id="dataSource"
        class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName"
            value="net.sourceforge.jtds.jdbc.Driver">
        </property>
        <property name="url"
            value="jdbc:jtds:sqlserver://localhost:1433;DatabaseName=dbName;SelectMethod=cursor">
        </property>
        <property name="username" value="sa"></property>
        <property name="password" value="sa"></property>
    </bean>
    
    <!-- Spring iBatis Template -->
    <bean id="sqlMapClient"
        class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
        <property name="configLocation" value="classpath:config/SqlMapConfig.xml" />
        <property name="dataSource" ref="dataSource" />
    </bean>
    
    <!-- 事务管理 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"></property>
    </bean>
    
    <!-- 声明式事务管理 -->
    <bean id="baseTransactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true">
        <property name="transactionManager" ref="transactionManager"></property>
        <property name="transactionAttributes">
            <props>
                <prop key="add*">PROPAGATION_REQUIRED</prop>            
                <prop key="edit*">PROPAGATION_REQUIRED</prop>
                <prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
            </props>
        </property>
    </bean>

   <!-- 注意该DAO 一定要继承SqlMapClientDaoSupport 使用getSqlMapClientTemplate()方法,并且要抛出 throws DataAccessException 异常 spring才能捕获并回滚 -->
    <bean id="UserDAO" class="com.gong.struts.test.UserDAO">
        <property name="sqlMapClient" ref="sqlMapClient"></property>
    </bean>
    
    <bean id="UserManager" parent="baseTransactionProxy">
        <property name="target">
            <bean class="com.gong.struts.test.UserManager">
                <property name="userdao" ref="UserDAO"></property>
            </bean>
        </property>
    </bean>

</beans>




<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi
="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:aop
="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation
="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd ">
    
<!-- DataSource -->
    
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method
="close">
        
<property name="driverClassName">
            
<value>com.mysql.jdbc.Driver</value>
        
</property>
        
<property name="url">
            
<value>jdbc:mysql://localhost/test</value>
        
</property>
        
<property name="username">
            
<value>root</value>
        
</property>
        
<property name="password">
            
<value>mysql</value>
        
</property>
    
</bean>
    
<!-- Spring iBatis Template -->
    
<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
        
<property name="configLocation" value="SqlMapConfig.xml" />
        
<property name="dataSource" ref="dataSource" />
    
</bean>
    
<bean id="transactionManager"
        class
="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        
<property name="dataSource" ref="dataSource" />
    
</bean>
    
<!-- 需要引入aop的命名空间 -->
    
<aop:config>
        
<!-- 切入点指明了在所有方法产生事务拦截操作 -->
        
<aop:pointcut id="serviceMethods"
            expression
="execution(* com.angi.ibatis.service.*.*(..))" />
        
<!-- 定义了将采用何种拦截操作,这里引用到 txAdvice -->
        
<aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethods" />
    
</aop:config>
    
<!-- 需要引入tx的命名空间 -->
    
<!-- 这是事务通知操作,使用的事务管理器引用自 transactionManager -->
    
<tx:advice id="txAdvice" transaction-manager="transactionManager">
        
<tx:attributes>
            
<!-- 指定哪些方法需要加入事务,这里懒惰一下全部加入,可以使用通配符来只加入需要的方法 -->
            
<tx:method name="*" propagation="REQUIRED" />
        
</tx:attributes>
    
</tx:advice>
    
<bean id="userDAO" class="com.angi.ibatis.dao.UserDaoImpl">
        
<property name="sqlMapClient">
            
<ref bean="sqlMapClient" />
        
</property>
    
</bean>
    
<bean id="userService" class="com.angi.ibatis.service.UserService">
        
<property name="userDao">
            
<ref bean="userDAO" />
        
</property>
    
</bean>
</beans>





  Spring下由三种途径对事物进行管理:编程式事务管理、声明式事务管理和AOP事务管理。其中AOP事务管理又分AOP注解事务管理和AOP XML配置两种,这里记录下述其中的AOP XML配置管理,这也是spring最推荐的方式。

  参照<spring高级程序设计>中的银行转账的例子。

1.Spring的数据源设置

Xml代码   收藏代码
  1. <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" >  
  2.   <property name="driverClassName" value="com.mysql.jdbc.Driver"/>  
  3.   <property name="url" value="jdbc:mysql://localhost:3306/test"/>  
  4.   <property name="username" value="root"/>  
  5.   <property name="password" value="123456"/>  
  6. </bean>  

 2.Spring对iBATIS的支持

   Spring对ibatis主要提供org.springframework.orm.ibatis.SqlMapClientFactoryBean类来进行支持  

Xml代码   收藏代码
  1. <bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">  
  2.   <property name="dataSource" ref="dataSource"/>  
  3.   <property name="configLocation" value="/config/sqlMapConfig.xml"/>  
  4. </bean>  

  3.Spring对iBATIS DAO的支持

  Spring提供org.springframework.orm.ibatis.support.SqlMapClientDaoSupport来对iBATIS DAO进行支持,通过调用该类的getSqlMapClientTemplate()方法来获得对iBATIS的控制访问。

Xml代码   收藏代码
  1. <bean id="accountDao" class="com.hj.dao.AccountDaoImp">  
  2.    <property name="sqlMapClient" ref="sqlMapClient"/>  
  3. </bean>     

 

Xml代码   收藏代码
  1. <bean id="bankService" class="com.hj.bankOps.DefaultBankService">  
  2.    <property name="accountDao" ref="bankAccountDao"/>  
  3. </bean>  

   这里DefaultBankService类主要实现BankService接口(提供服务的方法定义),其内部引用一个BankAccountDao实例来对数据库进行访问。BankAccountDao类主要继承SqlMapClientDaoSupport。

 4.Spring 配置事务  

Xml代码   收藏代码
  1. <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">  
  2.      <property name="dataSource" ref="dataSource"/>  
  3.   </bean>   

  5.AOP XML配置事务管理

    1).配置事务通知

Xml代码   收藏代码
  1. <tx:advice id="transactionManagerAdivice" transaction-manager="transactionManager">  
  2.    <tx:attributes>  
  3.       <tx:method name="*"   
  4.                 isolation="READ_COMMITTED"   
  5.                 propagation="REQUIRED"   
  6.                 rollback-for="java.lang.RuntionException" />  
  7.    </tx:attributes>  
  8. </tx:advice>  

   2).配置切入点和方面

Xml代码   收藏代码
  1. <aop:config>  
  2.    <aop:pointcut expression="execution(* com.hj.bankOps.DefaultBankService.*(..))" id="bankServicePc"/>  
  3.    <aop:advisor advice-ref="transactionManagerAdivice" pointcut-ref="bankServicePc"/>    
  4.  </aop:config>  

  上述execution(* com.hj.bankOps.DefaultBankService.*(..))表达式表示切入点为该类中的任何方法。所以当DefaultBankService类中方法调用时就会进行事务管理,并且当抛出RuntimeException时,自动进行回滚操作。

  6.遇到的问题

   在<Spring高级程序设计>一书上,对AOP XML事务配置时,其通知部分并没有设置具体属性(缺少 rollback-for="java.lang.RuntionException"

Xml代码   收藏代码
  1. <tx:attributes>  
  2.       <tx:method name="*"   
  3.                 isolation="READ_COMMITTED"   
  4.                 propagation="REQUIRED"   
  5.                />  
  6.    </tx:attributes>  

 这样在DefaultBankService方法调用中如果有异常抛出,事务并不进行相应回滚操作。





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值