spring frame 事务回滚的测试

 我的环境配置
Mysql :server version: 5.0.45-Debian_1ubuntu3.1-log Debian etch distribution
Spring frame: 2.0
jdk 1.6
数据库的配置:
--  MySQL Administrator dump 1.4
--
--
 ------------------------------------------------------
--
 Server version    5.0.45-Debian_1ubuntu3.1-log


/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */ ;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */ ;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */ ;
/*!40101 SET NAMES utf8 */ ;

/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */ ;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */ ;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */ ;


--
--
 Create schema SQLMapStudy
--

CREATE   DATABASE   IF   NOT   EXISTS  SQLMapStudy;
USE  SQLMapStudy;

--
--
 Definition of table `SQLMapStudy`.`ORDER`
--

DROP   TABLE   IF   EXISTS  `SQLMapStudy`.` ORDER `;
CREATE   TABLE   `SQLMapStudy`.` ORDER ` (
  `id` 
int ( 11 NOT   NULL  auto_increment,
  `
level int ( 11 default   ' 0 ' ,
  `name` 
text ,
  
PRIMARY   KEY   (`id`)
) ENGINE
= InnoDB AUTO_INCREMENT = 42   DEFAULT  CHARSET = latin1;

--
--
 Dumping data for table `SQLMapStudy`.`ORDER`
--

/*!40000 ALTER TABLE `ORDER` DISABLE KEYS */ ;
LOCK TABLES `
ORDER ` WRITE;
INSERT   INTO  `SQLMapStudy`.` ORDER VALUES   ( 24 , 5 , ' 233571 ' ),
 (
25 , 3 , ' 237607 ' ),
 (
26 , 4 , ' 951320 ' ),
 (
27 , 4 , ' 3981449 ' ),
 (
28 , 3 , ' 4201861 ' ),
 (
29 , 3 , ' 4286204 ' ),
 (
30 , 4 , ' 4467730 ' ),
 (
31 , 4 , ' 4577921 ' ),
 (
32 , 4 , ' 4644267 ' ),
 (
33 , 4 , ' 4676767 ' ),
 (
34 , 4 , ' 8718591 ' ),
 (
35 , 4 , ' 1200488898355 ' ),
 (
36 , 3 , ' 1200489291189 ' ),
 (
37 , 3 , ' 1200489506119 ' ),
 (
38 , 3 , ' 1200490058635 ' ),
 (
41 , 4 , ' 1200490554236 ' );
UNLOCK TABLES;
/*!40000 ALTER TABLE `ORDER` ENABLE KEYS */ ;




/*!40101 SET SQL_MODE=@OLD_SQL_MODE */ ;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */ ;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */ ;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */ ;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */ ;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */ ;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */ ;
要注意的问题:ENGINE=InnoDB

数据库映射对象类Order
/*
 * Copyright (C) 2000-2007 Wang Pengcheng <wpc0000@gmail.com>
 * Licensed to the Wang Pengcheng under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The LGPL licenses this file to You under the GNU Lesser General Public
 * Licence, Version 2.0  (the "License"); you may not use this file except in
 * compliance with the License.  You may obtain a copy of the License at
 *
 *     
http://www.gnu.org/licenses/lgpl.txt
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 
*/

// Edit 15 Jan 2008
package  com.studyspring.ch5;

public   class  Order  {
    
private int id;
    
private int level;
    
private String name;
    
public int getId() {
        
return id;
    }

    
public void setId(int id) {
        
this.id = id;
    }

    
public int getLevel() {
        
return level;
    }

    
public void setLevel(int level) {
        
this.level = level;
    }

    
public String getName() {
        
return name;
    }

    
public void setName(String name) {
        
this.name = name;
    }

    
}

实现RowMapper:
/*
 * Copyright (C) 2000-2007 Wang Pengcheng <wpc0000@gmail.com>
 * Licensed to the Wang Pengcheng under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The LGPL licenses this file to You under the GNU Lesser General Public
 * Licence, Version 2.0  (the "License"); you may not use this file except in
 * compliance with the License.  You may obtain a copy of the License at
 *
 *     
http://www.gnu.org/licenses/lgpl.txt
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 
*/

// Edit 15 Jan 2008
package  com.studyspring.ch5;

import  java.sql.ResultSet;
import  java.sql.SQLException;

import  org.springframework.jdbc.core.RowMapper;

public   class  OrderRowMapper  implements  RowMapper  {

    
public Object mapRow(ResultSet rs, int index) throws SQLException {
        Order order 
= new Order();
        order.setId(rs.getInt(
"id"));
        order.setLevel(rs.getInt(
"level"));
        order.setName(rs.getString(
"name"));
        
return order;
    }


}


为了使用和扩展的方便使用了一些接口
package  com.studyspring.ch5;

import  java.util.List;

public   interface  IUserDAO  {
    
public List<Order> getUserList();
    
public Order makeOrder(String name);
    
public void changelevel(int userid);

}

// /
package  com.studyspring.ch5;

public   interface  IUserManager  {
    
public boolean processOrder(String name);

}

以上是一些几本的类,下面就是一些和事务有关的具体实现了。
用于DAO的类:
/*
 * Copyright (C) 2000-2007 Wang Pengcheng <wpc0000@gmail.com>
 * Licensed to the Wang Pengcheng under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The LGPL licenses this file to You under the GNU Lesser General Public
 * Licence, Version 2.0  (the "License"); you may not use this file except in
 * compliance with the License.  You may obtain a copy of the License at
 *
 *     
http://www.gnu.org/licenses/lgpl.txt
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 
*/

// Edit 15 Jan 2008
package  com.studyspring.ch5;

import  java.util.List;

import  org.springframework.dao.DataAccessResourceFailureException;
import  org.springframework.jdbc.core.JdbcTemplate;

public   class  UserDAOImpl  implements  IUserDAO  {
    
    
private String sql;
    
private JdbcTemplate jdbcTemplate;
    

    
public void changelevel(int userid) {
        Object[] param 
= new Object[]{new Integer(userid)};
        sql 
= "update `ORDER` set level=level+1 where id=?";
        jdbcTemplate.update(sql,param);
    }


    
public List<Order> getUserList() {
        
// TODO Auto-generated method stub
        return null;
    }


    
public Order makeOrder(String name) {
        Order order 
= new Order();
        Object[] param 
= new Object[]{new Integer(3),new String(name)};
        sql
="insert into `ORDER`"
            
+"(level,name) value"
            
+"(?,?)";
        
int rowcount = jdbcTemplate.update(sql, param);
        
        
if(rowcount==1){
            sql
="select * from `ORDER`";
            List list 
= jdbcTemplate.query(sql, new OrderRowMapper());
            order 
=(Order)list.get(list.size()-1);
        }

        
throw new DataAccessResourceFailureException(sql);//如果要人为制造异常可以用这种方式抛出以检验回滚机制
                
//个人检测好象是任何异常都可以,这个任意是指:运行时异常还有spring的DataAccessResourceException的子类
        
//return order;
    }


    
public JdbcTemplate getJdbcTemplate() {
        
return jdbcTemplate;
    }


    
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        
this.jdbcTemplate = jdbcTemplate;
    }


}


业务逻辑类:
/*
 * Copyright (C) 2000-2007 Wang Pengcheng <wpc0000@gmail.com>
 * Licensed to the Wang Pengcheng under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The LGPL licenses this file to You under the GNU Lesser General Public
 * Licence, Version 2.0  (the "License"); you may not use this file except in
 * compliance with the License.  You may obtain a copy of the License at
 *
 *     
http://www.gnu.org/licenses/lgpl.txt
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 
*/

// Edit 15 Jan 2008
package  com.studyspring.ch5;

import  org.apache.commons.logging.Log;
import  org.apache.commons.logging.LogFactory;
import  org.springframework.dao.DataAccessException;
import  org.springframework.transaction.PlatformTransactionManager;
import  org.springframework.transaction.TransactionDefinition;
import  org.springframework.transaction.TransactionStatus;
import  org.springframework.transaction.support.DefaultTransactionDefinition;

import  com.studyspring.ch3.Advice4Hello;

public   class  UserManagerImpl  implements  IUserManager  {
    
private Log log = LogFactory.getLog(Advice4Hello.class);
    
private IUserDAO userDAO;
    
private PlatformTransactionManager manager;

    
public boolean processOrder(String name) {
        DefaultTransactionDefinition td 
= new DefaultTransactionDefinition(
                TransactionDefinition.PROPAGATION_REQUIRED);
        td.setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE);
        td.setTimeout(
500);
        TransactionStatus status 
= manager.getTransaction(td);//记录回滚前状态

        
try{
            Order order 
= userDAO.makeOrder(name);
            userDAO.changelevel(order.getId());
            log.info(
"The order level changing: "+order.getName());
        }
catch (DataAccessException e) {
            manager.rollback(status);
//启动回滚
            log.warn("Order error");
            
throw e;
        }

        manager.commit(status);
//正常结束,写数据库
        return true;
    }


    
public IUserDAO getUserDAO() {
        
return userDAO;
    }


    
public void setUserDAO(IUserDAO userDAO) {
        
this.userDAO = userDAO;
    }


    
public PlatformTransactionManager getManager() {
        
return manager;
    }


    
public void setManager(PlatformTransactionManager manager) {
        
this.manager = manager;
    }


}


