spring的事务管理方式!

 

事务管理

要和数据库交流,事务管理是必不可少的,刚刚开始学习Spring框架,被他提供的功能吸引,确实减少了我们的编码量.

Spring,提供了多种和数据库交流的办法,我们最常用的JDBC, 现在流行的 O/R映射,含盖现在所有的和数据库交流的办法. Spring不仅给我们提供了这些方法,同时还对其进行了有效的封装,大大减少我们的公式编码工作.举例说明:

下面一段是我们学习JDBC时候,最常见的代码:

Connection conn =null;

Statement stmt = null;

try {

conn = dataSource.getConnection();

stmt = con.createStatement();

stmt.executeUpdate("UPDATE user SET age = 18 WHERE id = 'erica'");

} finally {

if (stmt != null) {

try {

stmt.close();

} catch (SQLException ex) {

logger.warn("Exception in closing JDBC Statement", ex);

}

}

if (conn != null) {

try {

conn.close();

} catch (SQLException ex) {

logger.warn("Exception in closing JDBC Connection", ex);

}

}

 

我们要为执行语句SQL写很多公式代码,这些代码都是能复制和粘贴.我们再来看看,Spring给我们提供的办法.

JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);

jdbcTemplate.update("UPDATE user SET age = 10 WHERE id = 'erica'");

就是这样两句,大大简化我们的编码工作量,把我们的精力能更多的集中在数据的逻辑上.

:这是Spring提供的JDBC访问模版,具有一定的入侵性,依赖于SpringAPI.

 

我们传统编码,不仅要管理数据库连接,还要在try/catch中控制数据库事务 ,Spring给我们提供的JdbcTemplate将事务完全封装,我们完全不需要去关心,如果出现异常,就会自动回滚.

关于怎么操作数据库,这里就不多说了,我们关心的是数据库的事务机制,在执行一组SQL的时候,如果出现错误,怎么让数据保持一致性?

Spring提供两种数据库事务管理机制:第一,是我们比较熟悉的编码方式;通过手工编码控制事务提交或者回滚;第二,是声明配置方式,通过配置事务管理,控制事务,我比较推荐使用这种办法.

下面用代码说话:

第一种: 编码方式

 

public class JdbcTest {

     /**

      * @param args

      */

     protected final Log logger = LogFactory.getLog(getClass());

     private DataSource dataSource;

     private PlatformTransactionManager transactionManager;

    

     public DataSource getDataSource() {

         return dataSource;

     }

     public void setDataSource(DataSource dataSource) {

         this.dataSource = dataSource;

     }

public PlatformTransactionManager getTransactionManager() {

         return transactionManager;

     }

     public void setTransactionManager(PlatformTransactionManager transactionManager) {

         this.transactionManager = transactionManager;

     }

     public  boolean upDate()

         TransactionTemplate tt =new TransactionTemplate(getTransactionManager());

         tt.execute(new TransactionCallback(){

              public Object doInTransaction(TransactionStatus status) {

                   JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);

                   jdbcTemplate.update("update user1 set userId='120' where userName='totti'");

                   logger.info("第一条更成完成!");

                   jdbcTemplate.update("update user1 set userId='1000' where userName='totti'");

                   logger.info("第二条更成完成!");

                   //int a=100/0;

                   return null;

              }

         });

         return true;

     }

    

}

 

 

 

 

说明下: dataSource, transactionManager 是通过bean运行期注入的.我们看下配置文件.

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>

     <bean id="dataSource"

         class="org.apache.commons.dbcp.BasicDataSource">

         <property name="driverClassName">

              <value>net.sourceforge.jtds.jdbc.Driver</value>

         </property>

         <property name="url">

              <value>jdbc:jtds:sqlserver://127.0.0.1:1433/test</value>

         </property>

         <property name="username">

              <value>sa</value>

         </property>

         <property name="password">

              <value>timeout</value>

         </property>

     </bean>

     <bean id="transactionManager"

         class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

         <property name="dataSource">

              <ref bean="dataSource" />

         </property>

     </bean>

     <bean id="jdbcTest" class="com.test.JdbcTest">

         <property name="dataSource">

              <ref bean="dataSource" />

         </property>

