Spring框架 XML配置事务控制的步骤操作
作者:Hudie.
这篇文章主要介绍了Spring框架 XML配置事务控制的步骤操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
基于 XML 的声明式事务控制
1.环境搭建
拷贝必要的 jar 包到工程的 lib 目录
2.创建 spring 的配置文件并导入约束
这里直接给出本次测试的全部XML配置,具体细节在后面依次介绍。
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" 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.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd "> <!-- 配置连接池对象 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="com.mysql.jdbc.Driver" /> <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/mybase2" /> <property name="user" value="root" /> <property name="password" value="Hudie" /> </bean> <!-- 配置JdbcTemplate模板对象 --> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- dao --> <bean id="userDao" class="com.gql.dao.UserDaoImp"> <property name="jdbcTemplate" ref="jdbcTemplate"></property> </bean> <!-- service --> <bean id="userService" class="com.gql.service.UserServiceImp"> <property name="userDao" ref="userDao"></property> </bean> <!-- 事务类/切面 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 通知: 1.告诉Spring容器采用哪种事务管理机制. 2.告诉Spring容器目标方法采用什么样的事务处理策略. --> <tx:advice id="tx" transaction-manager="transactionManager"> <tx:attributes> <!-- name 规定目标方法 isolation 事务隔离级别,默认是default propagation 传播机制,默认是REQUIREL --> <tx:method name="save" isolation="DEFAULT" propagation="REQUIRED" read-only="false" /> <tx:method name="up*" isolation="DEFAULT" propagation="REQUIRED" read-only="false" /> <tx:method name="de*" isolation="DEFAULT" propagation="REQUIRED" read-only="false" /> <tx:method name="get*" isolation="DEFAULT" propagation="REQUIRED" read-only="true" /> </tx:attributes> </tx:advice> <aop:config> <aop:pointcut expression="execution (* com.gql.service.UserServiceImp.*(..))" id="point" /> <aop:advisor advice-ref="tx" pointcut-ref="point" /> </aop:config> </beans>
3.准备数据库表和实体类
user数据库表
create database mybase2; USE mybase2; CREATE TABLE `user` ( `id` INT(10) NOT NULL AUTO_INCREMENT COMMENT '主键', `name` VARCHAR(20) NOT NULL DEFAULT '0', `age` INT(10) NOT NULL DEFAULT '0', PRIMARY KEY (`id`) ) COLLATE='utf8_general_ci' ENGINE=InnoDB ; INSERT INTO user values(NULL,'周冬雨',21); INSERT INTO user values(NULL,'马冬梅',18); INSERT INTO user values(NULL,'马西梅',19);
User实体类
package com.gql.entity; import java.io.Serializable; /** * 类说明: * User实体类 * @guoqianliang1998. */ public class User implements Serializable { /** * 生成序列号 */ private static final long serialVersionUID = -4492760954899814333L; private int id; private String name; private int age; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
4.业务层接口与实现类
业务层接口
package com.gql.service; import java.util.List; import com.gql.entity.User; /** * 类说明: * 业务层接口 * @guoqianliang1998. */ public interface UserService { void save(User user); void update(int id, User user); void delete(int id); User getUser(int id); List<User> getUserList(int[] ids); List<User> getUserList(); }
业务层实现类
package com.gql.service; import java.util.List; import com.gql.dao.UserDao; import com.gql.entity.User; /** * 类说明: * 业务层实现类 * @guoqianliang1998. */ public class UserServiceImp implements UserService { private UserDao userDao; public void setUserDao(UserDao userDao) { this.userDao = userDao; } @Override public void save(User user) { userDao.save(user); int i = 1/0; } @Override public void update(int id, User user) { userDao.update(id, user); } @Override public void delete(int id) { userDao.delete(id); } @Override public User getUser(int id) { User user = userDao.getUser(id); return user; } @Override public List<User> getUserList(int[] ids) { List<User> userList = userDao.getUserList(ids); return userList; } @Override public List<User> getUserList() { List<User> list = userDao.getUserList(); return list; } }
5.数据访问层接口与实现类
数据访问层接口
package com.gql.dao; import java.util.List; import com.gql.entity.User; /** * 类说明: * 数据访问层接口 * @guoqianliang1998. */ public interface UserDao { void save(User user); void update(int id, User user); void delete(int id); User getUser(int id); List<User> getUserList(int[] ids); List<User> getUserList(); }
数据访问层实现类
package com.gql.dao; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import com.gql.RowMapper.UserRowMapper; import com.gql.entity.User; /** * 类说明: * 数据访问层实现类 * @guoqianliang1998. */ public class UserDaoImp implements UserDao { private JdbcTemplate jdbcTemplate; public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } @Override public void save(User user) { String sql = "INSERT INTO user values(NULL,?,?)"; jdbcTemplate.update(sql, user.getName(), user.getAge()); } @Override public void update(int id, User user) { String sql = "update user set name=?,age=? WHERE id = ?"; jdbcTemplate.update(sql, user.getName(), user.getAge(), id); } @Override public void delete(int id) { String sql = "DELETE FROM user WHERE id = ?;"; jdbcTemplate.update(sql, id); } @Override public User getUser(int id) { String sql = "select * from user where id = ?"; User user = jdbcTemplate.queryForObject(sql, new RowMapper<User>() { @Override public User mapRow(ResultSet rs, int rowNum) throws SQLException { User user = new User(); user.setId(rs.getInt(1)); user.setName(rs.getString(2)); user.setAge(rs.getInt(3)); return user; } }, id); return user; } @Override public List<User> getUserList(int[] ids) { String sql = "select * from user where id in(:ids)"; NamedParameterJdbcTemplate n = new NamedParameterJdbcTemplate(jdbcTemplate.getDataSource()); Map<String,Object> paramMap = new HashMap<String,Object>(); List list = new ArrayList(); for (int i = 0; i < ids.length; i++) { list.add(ids[i]); } paramMap.put("ids", list); List<User> userList = n.query(sql, paramMap, new RowMapper<User>(){ @Override public User mapRow(ResultSet rs, int rowNum) throws SQLException { User user = new User(); user.setId(rs.getInt(1)); user.setName(rs.getString(2)); user.setAge(rs.getInt(3)); return user; } }); return userList; // 第二种写法↓↓↓ // StringBuilder sb = new StringBuilder(); // sb.append("SELECT * FROM user WHERE id = ?"); // for(int i=0;i<ids.length-1;i++){ // sb.append(" or id = ?"); // } // Integer[] in = new Integer[ids.length]; // for(int i=0;i<ids.length;i++){ // in[i] = ids[i]; // } // Object[] args = in; // List<User> userList = jdbcTemplate.query(sb.toString(),args,new RowMapper() { // // @Override // public Object mapRow(ResultSet rs, int rowNum) throws SQLException { // User user = new User(); // user.setId(rs.getInt(1)); // user.setName(rs.getString(2)); // user.setAge(rs.getInt(3)); // return user; // } // }); // return userList; } @Override public List<User> getUserList() { String sql = "select * from user"; List<User> list = jdbcTemplate.query(sql, new UserRowMapper()); return list; } }
6.配置c3p0数据源/业务层/数据访问层
配置c3p0数据源
<!-- 配置连接池对象 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="com.mysql.jdbc.Driver" /> <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/mybase2" /> <property name="user" value="root" /> <property name="password" value="Hudie" /> </bean> <!-- 配置JdbcTemplate模板对象 --> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"></property> </bean>
业务层
<!-- service --> <bean id="userService" class="com.gql.service.UserServiceImp"> <property name="userDao" ref="userDao"></property> </bean>
数据访问层
<!-- dao --> <bean id="userDao" class="com.gql.dao.UserDaoImp"> <property name="jdbcTemplate" ref="jdbcTemplate"></property> </bean>
7.配置事务管理器
<!-- 事务管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <!-- 注入 DataSource--> <property name="dataSource" ref="dataSource"></property> </bean>
8.配置事务的通知
事务的通知:
- 配置事务的通知来引用事务管理器
- 告诉Spring容器采用哪种事务管理机制.
- 告诉Spring容器目标方法采用什么样的事务处理策略.
<!-- 事务的通知: 1.告诉Spring容器采用哪种事务管理机制. 2.告诉Spring容器目标方法采用什么样的事务处理策略. --> <tx:advice id="tx" transaction-manager="transactionManager"> <tx:attributes> <!-- name 规定目标方法 isolation 事务隔离级别,默认是default propagation 传播机制,默认是REQUIREL --> <tx:method name="save" isolation="DEFAULT" propagation="REQUIRED" read-only="false" /> </tx:attributes> </tx:advice>
通知内配置事务的属性
属性 | 说明 |
---|---|
read-only | 是否是只读事务。默认 false,不只读。 |
isolation | 指定事务的隔离级别。默认值是使用数据库的默认隔离级别。 |
propagation | 指定事务的传播行为。 |
timeout | 指定超时时间。默认值为:-1。永不超时。 |
rollback-for | 用于指定一个异常,当执行产生该异常时,事务回滚。产生其他异常,事务不回滚。没有默认值,任何异常都回滚。 |
no-rollback-for | 用于指定一个异常,当产生该异常时,事务不回滚,产生其他异常时,事务回 |
滚。没有默认值,任何异常都回滚。 |
9.配置 AOP 切入点表达式
<!-- AOP切入点表达式 --> <aop:config> <aop:pointcut expression="execution (* com.gql.service.UserServiceImp.*(..))" id="point" /> <!-- 切入点表达式和事务的对应关系 --> <aop:advisor advice-ref="tx" pointcut-ref="point" /> </aop:config>
10.配置切入点表达式和事务通知的对应关系
<!-- AOP切入点表达式 --> <aop:config> <aop:pointcut expression="execution (* com.gql.service.UserServiceImp.*(..))" id="point" /> <!-- 切入点表达式和事务的对应关系 --> <aop:advisor advice-ref="tx" pointcut-ref="point" /> </aop:config>
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。