使用Spring进行事务管理——转账案例

搭建环境

  1. 启动Mysql:管理员身份打开cmd,输入指令net start mysql

  2. 创建数据库及账户表:

create database spring_day03;
use spring_day03;
create table account(
  id int primary key auto_increment,
  username varchar(50),
  money INT
);

insert into account(username,money) values('jack','10000');
insert into account(username,money) values('rose','10000');
  1. 导入jar包到MyEclipse
     核心:4+1
     aop : 4 (aop联盟、spring aop、aspectj规范、spring aspect)
     数据库:2 (jdbc/tx)
     驱动:mysql
     连接池:c3p0
    在这里插入图片描述

    包很多!所以我找全后上传到了网盘,可自取
    链接:https://pan.baidu.com/s/1BPUa5VexRO5SsTvLbLOL6g
    提取码:n0mp

  2. 在MyEclipse里面创建Dao层和Service层
    (1)Dao层
    dao接口:

package com.lovejava.dao;
/**
 * @Description Spring实现转账案例————dao层:接口中有汇款和收款抽象方法
 */
public interface AccountDao {
	/*
	 汇款
	 */
	public void out(String outer,Integer money);
	/*
	收款
	 */
	public void in(String inner,Integer money);

}

dao接口实现类(继承JdbcDaoSupport类)

package com.lovejava.dao.impl;

import org.springframework.jdbc.core.support.JdbcDaoSupport;
import com.lovejava.dao.AccountDao;

public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao {   //通过继承JdbcDaoSupport类来实现Dao

	//实现汇款方法
	public void out(String outer, Integer money) {
		this.getJdbcTemplate().update("update account set money=money-? where username=?", money,outer);
	}
	//实现收款方法
	public void in(String inner, Integer money) {
		this.getJdbcTemplate().update("update account set money=money+? where username=?", money,inner);
	}

}

(2)Service层
Service接口

package com.lovejava.service;
/**
 * @Description service层:具体的用户转账操作
 */
public interface AccountService {
	/**
	 * @Description 转账
	 */
	public void transfer(String outer,String inner,Integer money);

}

Service接口实现类:

package com.lovejava.service.Impl;

import com.lovejava.dao.AccountDao;
import com.lovejava.service.AccountService;

public class AccountServiceImpl implements AccountService {
	//转账要使用到Dao
	private AccountDao accountDao;
	public void setAccountDao(AccountDao accountDao){
		this.accountDao=accountDao;
	}

	public void transfer(String outer, String inner, Integer money) {
		accountDao.out(outer, money);
		accountDao.in(inner, money);	
	}
}

配置文件:applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
                           http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/aop 
                           http://www.springframework.org/schema/aop/spring-aop.xsd
                           http://www.springframework.org/schema/context 
       					   http://www.springframework.org/schema/context/spring-context.xsd">

     <!-- 连接数据库 -->
     <!-- 1 datasource -->
     <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
           <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
           <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/spring_day03"></property>
           <property name="user" value="root"></property>
           <property name="password" value="root123"></property>
     </bean>
     
    <!-- 2 Dao -->
    <bean id="accountDao" class="com.lovejava.dao.impl.AccountDaoImpl">
          <property name="dataSource" ref="dataSource"></property>
    </bean>
    
    <!-- 3 Service -->
    <bean id="accountService" class="com.lovejava.service.Impl.AccountServiceImpl">
          <property name="accountDao" ref="accountDao"></property>
    </bean>
</beans>

测试Bean是否注入成功:

package com.lovejava;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.lovejava.service.AccountService;

/**
 * @Description 测试配置文件
 * @author zxx
 * @version v0.0
 * @date 2019-7-27
 */
public class TestApp {
	@Test
	public void demo01(){
		String xmlPath="applicationContext.xml";
		ApplicationContext applicationContext=new ClassPathXmlApplicationContext(xmlPath);
		AccountService accountService=(AccountService)applicationContext.getBean("accountService");
		accountService.transfer("jack", "rose", 1000);  //jack给rose转账1000元
	}

}

运行后,数据库中表数据确实改变了:
执行前
执行后

AOP配置(全自动)

在spring xml 配置aop 自动生成代理,进行事务的管理
三步骤:

  1. 配置管理器
  2. 配置事务详情
  3. 配置AOP

方法1:AOP基于XML

只需要修改XML文件,添加事务管理(包括上面的三个步骤:配置管理器、事务详情、AOP)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       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/aop 
                           http://www.springframework.org/schema/aop/spring-aop.xsd
                           http://www.springframework.org/schema/context 
       					   http://www.springframework.org/schema/context/spring-context.xsd
       					   http://www.springframework.org/schema/tx 
       					   http://www.springframework.org/schema/tx/spring-tx.xsd">

     <!-- 连接数据库 -->
     <!-- 1 datasource -->
     <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
           <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
           <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/spring_day03"></property>
           <property name="user" value="root"></property>
           <property name="password" value="root123"></property>
     </bean>
     
    <!-- 2 Dao -->
    <bean id="accountDao" class="com.lovejava.dao.impl.AccountDaoImpl">
          <property name="dataSource" ref="dataSource"></property>
    </bean>
    
    <!-- 3 Service -->
    <bean id="accountService" class="com.lovejava.service.Impl.AccountServiceImpl">
          <property name="accountDao" ref="accountDao"></property>
    </bean>
    
    <!-- 4 事务管理 -->
    <!-- 4.1 事务管理器 -->
    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    
    
    <!-- 4.2 事务详情 (事务通知),在AOP筛选的基础上对ABC三个方法确定使用什么样的事务。例如,AC读写,B只读  等
        tx:attributes 用于配置事务详情(属性)
           tx:method name="" 详情的具体配置
                 name:转账方法     
                 propagation传播行为
                 isolation隔离级别
           -->
    <tx:advice id="txAdvice" transaction-manager="txManager">
        <tx:attributes>
           <tx:method name="transfer" propagation="REQUIRED" isolation="DEFAULT"/>
        </tx:attributes>
    </tx:advice>
    
    
    <!-- 4.3 AOP编程:目标类ABCD四个方法(四个连接点),切入点表达式确定增强的连接器,从而获得切入点:ABC -->
    <aop:config>
       <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.lovejava.service..*.*(..))"/>
    </aop:config>
    
</beans>

方法2:AOP基于注解(最简单的方式)

这种方法需要做的事:

  1. 配置事务管理器,将并事务管理器交予spring
  2. 在目标类或目标方法添加注解即可 @Transactional

1.配置事务管理器,将并事务管理器交予spring

<!-- 4 事务管理 基于注解-->
    <!-- 4.1 事务管理器 -->
    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    
    <!-- 4.2 将管理器交予spring 
    * transaction-manager 配置事务管理器
		* proxy-target-class=true : 底层强制使用cglib 代理
    -->
   <tx:annotation-driven transaction-manager="txManager" />

2.AccountServiceImpl类中添加注解()

package com.lovejava.service.Impl;

import org.springframework.transaction.annotation.Transactional;     //添加注解

import com.lovejava.dao.AccountDao;
import com.lovejava.service.AccountService;

@Transactional
public class AccountServiceImpl implements AccountService {
	//转账要使用到Dao
	private AccountDao accountDao;
	public void setAccountDao(AccountDao accountDao){
		this.accountDao=accountDao;
	}

	public void transfer(String outer, String inner, Integer money) {
		accountDao.out(outer, money);
		accountDao.in(inner, money);	

	}

}

使用注解时,在注解后面加括号,括号内可以描述事务详情
在这里插入图片描述

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值