声明事务-注解配置

Spring事务控制我们要明确的:

1.JavaEE体系进行分层开发,事务处理位于业务层,所以,一般情况下我们使用事务代理,一般放在分层设计业务层

2.spring框架为我们提供了一组事务控制的应用程序接口(API)。

3.spring的事务控制都是基于AOP的,它既可以使用编程的方式实现,也可以使用配置的方式实现。所以我们学习的重点是使用配置的方式实现。

 

出现以下错误可能是Service层代码的AccountServiceImpl下,的真正业务代码里没有添加@Transactional(readOnly=false)

applicationContext.xml:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3     xmlns:p="http://www.springframework.org/schema/p"
 4     xmlns:context="http://www.springframework.org/schema/context"
 5     xmlns:tx="http://www.springframework.org/schema/tx"
 6     xmlns:aop="http://www.springframework.org/schema/aop"
 7     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 8     xsi:schemaLocation="http://www.springframework.org/schema/beans
 9         http://www.springframework.org/schema/beans/spring-beans.xsd
10         http://www.springframework.org/schema/context
11         http://www.springframework.org/schema/context/spring-context.xsd
12         http://www.springframework.org/schema/tx
13         http://www.springframework.org/schema/tx/spring-tx.xsd
14         http://www.springframework.org/schema/aop
15         http://www.springframework.org/schema/aop/spring-aop.xsd
16         ">
17         
18     <!-- 配置组件包扫描的位置 -->
19     <context:component-scan base-package="top.abcdit.spring"/>
20     
21     <!-- 读取db.properties配置文件到Spring容器中 -->
22     <context:property-placeholder location="classpath:db.properties"/>    
23     
24     <!-- 配置 阿里巴巴的 druid 数据源(连接池) -->
25     <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
26         
27         <!-- SpringEL 语法 ${key}  -->
28         
29         <property name="driverClassName" value="${jdbc.driverClassName}"/>
30         <property name="url" value="${jdbc.url}"/>
31         
32         <!-- 
33             ${username}如果key是username,name 默认spring框架调用的当前操作系统的账号
34             解决方案:可以统一给key加一个前缀
35          -->
36          
37          <property name="username" value="${jdbc.username}"/>
38          <property name="password" value="${jdbc.password}"/>
39          <property name="maxActive" value="${jdbc.maxActive}"/>
40     </bean>
41     
42     <!-- 配置jdbcTemplate 模板类  -->
43     
44     <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
45     
46         <!-- 注入数据源(连接池),set方法注入 -->
47         <property name="dataSource" ref="dataSource"/>
48         <!-- 构造器注入 -->
49            <!-- <constructor-arg name="dataSource" ref="dataSource"/> -->
50         
51     </bean>
52     
53     <!--
54          开始Spring的事务配置 
55          配置思路
56          1.配置事务管理器
57          2.配置事务细节
58              把事务管理器配置到事务管理器中
59          3.把事务管理器 使用aop切入Service层中
60     -->
61     
62     <!-- 配置事务管理器 -->
63     <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
64         <!-- 注入数据源(连接池) -->
65         <property name="dataSource" ref="dataSource"/>
66     
67     </bean>
68     
69     <!-- 开启事务注解驱动 
70         transaction-manager: 是万物管理器
71     -->
72     <tx:annotation-driven transaction-manager="transactionManager"/>    
73     
74 </beans>

AccountDao:

 1 package top.abcdit.spring.dao;
 2 
 3 public interface AccountDao {
 4     
 5     /**
 6      * 转出方法
 7      * @param OutId
 8      * @param money
 9      */
10     void transOut(Integer outId,Integer money);
11     
12     /**
13      * 转入方法
14      * @param inId
15      * @param money
16      */
17     void transInt(Integer inId,Integer money);
18     
19     
20     
21 }

AccountDaoImpl:

 1 package top.abcdit.spring.dao.impl;
 2 
 3 import org.springframework.beans.factory.annotation.Autowired;
 4 import org.springframework.jdbc.core.JdbcTemplate;
 5 import org.springframework.stereotype.Repository;
 6 
 7 import top.abcdit.spring.dao.AccountDao;
 8 
 9 @Repository