xml配置文件:
需要注意的是:
         < property  name ="defaultAutoCommit" >
            
< value > false </ value >
        
</ property >
<? xml version="1.0" encoding="UTF-8" ?>
< beans  xmlns ="http://www.springframework.org/schema/beans"
    xmlns:xsi
="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation
="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd" >
    
< 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:3306/SpringStudy </ value >
        
</ property >

        
< property  name ="username" >
            
< value > mysql user name </ value >
        
</ property >

        
< property  name ="password" >
            
< value > mysql password </ value >
        
</ property >

        
< property  name ="defaultAutoCommit" >
            
< value > false </ value >
        
</ property >
        
    
</ bean >

    
< bean  id ="jdbcTemplate"
        class
="org.springframework.jdbc.core.JdbcTemplate" >
        
< property  name ="dataSource" >
            
< ref  local ="dataSource" />
        
</ property >
    
</ bean >

    
< bean  id ="transactionManager"
        class
="org.springframework.jdbc.datasource.DataSourceTransactionManager" >

        
< property  name ="dataSource" >
            
< ref  local ="dataSource"   />
        
</ property >
    
</ bean >

    
< bean  id ="userOimpl"  class ="com.studyspring.ch5.UserDAOImpl" >
        
< property  name ="jdbcTemplate" >
            
