学习笔记-Springs声明性JDBC事务管理
近日在看台湾人林信良的《Spring技术手册》,这本书总体上简单易懂,适合初学者。但是在声明性JDBC事务管理这节中的例子程序写的不够详细。下来看看并略加修改了下。
首先,在MySQL中建立一个表myuser。注意要让MySQL支持事务,要选择InnoDB类型的表。
Create table myuser(
id int (11) not null auto_increment primary key,
name varchar(100) not null default '',
age int
)type=InnoDB;
这里有个实体类user.java:
package
onlyfun.caterpillar;
public class User {
private Integer id;
private String name;
private Integer age;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
为了面向接口编程,我们实现一个接口,让DAO类实现这个接口。
public class User {
private Integer id;
private String name;
private Integer age;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
package
onlyfun.caterpillar;
public interface IUserDAO {
public void insert(User user);
public User find(Integer id);
}
具体的DAO类如下:在这个类中我们模拟事务处理。
public interface IUserDAO {
public void insert(User user);
public User find(Integer id);
}
package
onlyfun.caterpillar;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.jdbc.core.JdbcTemplate;
public class UserDAO implements IUserDAO {
private JdbcTemplate jdbcTemplate;
public void setDataSource(DataSource dataSource) {
jdbcTemplate = new JdbcTemplate(dataSource);
}
public void insert(User user) {//在这个方法中我们执行了数据插入和数据查询两个操作,用来模拟事务操作。我们故意在查询的语句中把数据库表写成smyuser。
//这样,在insert方法执行过程中,会由于查询语句出错而撤销之前的插入语句的效果。
String name = user.getName();
int age = user.getAge().intValue();
jdbcTemplate.update("INSERT INTO myuser (name,age) "
+ "VALUES('" + name + "'," + age + ")");
List rows = jdbcTemplate.queryForList(
"SELECT * FROM smyuser WHERE id=4");
Iterator it = rows.iterator();
if(it.hasNext()) {
Map userMap = (Map) it.next();
Integer i = new Integer(userMap.get("id").toString());
String names = userMap.get("name").toString();
Integer ages = new Integer(userMap.get("age").toString());
User users = new User();
users.setId(i);
users.setName(name);
users.setAge(age);
System.out.println("names: " + users.getName());
}
}
public User find(Integer id) {
List rows = jdbcTemplate.queryForList(
"SELECT * FROM myuser WHERE id=" + id.intValue());
Iterator it = rows.iterator();
if(it.hasNext()) {
Map userMap = (Map) it.next();
Integer i = new Integer(userMap.get("id").toString());
String name = userMap.get("name").toString();
Integer age = new Integer(userMap.get("age").toString());
User user = new User();
user.setId(i);
user.setName(name);
user.setAge(age);
return user;
}
return null;
}
}
然后,在具体测试类中我们这样:
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.jdbc.core.JdbcTemplate;
public class UserDAO implements IUserDAO {
private JdbcTemplate jdbcTemplate;
public void setDataSource(DataSource dataSource) {
jdbcTemplate = new JdbcTemplate(dataSource);
}
public void insert(User user) {//在这个方法中我们执行了数据插入和数据查询两个操作,用来模拟事务操作。我们故意在查询的语句中把数据库表写成smyuser。
//这样,在insert方法执行过程中,会由于查询语句出错而撤销之前的插入语句的效果。
String name = user.getName();
int age = user.getAge().intValue();
jdbcTemplate.update("INSERT INTO myuser (name,age) "
+ "VALUES('" + name + "'," + age + ")");
List rows = jdbcTemplate.queryForList(
"SELECT * FROM smyuser WHERE id=4");
Iterator it = rows.iterator();
if(it.hasNext()) {
Map userMap = (Map) it.next();
Integer i = new Integer(userMap.get("id").toString());
String names = userMap.get("name").toString();
Integer ages = new Integer(userMap.get("age").toString());
User users = new User();
users.setId(i);
users.setName(name);
users.setAge(age);
System.out.println("names: " + users.getName());
}
}
public User find(Integer id) {
List rows = jdbcTemplate.queryForList(
"SELECT * FROM myuser WHERE id=" + id.intValue());
Iterator it = rows.iterator();
if(it.hasNext()) {
Map userMap = (Map) it.next();
Integer i = new Integer(userMap.get("id").toString());
String name = userMap.get("name").toString();
Integer age = new Integer(userMap.get("age").toString());
User user = new User();
user.setId(i);
user.setName(name);
user.setAge(age);
return user;
}
return null;
}
}
package
onlyfun.caterpillar;
import org.springframework.context.ApplicationContext;
import org.springframework.context.
support.FileSystemXmlApplicationContext;
public class SpringDAODemo {
public static void main(String[] args) {
ApplicationContext context =
new FileSystemXmlApplicationContext(
"beans-config.xml");
User user = new User();
user.setName("1matthew");
user.setAge(new Integer(30));
IUserDAO userDAO =
(IUserDAO) context.getBean("userDAOProxy");
userDAO.insert(user);
user = userDAO.find(new Integer(16));
System.out.println("name: " + user.getName());
}
}
最后,我们来看配置文件:在这个文件中我们注入事务管理。
import org.springframework.context.ApplicationContext;
import org.springframework.context.
support.FileSystemXmlApplicationContext;
public class SpringDAODemo {
public static void main(String[] args) {
ApplicationContext context =
new FileSystemXmlApplicationContext(
"beans-config.xml");
User user = new User();
user.setName("1matthew");
user.setAge(new Integer(30));
IUserDAO userDAO =
(IUserDAO) context.getBean("userDAOProxy");
userDAO.insert(user);
user = userDAO.find(new Integer(16));
System.out.println("name: " + user.getName());
}
}
<?
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" destroy-method ="close" >
< property name ="driverClassName" >
< value > com.mysql.jdbc.Driver </ value >
</ property >
< property name ="url" >
< value > jdbc:mysql://localhost:3306/test </ value >
</ property >
< property name ="username" >
< value > root </ value >
</ property >
< property name ="password" >
< value > 131421 </ value >
</ property >
</ bean >
< bean id ="transactionManager" class ="org.springframework.jdbc.datasource.DataSourceTransactionManager" >
< property name ="dataSource" >
< ref bean ="dataSource" />
</ property >
</ bean >
< bean id ="userDAO" class ="onlyfun.caterpillar.UserDAO" >
< property name ="dataSource" >
< ref bean ="dataSource" />
</ property >
</ bean >
< bean id ="userDAOProxy" class ="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" >
< property name ="proxyInterfaces" >
< list >
< value > onlyfun.caterpillar.IUserDAO </ value >
</ list >
</ property >
< property name ="target" >
< ref bean ="userDAO" />
</ property >
< property name ="transactionManager" >
< ref bean ="transactionManager" />
</ property >
< property name ="transactionAttributes" >
< props >
< prop key ="insert*" > PROPAGATION_REQUIRED </ prop >
</ props >
</ property >
</ bean >
</ beans >
datasource这个bean中我们配置了数据源的相关属性。在userDAOProxy这个bean中,我们配置了target、transactionManager、transactionAttributes属性。在transactionAttributes中,我们指定所有insert*方法中操作会注入事务管理。
<! 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" destroy-method ="close" >
< property name ="driverClassName" >
< value > com.mysql.jdbc.Driver </ value >
</ property >
< property name ="url" >
< value > jdbc:mysql://localhost:3306/test </ value >
</ property >
< property name ="username" >
< value > root </ value >
</ property >
< property name ="password" >
< value > 131421 </ value >
</ property >
</ bean >
< bean id ="transactionManager" class ="org.springframework.jdbc.datasource.DataSourceTransactionManager" >
< property name ="dataSource" >
< ref bean ="dataSource" />
</ property >
</ bean >
< bean id ="userDAO" class ="onlyfun.caterpillar.UserDAO" >
< property name ="dataSource" >
< ref bean ="dataSource" />
</ property >
</ bean >
< bean id ="userDAOProxy" class ="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" >
< property name ="proxyInterfaces" >
< list >
< value > onlyfun.caterpillar.IUserDAO </ value >
</ list >
</ property >
< property name ="target" >
< ref bean ="userDAO" />
</ property >
< property name ="transactionManager" >
< ref bean ="transactionManager" />
</ property >
< property name ="transactionAttributes" >
< props >
< prop key ="insert*" > PROPAGATION_REQUIRED </ prop >
</ props >
</ property >
</ bean >
</ beans >
程序的运行结果是,由于在insert方法中的查询语句出错,会引起之前的insert语句效果被撤销。你也可以把查询语句先设置正确,看看效果。