Spring 事务 (xml配置aop、注解事务)

1.spring事务是基于aop思想实现的,即aop事务

  • spring封装了事务管理代码
  • 事务操作:打开事务,提交事务,回滚事务
  • 事务操作对象:因为在不同平台,操作事务的代码各不相同.spring提供了一个接口,PlatformTransactionManager 接口
  1. DataSourceTransactionManager
  2. HibernateTransitionmanager
  3. 注意:在spring事务管理.最为核心的对象就是TransactionManager对象
  • spring管理事务的属性介绍

1.事务得隔离级别:

  1 读未提交
  2 读已提交
  4 可重复读
  8 串行化

2,是否只读

true 只读
false 可操作

3,事务的传播行为

 2.xml实现aop事务

(需要先了解spring aop面向切面编程)

1.在spring配置文件中配置通知:   


<!--在spring中玩事务管理.最为核心的对象就是TransactionManager对象  -->
	<!-- 配置事务管理器 -->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource" />
	</bean>
<!-- 配置事物通知 -->
	<tx:advice id="transactionAdvice" transaction-manager="transactionManager">
		<tx:attributes>
			<!--以方法为单位,指定方法应用什么事务属性  -->
			<!--isolation隔离级别  propagation传播行为  read-only是否只读  -->
			<tx:method name="add*" isolation="DEFAULT" propagation="REQUIRED" read-only="false" />
			<tx:method name="append*" isolation="DEFAULT" propagation="REQUIRED" read-only="false"/>
			<tx:method name="insert*" isolation="DEFAULT" propagation="REQUIRED" read-only="false" />
			<tx:method name="save*" isolation="DEFAULT" propagation="REQUIRED" read-only="false" />
			
			<tx:method name="update*" isolation="DEFAULT" propagation="REQUIRED" read-only="false" />
			<tx:method name="modify*" isolation="DEFAULT" propagation="REQUIRED" read-only="false" />
			<tx:method name="edit*" isolation="DEFAULT" propagation="REQUIRED" read-only="false"/>
			
			<tx:method name="delete*" isolation="DEFAULT" propagation="REQUIRED" read-only="false" />
			<tx:method name="remove*" isolation="DEFAULT" propagation="REQUIRED" read-only="false" />
			<tx:method name="repair" isolation="DEFAULT" propagation="REQUIRED" read-only="false" />
			<tx:method name="delAndRepair" isolation="DEFAULT" propagation="REQUIRED" read-only="false" />

			<tx:method name="get*" isolation="DEFAULT" propagation="REQUIRED" read-only="true" />
			<tx:method name="find*" isolation="DEFAULT" propagation="REQUIRED" read-only="true" />
			<tx:method name="load*" isolation="DEFAULT" propagation="REQUIRED" read-only="true" />
			<tx:method name="search*" isolation="DEFAULT" propagation="REQUIRED" read-only="true" />
			<tx:method name="datagrid*" isolation="DEFAULT" propagation="REQUIRED" read-only="true" />

		</tx:attributes>
	</tx:advice>

2.配置将通知织入目标

<!-- 配置织入 -->
	<aop:config>
	        <!-- 将service层需要事务的方法作为切点 -->
		<aop:pointcut id="transactionPointcut" expression="execution(* com.sj.service.imp.*DerviceImp.*(..))" />
		<!--配置切面 通知+切点-->
		<aop:advisor pointcut-ref="transactionPointcut" advice-ref="transactionAdvice" />
	</aop:config>

3.书写dao以及实现dao

public interface UserDao {
	
	void save(User u); 
	void delete(Integer id);
	void update(User u);
	User getUser(Integer id);
	List<User> getAllUser();
	void updateAddMoney(Integer id,Double money);
	void updatereduceMoney(Integer id,Double money);
	

}
public class UserDaoImp extends JdbcDaoSupport implements UserDao {

	@Override
	public void save(User u) {
		String sql = "insert into user (name,money) values(?,?)";
		super.getJdbcTemplate().update(sql, u.getName(), u.getMoney());

	}

	@Override
	public void delete(Integer id) {
		String sql = "delete from user where id = ?";
		super.getJdbcTemplate().update(sql, id);
	}

	@Override
	public void update(User u) {
		String sql = "update user set name = ? where id = ? ";
		super.getJdbcTemplate().update(sql, u.getName(), u.getId());
	}