< ref  local ="jdbcTemplate" />
        
</ property >
    
</ bean >

    
< bean  id ="userManager"
        class
="com.studyspring.ch5.UserManagerImpl" >

        
< property  name ="userDAO" >
            
< ref  local ="userOimpl" />
        
</ property >

        
< property  name ="manager" >
            
< ref  local ="transactionManager" />
        
</ property >
    
</ bean >

</ beans >

最终的运行程序
package  com.studyspring.ch5;

import  org.springframework.context.ApplicationContext;
import  org.springframework.context.support.FileSystemXmlApplicationContext;

public   class  PogrammaticTrans  {

    
/**
     * 
@param args
     
*/

    
public static void main(String[] args) {
        ApplicationContext ctx 
= new FileSystemXmlApplicationContext(
                
"/src/com/studyspring/ch5/configch5.xml");
        IUserManager userManager 
= (IUserManager) ctx.getBean("userManager");
        System.err.print(userManager.processOrder(Long.toString(System.currentTimeMillis())));
    }


}


如果要用TransactionTemplate这要注意异常捕获的位置和层次关系
package  com.studyspring.ch5;

import  org.apache.commons.logging.Log;
import  org.apache.commons.logging.LogFactory;
import  org.springframework.dao.DataAccessException;
import  org.springframework.transaction.PlatformTransactionManager;
import  org.springframework.transaction.TransactionDefinition;
import  org.springframework.transaction.TransactionStatus;
import  org.springframework.transaction.support.DefaultTransactionDefinition;
import  org.springframework.transaction.support.TransactionCallback;
import  org.springframework.transaction.support.TransactionTemplate;

import  com.studyspring.ch3.Advice4Hello;

public   class  UserManagerImplWTT  implements  IUserManager  {
    
private Log log = LogFactory.getLog(Advice4Hello.class);
    
private IUserDAO userDAO;
    
private PlatformTransactionManager manager;

    
public boolean processOrder(final String name) {
        TransactionTemplate tt 
= new TransactionTemplate(manager);
        tt.setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE);
        tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        tt.setTimeout(
500);

        
try {
            tt.execute(
new TransactionCallback() {

                
public Object doInTransaction(TransactionStatus status) {
                    Order order 
= new Order();
                    order 
= userDAO.makeOrder(name);
                    userDAO.changelevel(order.getId());
                    log.info(
"Finish :" + order.getName());
                    
return order;
                }


            }
);
        }
 catch (Exception e) {
                
//添加这个捕获的原因是:一般我们不会将异常抛给系统,而是利用AOP进行统一处理。
               
//如果在 doInTransaction里面捕获则不会回滚。

        }

        
return true;
    }


    
public IUserDAO getUserDAO() {
        
return userDAO;
    }


    
public void setUserDAO(IUserDAO userDAO) {
        
this.userDAO = userDAO;
    }


    
public PlatformTransactionManager getManager() {
        
return manager;
    }


    
public void setManager(PlatformTransactionManager manager) {
        
this.manager = manager;
    }


}


以上运行后会抛出异常,并且数据库id变化,但是没有数据加入。这就是回滚机制的作用。
感谢spring为我们解决了很多。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值