我的环境配置
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为我们解决了很多。
Mysql :server version: 5.0.45-Debian_1ubuntu3.1-log Debian etch distribution
Spring frame: 2.0
jdk 1.6
数据库的配置:






































































数据库映射对象类Order


















































































为了使用和扩展的方便使用了一些接口

















以上是一些几本的类,下面就是一些和事务有关的具体实现了。
用于DAO的类:






































































业务逻辑类:









































































xml配置文件:
需要注意的是:



































































最终的运行程序



















如果要用TransactionTemplate这要注意异常捕获的位置和层次关系






























































以上运行后会抛出异常,并且数据库id变化,但是没有数据加入。这就是回滚机制的作用。
感谢spring为我们解决了很多。