10 public class AccountDaoImpl implements AccountDao {
11     
12     
13     @Autowired  //默认按类型注入
14     private JdbcTemplate jdbcTemplate;
15     
16     
17     public void transOut(Integer outId, Integer money) {
18         String sql = "update s_account set balance = balance - ? where id = ?";
19         jdbcTemplate.update(sql, money, outId);
20         
21     }
22 
23     public void transInt(Integer inId, Integer money) {
24         String sql = "update s_account set balance = balance + ? where id = ?";
25         jdbcTemplate.update(sql, money, inId);
26         
27     }
28     
29 }

AccountService:

 1 package top.abcdit.spring.service;
 2 
 3 public interface AccountService {
 4     
 5     /**
 6      * 这是转账的业务方法
 7      * @param outId 转出账号
 8      * @param inId  转入账号
 9      * @param money 金额
10      */
11     void trans(Integer outId,Integer inId, Integer money);
12     
13     void selectByPrimaryKey (Integer id);
14     
15     void selectList();
16 }

AccountServiceImpl:

 1 package top.abcdit.spring.service.impl;
 2 
 3 import org.springframework.beans.factory.annotation.Autowired;
 4 import org.springframework.stereotype.Service;
 5 import org.springframework.transaction.annotation.Isolation;
 6 import org.springframework.transaction.annotation.Propagation;
 7 import org.springframework.transaction.annotation.Transactional;
 8 
 9 import top.abcdit.spring.dao.AccountDao;
10 import top.abcdit.spring.service.AccountService;
11 
12 
13 /*
14  * 
15  * @Transactional
16  *     开启注解事务配置,一个 @Transactional只能对当前类有效,当前类下面所有方法配置一样
17  *  isolation=Isolation.REPEATABLE_READ, 隔离级别
18     propagation=Propagation.REQUIRED, 传播行为(规则)
19     timeout=5, 超时时间
20     readOnly=true  是否是只读事务
21  * 
22  */
23 
24 @Service
25 @Transactional(isolation=Isolation.REPEATABLE_READ,
26                 propagation=Propagation.REQUIRED,
27                 timeout=5,
28                 readOnly=true
29         )
30 
31 public class AccountServiceImpl implements AccountService{
32     
33     @Autowired
34     private AccountDao accountDao;
35     
36     
37     /**
38      *  这是真正的业务方法
39      * 一个业务方法有多个 功能 (多个dao层方法)
40      * 
41      */
42     @Transactional(readOnly=false)  //注解配置时,这里也要添加
43     public void trans(Integer outId, Integer inId, Integer money) {
44         
45         accountDao.transOut(outId, money);
46         //System.out.println(1/0);
47         accountDao.transInt(inId, money);
48         
49     }
50     
51     @Transactional(readOnly=true)
52     public void selectByPrimaryKey(Integer id) {
53         
54     }
55     
56     @Transactional(readOnly=true)
57     public void selectList() {
58         
59     }
60 
61     
62 }  

db.properties配置文件

jdbc.driverClassName=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring_jdbc?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT
jdbc.username=root
jdbc.password=myroot
jdbc.maxActive=10

测试代码:

 1 package top.abcdit.spring.test;
 2 
 3 import static org.junit.Assert.*;
 4 
 5 import org.junit.Test;
 6 import org.junit.runner.RunWith;
 7 import org.springframework.beans.factory.annotation.Autowired;
 8 import org.springframework.test.context.ContextConfiguration;
 9 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
10 
11 import top.abcdit.spring.service.AccountService;
12 
13 
14 
15 @RunWith(SpringJUnit4ClassRunner.class)
16 @ContextConfiguration("classpath:applicationContext.xml")
17 public class AccountServiceTest {
18     
19     @Autowired
20     private AccountService service;
21     
22     @Test
23     public void testName() throws Exception {
24         service.trans(10001, 10002, 3000);
25     }
26 
27 }

 

posted @ 2019-07-08 22:02  abcdjava  阅读(2016)  评论(0编辑  收藏  举报