	@Override
	public User getUser(Integer id) {
		String sql = "select * from user where id = ?";
		User u = super.getJdbcTemplate().queryForObject(sql, new RowMapper<User>() {

			@Override
			public User mapRow(ResultSet rs, int arg1) throws SQLException {
				User u = new User();
				u.setId(rs.getInt("id"));
				u.setName(rs.getString("name"));
				u.setMoney(rs.getDouble("money"));
				return u;
			}
		}, id);
		return u;
	}

	@Override
	public List<User> getAllUser() {
		String sql = "select * from user ";
		List<User> u = super.getJdbcTemplate().query(sql, new RowMapper<User>() {

			@Override
			public User mapRow(ResultSet rs, int arg1) throws SQLException {
				User u = new User();
				u.setId(rs.getInt("id"));
				u.setName(rs.getString("name"));
				u.setMoney(rs.getDouble("money"));
				return u;
			}
		});
		return u;
	}

	@Override
	public void updateAddMoney(Integer id, Double money) {
		String sql = "update user set money=money + ? where id=?";
		super.getJdbcTemplate().update(sql, money, id);
	}

	@Override
	public void updatereduceMoney(Integer id, Double money) {
		String sql = "update user set money=money - ? where id=?";
		super.getJdbcTemplate().update(sql, money, id);

	}

}

 3.书写service以及实现

扫描二维码关注公众号,回复: 4861949 查看本文章
public interface UserService {

	void updateMoney(Integer from, Integer to, Double money);

	void updateMoney2(Integer from, Integer to, Double money);

	public User getUser(Integer id);

}
public class UserServiceImp implements UserService {

	private UserDao userDao;

	@Override
	public User getUser(Integer id) {
		User u = userDao.getUser(id);
		return u;
	}

	// 转钱
	@Override
	public void updateMoney(Integer from, Integer to, Double money) {
		userDao.updatereduceMoney(from, money);
		userDao.updateAddMoney(to, money);

	}

	// 转钱 异常
	@Override
	public void updateMoney2(Integer from, Integer to, Double money) {
		userDao.updatereduceMoney(from, money);
		// 模拟异常
		int s = 1;
		int i = s / 0;
		userDao.updateAddMoney(to, money);

	}

	public void setUserDao(UserDao userDao) {
		this.userDao = userDao;
	}

}

 4.注入dao,service到spring

        <!-- 引入外部文文件 -->
	<context:property-placeholder location="classpath:db.properties"/>
	<!--配置连接池  -->
	<bean name="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
		<property name="url" value="${jdbc.url}"></property>
		<property name="username" value="${jdbc.username}"></property>
		<property name="password" value="${jdbc.password}"></property>
	</bean>
	
	
	<!-- Dao -->
	<bean name="userDao" class="com.sj.dao.imp.UserDaoImp">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	<!-- Service -->
	<bean name="userService" class="com.sj.service.imp.UserServiceImp">
		<property name="userDao" ref="userDao"></property>
	</bean>

4.完整spirng配置文件

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
	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-4.0.xsd
	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
	http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
	http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">
	
	<!-- 引入外部文文件 -->
	<context:property-placeholder location="classpath:db.properties"/>
	<!--配置连接池  -->
	<bean name="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
		<property name="url" value="${jdbc.url}"></property>
		<property name="username" value="${jdbc.username}"></property>
		<property name="password" value="${jdbc.password}"></property>
	</bean>
	
	
	<!-- Dao -->
	<bean name="userDao" class="com.sj.dao.imp.UserDaoImp">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	<!-- Service -->
	<bean name="userService" class="com.sj.service.imp.UserServiceImp">
		<property name="userDao" ref="userDao"></property>
	</bean>
	
	<!--在spring中玩事务管理.最为核心的对象就是TransactionManager对象  -->
	<!-- 配置事务管理器 -->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource" />
	</bean>

	
	<!-- 配置事物通知 -->
	<tx:advice id="transactionAdvice" transaction-manager="transactionManager">
		<tx:attributes>
			<!--以方法为单位,指定方法应用什么事务属性  -->
			<!--isolation隔离级别  propagation传播行为  read-only是否只读  -->
			<tx:method name="add*" isolation="DEFAULT" propagation="REQUIRED" read-only="false" />
			<tx:method name="append*" isolation="DEFAULT" propagation="REQUIRED" read-only="false"/>
			<tx:method name="insert*" isolation="DEFAULT" propagation="REQUIRED" read-only="false" />
			<tx:method name="save*" isolation="DEFAULT" propagation="REQUIRED" read-only="false" />
			
			<tx:method name="update*" isolation="DEFAULT" propagation="REQUIRED" read-only="false" />
			<tx:method name="modify*" isolation="DEFAULT" propagation="REQUIRED" read-only="false" />
			<tx:method name="edit*" isolation="DEFAULT" propagation="REQUIRED" read-only="false"/>
			
			<tx:method name="delete*" isolation="DEFAULT" propagation="REQUIRED" read-only="false" />
			<tx:method name="remove*" isolation="DEFAULT" propagation="REQUIRED" read-only="false" />
			<tx:method name="repair" isolation="DEFAULT" propagation="REQUIRED" read-only="false" />
			<tx:method name="delAndRepair" isolation="DEFAULT" propagation="REQUIRED" read-only="false" />

			<tx:method name="get*" isolation="DEFAULT" propagation="REQUIRED" read-only="true" />
			<tx:method name="find*" isolation="DEFAULT" propagation="REQUIRED" read-only="true" />
			<tx:method name="load*" isolation="DEFAULT" propagation="REQUIRED" read-only="true" />
			<tx:method name="search*" isolation="DEFAULT" propagation="REQUIRED" read-only="true" />
			<tx:method name="datagrid*" isolation="DEFAULT" propagation="REQUIRED" read-only="true" />

		</tx:attributes>
	</tx:advice>
	<!-- 配置织入 -->
	<aop:config>
		<!--配置切点 表达式 -->
		<!-- 将service层需要事务的方法作为切点 -->
		<aop:pointcut id="transactionPointcut" expression="execution(* com.sj.service.imp.*DerviceImp.*(..))" />
		<!--配置切面 通知+切点-->
		<aop:advisor pointcut-ref="transactionPointcut" advice-ref="transactionAdvice" />
	</aop:config>

</beans>

5.Test测试

public class SpringTest {

	@Test
	public void run3() {
		// 转钱
		ApplicationContext app = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
		UserServiceImp service =  (UserServiceImp) app.getBean("userService");
		service.updateMoney(2, 1, 100d);
	}
	@Test
	public void run4() {
		// 转钱(异常)
		ApplicationContext app = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
		UserServiceImp service =  (UserServiceImp) app.getBean("userService");
		service.updateMoney2(2, 1, 100d);
	}


}

1.执行run3,转账成功

2.执行run4(执行应该转账失败,回滚事务)

如果未配置事务结果是(执行减少自己账户前后出现异常,导致对方账户未收到)

配置事务后:

 3.注解事务:就很简单了直接添加
 <tx:annotation-driven transaction-manager="transactionManager" />

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
	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-4.0.xsd
	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
	http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
	http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">
	
	<!-- 引入外部文文件 -->
	<context:property-placeholder location="classpath:db.properties"/>
	<!--配置连接池  -->
	<bean name="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
		<property name="url" value="${jdbc.url}"></property>
		<property name="username" value="${jdbc.username}"></property>
		<property name="password" value="${jdbc.password}"></property>
	</bean>
	
	
	<!-- Dao -->
	<bean name="userDao" class="com.sj.dao.imp.UserDaoImp">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	<!-- Service -->
	<bean name="userService" class="com.sj.service.imp.UserServiceImp">
		<property name="userDao" ref="userDao"></property>
	</bean>
	
	<!--在spring中玩事务管理.最为核心的对象就是TransactionManager对象  -->
	<!-- 配置事务管理器 -->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource" />
	</bean>

	<!-- 注解方式配置事物 -->
	 <tx:annotation-driven transaction-manager="transactionManager" /> 


</beans>

2.在service用注解实现事务

//类注解给所有方法添加事务,可以直接在方法覆盖类注解事务
@Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED, readOnly = true)
public class UserServiceImp implements UserService {

	private UserDao userDao;

	public User getUser(Integer id) {
		User u = userDao.getUser(id);
		return u;
	}

	// 转钱,将只读改为false
	@Override
	@Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED, readOnly = false)
	public void updateMoney(Integer from, Integer to, Double money) {
		userDao.updatereduceMoney(from, money);
		userDao.updateAddMoney(to, money);

	}

	// 转钱 异常,将只读改为false
	@Override
	@Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED, readOnly = false)
	public void updateMoney2(Integer from, Integer to, Double money) {
		userDao.updatereduceMoney(from, money);
		// 模拟异常
		int s = 1;
		int i = s / 0;
		userDao.updateAddMoney(to, money);

	}

	public void setUserDao(UserDao userDao) {
		this.userDao = userDao;
	}

}

注解事务就ok

猜你喜欢

转载自blog.csdn.net/qq_36472252/article/details/86227650