聲明事務-注解配置


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 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM