Spring_33_3 | 回顾:事务支持转账_三层架构/XML
1package com.tz.dao.impl;
2
3import com.tz.dao.AccountDao;
4import com.tz.domain.Account;
5import com.tz.utils.ConnectionUtils;
6import org.apache.commons.dbutils.QueryRunner;
7import org.apache.commons.dbutils.handlers.BeanListHandler;
8import java.sql.SQLException;
9import java.util.List;
10//import org.springframework.jdbc.core.BeanPropertyRowMapper;
11//import org.springframework.jdbc.core.support.JdbcDaoSupport;
12//import org.springframework.jdbc.core.JdbcTemplate;
13
14
15//public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao{
16//
17// //3.注:在方法里面加了继承"extends JdbcDaoSupport"后,就可以删除重复代码
18// private JdbcTemplate jdbcTemplate;
19//
20// public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
21// this.jdbcTemplate = jdbcTemplate;
22// }
23
24public class AccountDaoImpl implements AccountDao{
25
26 private QueryRunner runner;
27 private ConnectionUtils connectionUtils;
28
29 public void setRunner(QueryRunner runner) {
30 this.runner = runner;
31 }
32
33 public void setConnectionUtils(ConnectionUtils connectionUtils) {
34 this.connectionUtils = connectionUtils;
35 }
36
37
38 /**
39 * 按姓名查询
40 * @param accountName
41 * @return
42 */
43 // 注:拿来做参考
44 // @Override
45 // public Account findAccountByName(String accountName) {
46 // List<Account> accounts_name = super.getJdbcTemplate().query("select * from account where name=?", new BeanPropertyRowMapper<Account>(Account.class), accountName);
47 // if(accounts_name.isEmpty()){
48 // return null;
49 // }
50 // if(accounts_name.size()>1){
51 // throw new RuntimeException("结果集不唯一");
52 // }
53 // return accounts_name.get(0);
54 // }
55
56 @Override
57 public Account findAccountByName(String accountName) {
58 try {
59 //把"connectionUtils.getThreadConnection()",意思是手动开启事务连接
60 //BeanListHandler:将结果集中的每一行数据都封装到一个对应JavaBean实例中,存放到List里面.
61 List<Account> accounts_name = runner.query(connectionUtils.getThreadConnection(),"select * from account where name=?", new BeanListHandler<Account>(Account.class), accountName);
62 if(accounts_name.isEmpty()){
63 return null;
64 }
65 if(accounts_name.size()>1){
66 throw new RuntimeException("结果集不唯一");
67 }
68 return accounts_name.get(0);
69 } catch (SQLException e) {
70 throw new RuntimeException(e); //代码是从上往下执行,遇到异常后再执行下去就没意义,这是手动关闭
71 }
72 }
73
74 /**
75 * 更新
76 * @param account
77 */
78 @Override
79 public void updateAccount(Account account) {
80 try {
81 runner.update(connectionUtils.getThreadConnection(),"update account set name=?,money=? where id =?",account.getName(),account.getMoney(),account.getId());
82 } catch (SQLException e) {
83 e.printStackTrace();
84 }
85 }
86}
1package com.tz.dao;
2
3import com.tz.domain.Account;
4
5/**
6 * Created by Administrator on 2020/1/16 0016.
7 */
8public interface AccountDao {
9
10 //根据名称查询
11 Account findAccountByName(String accountName);
12 //更新
13 void updateAccount(Account account);
14}
1package com.tz.domain;
2
3/**
4 * Created by Administrator on 2020/1/16 0016.
5 */
6public class Account {
7 private Integer id;
8 private String name;
9 private Float money;
10
11 public Integer getId() {
12 return id;
13 }
14
15 public void setId(Integer id) {
16 this.id = id;
17 }
18
19 public String getName() {
20 return name;
21 }
22
23 public void setName(String name) {
24 this.name = name;
25 }
26
27 public Float getMoney() {
28 return money;
29 }
30
31 public void setMoney(Float money) {
32 this.money = money;
33 }
34
35 @Override
36 public String toString() {
37 return "Account{" +
38 "id=" + id +
39 ", name='" + name + '\'' +
40 ", money=" + money +
41 '}';
42 }
43}
1package com.tz.service.impl;
2
3import com.tz.dao.AccountDao;
4import com.tz.domain.Account;
5import com.tz.service.AccountService;
6import com.tz.utils.TransactionManager;
7
8/**
9 * Created by Administrator on 2020/1/17 0017.
10 */
11public class AccountServiceImpl implements AccountService{
12 //把持久层引进来
13 private AccountDao accountDao;
14 //事务
15 private TransactionManager txManager;
16
17 public void setAccountDao(AccountDao accountDao) {
18 this.accountDao = accountDao;
19 }
20
21 public void setTxManager(TransactionManager txManager) {
22 this.txManager = txManager;
23 }
24
25 /**
26 * 转账操作
27 * @param sourceName 转出账户名称
28 * @param targetName 转入账户名称
29 * @param money
30 */
31 @Override
32 public void transfer(String sourceName, String targetName, Float money) {
33 try {
34 //开启事务
35 txManager.beginTransaction();
36 //根据账户名查询转出账户
37 Account source = accountDao.findAccountByName(sourceName);
38 //根据账户名查询转入账户
39 Account target = accountDao.findAccountByName(targetName);
40 //转出账户减钱
41 source.setMoney(source.getMoney()-money);
42 //转入账户加钱
43 target.setMoney(target.getMoney()+money);
44 //更新转出账户
45 accountDao.updateAccount(source);
46 //模拟异常产生
47 int i = 1/0;
48 //更新转入账户
49 accountDao.updateAccount(target);
50 //提交事务
51 txManager.commit();
52 } catch (Exception e) {
53 txManager.rollback();
54 e.printStackTrace();
55 } finally {
56 //释放连接
57 txManager.release();
58 }
59 }
60}
1package com.tz.service;
2
3/**
4 * Created by Administrator on 2020/1/17 0017.
5 */
6public interface AccountService {
7 /**
8 * 转账操作
9 * @param sourceName 转出账户名称
10 * @param targetName 转入账户名称
11 * @param money
12 */
13 void transfer(String sourceName,String targetName,Float money);
14}
1package com.tz.utils;
2
3import javax.sql.DataSource;
4import java.sql.Connection;
5import java.sql.SQLException;
6
7/**
8 * 与本地/当前线程连接工具类
9 */
10public class ConnectionUtils {
11 private ThreadLocal<Connection> tl = new ThreadLocal<Connection>();
12
13 private DataSource dataSource;
14
15 public void setDataSource(DataSource dataSource) {
16 this.dataSource = dataSource;
17 }
18
19 /**
20 * 获取线程上的连接
21 * @return
22 */
23 public Connection getThreadConnection(){
24 try { //try{}catch(){}快捷键:Ctil+Alt+t , 前提是选中
25 //先从线程上拿连接
26 Connection conn = tl.get();
27 //判断当前线程上是否有连接
28 if(conn==null){
29 //从数据源中拿
30 conn = dataSource.getConnection();
31 //与当前线程绑定
32 tl.set(conn);
33 }
34 return conn;
35 } catch (SQLException e) {
36 throw new RuntimeException(e);
37 }
38 }
39
40 //把当前线程与连接解绑/移除
41 public void removeConnection(){
42 tl.remove();
43 }
44}
1package com.tz.utils;
2
3import java.sql.SQLException;
4
5/**
6 * 事务工具类
7 */
8public class TransactionManager {
9 //把线程工具类引入进来
10 private ConnectionUtils connectionUtils;
11
12 public void setConnectionUtils(ConnectionUtils connectionUtils) {
13 this.connectionUtils = connectionUtils;
14 }
15
16 /**
17 * 开启事务
18 *
19 * begin:开始
20 * Transaction:交易,业务,买卖;办理;处理
21 *
22 * connectionUtils:这是自己设置的线程工具类
23 * getThreadConnection:获取线程连接
24 * setAutoCommint:设置自动提交
25 */
26 public void beginTransaction(){
27 try {
28 connectionUtils.getThreadConnection().setAutoCommit(false);
29 } catch (SQLException e) {
30 e.printStackTrace();
31 }
32 }
33
34 /**
35 * 提交事务
36 */
37 public void commit(){
38 try {
39 connectionUtils.getThreadConnection().commit();
40 } catch (SQLException e) {
41 e.printStackTrace();
42 }
43 }
44
45 /**
46 * 回滚事务
47 */
48 public void rollback(){
49 try {
50 connectionUtils.getThreadConnection().rollback();
51 } catch (SQLException e) {
52 e.printStackTrace();
53 }
54 }
55
56 /**
57 * 释放连接
58 */
59 public void release(){
60 try {
61 connectionUtils.getThreadConnection().close();
62 connectionUtils.removeConnection(); //解绑,还到池中
63 } catch (SQLException e) {
64 e.printStackTrace();
65 }
66 }
67}
1<?xml version="1.0" encoding="UTF-8"?>
2<beans xmlns="http://www.springframework.org/schema/beans"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xsi:schemaLocation="
5 http://www.springframework.org/schema/beans
6 https://www.springframework.org/schema/beans/spring-beans.xsd">
7
8 <!--配置业务层Service-->
9 <bean id="accountService" class="com.tz.service.impl.AccountServiceImpl">
10 <property name="accountDao" ref="accountDao"></property>
11 <property name="txManager" ref="txManager"></property>
12 </bean>
13
14 <!--配置持久层Dao-->
15 <bean id="accountDao" class="com.tz.dao.impl.AccountDaoImpl">
16 <!--<property name="jdbcTemplate" ref="jdbcTemplate"></property>-->
17 <property name="runner" ref="runner"></property>
18 <property name="connectionUtils" ref="connectionUtils"></property>
19 </bean>
20
21 <!--配置事务TransactionManager-->
22 <bean id="txManager" class="com.tz.utils.TransactionManager">
23 <property name="connectionUtils" ref="connectionUtils"></property>
24 </bean>
25
26 <!--配置ConnectionUtils-->
27 <bean id="connectionUtils" class="com.tz.utils.ConnectionUtils">
28 <property name="dataSource" ref="dataSource"></property>
29 </bean>
30
31 <!--配置QueryRunner-->
32 <bean id="runner" class="org.apache.commons.dbutils.QueryRunner"></bean>
33
34 <!--配置JdbcTemplate-->
35 <!-- <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
36 <property name="dataSource" ref="dataSource"></property>
37 </bean>
38 -->
39
40 <!--配置数据源DataSource-->
41 <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"><!--这是JdbcTemplate java里面内置的配置,要配置引用-->
42 <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
43 <property name="url" value="jdbc:mysql:///test"></property>
44 <property name="username" value="root"></property>
45 <property name="password" value="root"></property>
46 </bean>
47</beans>
1package com.tz.test;
2
3import com.tz.service.AccountService;
4import org.junit.Test;
5import org.junit.runner.RunWith;
6import org.springframework.beans.factory.annotation.Autowired;
7import org.springframework.test.context.ContextConfiguration;
8import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
9
10@RunWith(SpringJUnit4ClassRunner.class) //junit单元测试
11@ContextConfiguration(locations="classpath:bean.xml") //读取bean.xml配置文件注解
12public class AccountTest {
13
14 @Autowired
15 private AccountService as;
16
17 @Test
18 public void test1(){
19 as.transfer("ccc","xiaoxiao",100f);
20 }
21}
1<?xml version="1.0" encoding="UTF-8"?>
2<project xmlns="http://maven.apache.org/POM/4.0.0"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5 <modelVersion>4.0.0</modelVersion>
6
7 <groupId>com.tz</groupId>
8 <artifactId>SpringIOC</artifactId>
9 <version>1.0-SNAPSHOT</version>
10
11 <dependencies>
12 <dependency>
13 <groupId>org.springframework</groupId>
14 <artifactId>spring-context</artifactId>
15 <version>5.0.8.RELEASE</version>
16 </dependency>
17
18 <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
19 <dependency>
20 <groupId>org.springframework</groupId>
21 <artifactId>spring-jdbc</artifactId>
22 <version>5.0.8.RELEASE</version>
23 </dependency>
24
25 <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
26 <dependency>
27 <groupId>mysql</groupId>
28 <artifactId>mysql-connector-java</artifactId>
29 <version>5.0.8</version>
30 </dependency>
31
32 <!-- https://mvnrepository.com/artifact/org.springframework/spring-tx -->
33 <dependency>
34 <groupId>org.springframework</groupId>
35 <artifactId>spring-tx</artifactId>
36 <version>5.0.8.RELEASE</version>
37 </dependency>
38
39 <!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
40 <dependency>
41 <groupId>org.springframework</groupId>
42 <artifactId>spring-test</artifactId>
43 <version>5.0.8.RELEASE</version>
44 <scope>test</scope>
45 </dependency>
46
47 <!-- https://mvnrepository.com/artifact/commons-dbutils/commons-dbutils -->
48 <dependency>
49 <groupId>commons-dbutils</groupId>
50 <artifactId>commons-dbutils</artifactId>
51 <version>1.4</version>
52 </dependency>
53
54 <!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
55 <dependency>
56 <groupId>com.mchange</groupId>
57 <artifactId>c3p0</artifactId>
58 <version>0.9.5.2</version>
59 </dependency>
60
61 <dependency>
62 <groupId>junit</groupId>
63 <artifactId>junit</artifactId>
64 <version>4.12</version>
65 </dependency>
66 </dependencies>
67
68</project>
目录大纲 Directory outline