<property name="transactionManager">

              <ref bean="transactionManager" />

         </property>

     </bean>

</beans>

 

我们要注意这个类: class="org.springframework.jdbc.datasource.DataSourceTransactionManager"

事务管理全靠他了,根据我们的数据库连接不同,选择合适的事务管理类.

代码中有这句 //int a=100/0; 我们可以人为制造异常,看下数据库的回滚效果.

 

 

第二种方式:声明配置方式

我们也可以把事务管理的代码放置到配置文件中,为代码文件减减肥.

 

代码如下:

public class JdbcTest {

     /**

      * @param args

      */

     protected final Log logger = LogFactory.getLog(getClass());

     private DataSource dataSource;

     public DataSource getDataSource() {

         return dataSource;

     }

     public void setDataSource(DataSource dataSource) {

         this.dataSource = dataSource;

     }

     public  boolean upDate() {

                   JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);

                   jdbcTemplate.update("update user1 set userId='120' where userName='totti'");

                   logger.info("第一条更成完成!");

                   jdbcTemplate.update("update user1 set userId='1000' where userName='totti'");

                   logger.info("第二条更成完成!");

                   //int a=100/0;

              }

         return true;

     }

}

 

可以和编码方式比较下,这里我们只有SQL语句.

 

配置文件:

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>

     <bean id="dataSource"

         class="org.apache.commons.dbcp.BasicDataSource">

         <property name="driverClassName">

              <value>net.sourceforge.jtds.jdbc.Driver</value>

          </property>

         <property name="url">

              <value>jdbc:jtds:sqlserver://127.0.0.1:1433/test</value>

         </property>

         <property name="username">

              <value>sa</value>

         </property>

         <property name="password">

              <value>timeout</value>

         </property>

     </bean>

     <bean id="UserDAOProxy"

         class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">

         <property name="transactionManager">

              <ref bean="transactionManager" />

         </property>

         <property name="target">

              <ref local="jdbcTest" />

         </property>

         <property name="transactionAttributes">

              <props>

                   <prop key="insert*">PROPAGATION_REQUIRED</prop>

                   <prop key="upDate*">PROPAGATION_REQUIRED</prop>

                   <prop key="*">PROPAGATION_REQUIRED,readOnly</prop>

              </props>

         </property>

     </bean>

     <bean id="transactionManager"

         class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

         <property name="dataSource">

              <ref bean="dataSource" />

         </property>

     </bean>

     <bean id="jdbcTest" class="com.test.JdbcTest">

         <property name="dataSource">

              <ref bean="dataSource" />

         </property>

     </bean>

</beans>

 

我们不需要在代码里注入transactionManager,bean,我们声明了一个动态UserDAOProxy,他对我们的事务管理负责,也就是说,我们把代码实现的功能,通过这个bean实现了,把事务放到配置中,让我们的代码逻辑更加清晰.更好维护.

<property name="target">

              <ref local="jdbcTest" />

          </property>

这个配置需要特别说明下,需要实现事务管理的bean配置到这里.

 <property name="transactionAttributes"> 这个节点配置事务管理方式, insert*指的是以 insert开头的方法,都使用PROPAGATION_REQUIRED的事务管理方式.

代码中同样有//int a=100/0;

我们可以自己制造一个异常,看看是否会回滚.

 

下面是测试代码:

public static void main(String[] args) {

         // TODO 自动生成方法存根

         ApplicationContext ctx=new FileSystemXmlApplicationContext("src/applicationContext.xml");

         JdbcTest action = (JdbcTest)ctx.getBean("UserDAOProxy");

        boolean result=    action.upDate();

        System.out.print(result);

     }

JdbcTest action = (JdbcTest)ctx.getBean("UserDAOProxy");

这句要特别说明下,在编码方式中,这个beanJdbcTest. 配置文件中还没有UserDAOProxy ; 声明方式配置事务的时候, 我们要指定的 动态代理类 UserDAOProxy ,这里需要注意下,如果配置错误,数据库怎么也不回滚.我就犯过这样的错误.

 

本人也才开始学习Spring, 上述文章中存在错误和不足,望大家指出,会虚心改正. 希望本文对像我一样的初学者有所帮助.

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值