13.spring基于純注解的聲明式事務控制(*)

spring基于純注解的聲明式事務控制(*)

了解即可,真實項目中不建議使用這種方式

一售碳、純注解配置步驟

1). 配置數據庫連接信息jdbcConfig.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring_01
jdbc.username=root
jdbc.password=abc123

2). 配置jdbcConfig jdbcTemplate與數據源

DataSourceTransactionManager類中有個屬性nestedTransactionAllowed ,表示允許【嵌套事務】星澳,基于此原理滞谢,然后再基于切面編程(被代理方法前后增強),實現(xiàn)嵌套事務粥庄!

package config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;

import javax.sql.DataSource;

/**
 * 和連接數據庫相關的配置類
 */
public class JdbcConfig {

    @Value("${jdbc.driver}")
    private String driver;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String username;
    @Value("${jdbc.password}")
    private String password;

    @Bean(name = "jdbcTemplate")
    public JdbcTemplate createJdbcTemplate(DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }

    @Bean(name="dataSource")
    public DataSource createDataSource() {
        DriverManagerDataSource ds = new DriverManagerDataSource();
        ds.setDriverClassName(driver);
        ds.setUrl(url);
        ds.setUsername(username);
        ds.setPassword(password);

        return ds;
    }
}

3). 配置 事務管理器TransactionConfig --- 切面

package config;
import org.springframework.context.annotation.Bean;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import javax.sql.DataSource;

/**
 * 和事務相關的配置類
 */
public class TransactionConfig {

    /** 創(chuàng)建事務管理器對象 */
    @Bean(name="transactionManager")
    public PlatformTransactionManager createTransactionManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
}

4). 配置綜合配置類SpringConfiguration

相當于applicationContext.xml;其中@EnableTransactionManagement表示開啟事務

package config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.PropertySource;
import org.springframework.transaction.annotation.EnableTransactionManagement;

/**
 * spring的配置類,相當于applicationContext.xml
 */
@Configuration
@ComponentScan("com.itheima")
@Import({JdbcConfig.class,TransactionConfig.class})
@PropertySource("jdbcConfig.properties")
@EnableTransactionManagement // 開啟事務
public class SpringConfiguration {
}

二衫樊、項目其他源代碼

1). 項目結構


spring基于純注解的聲明式事務控制.png

2). Account pojo

省略get/set/toString方法

public class Account {
    private Integer id;
    private String name;
    private Float money;
    ...

3). MyJdbcDaoSupport 抽離的jdbcTemplate

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

/** 如果使用注解開發(fā)飒赃,需要自己抽離JdbcTemplate */
@Component("myJdbcDaoSupport")
public class MyJdbcDaoSupport {

    // 下面這部分就需要在配置文件中進行配置
    @Autowired
    private JdbcTemplate jdbcTemplate;
    public JdbcTemplate getJdbcTemplate() {
        return jdbcTemplate;
    }

}

4). dao持久層

import com.itheima.domain.Account;
import java.sql.SQLException;
public interface AccountDao {

    /** 根據id查詢賬戶的余額 */
    public Account queryMoney(Integer id) throws SQLException;

    /** 根據id更新賬戶的余額 */
    public int updateMoney(Integer id, Float money) throws SQLException;
}
import com.itheima.dao.AccountDao;
import com.itheima.domain.Account;
import com.itheima.utils.MyJdbcDaoSupport;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.stereotype.Repository;

import java.sql.SQLException;

@Repository("accountDao")
public class AccountDaoImpl extends MyJdbcDaoSupport implements AccountDao {

    /** @事務
     * 根據id查詢賬戶的余額利花,將異常顯示拋出 */
    @Override
    public Account queryMoney(Integer id) throws SQLException {
        return super.getJdbcTemplate().queryForObject("select money from account where id = ?",
                new BeanPropertyRowMapper<Account>(Account.class), id);
    }

    /** @事務
     * 根據id更新賬戶的余額, 將異常顯示拋出 */
    @Override
    public int updateMoney(Integer id, Float money) throws SQLException {
        return super.getJdbcTemplate().update("update account set money = ? where id = ?",
                money, id);
    }
}

5). service業(yè)務層

public interface AccountService {
    /** 轉賬業(yè)務 */
    public boolean transfer(Integer fromId, Integer toId, Float money) throws Exception;
}
package com.itheima.service.impl;

import com.itheima.dao.AccountDao;
import com.itheima.domain.Account;
import com.itheima.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service("accountService")
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
public class AccountServiceImpl implements AccountService {

    @Autowired
    private AccountDao accountDao;

    /** @事務
     * 轉賬業(yè)務 使用注解進行聲明式事務處理科侈,使用
     * @Transactional 注解载佳,并在其中配置參數*/
    @Override
    @Transactional(propagation = Propagation.SUPPORTS, readOnly = false)
    public boolean transfer(Integer fromId, Integer toId, Float money) throws Exception {
        // 1. 查詢原賬戶余額
        Account fromMoney = accountDao.queryMoney(fromId);

        if (fromMoney.getMoney() < money) {
            throw new RuntimeException("賬戶余額不足,無法完成轉賬");
        }

        // 2. 查詢被轉入賬戶的余額
        Account toMoney = accountDao.queryMoney(toId);

        // 3. 扣除原賬戶的money
        accountDao.updateMoney(fromId, fromMoney.getMoney() - money);

        // 顯示拋出一個異常臀栈。
        //int a = 8 / 0;

        // 4. 添加被轉入賬戶的余額
        accountDao.updateMoney(toId, toMoney.getMoney() + money);

        return true;
    }
}

6). Junit4測試代碼

import config.SpringConfiguration;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfiguration.class)
public class MyTest {
    @Autowired
    private ApplicationContext ac;

    /** 轉賬測試 */
    @Test
    public void testTransfer() throws Exception {
        AccountService service = (AccountService)ac.getBean("accountService");
        boolean res = service.transfer(4, 2, 1000F);
        System.out.println(res);
    }
}

7). maven工程坐標

<dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.41</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>5.0.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.0.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>5.0.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-expression</artifactId>
            <version>5.0.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>5.0.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <!-- 切入點表達式解析的jar包 -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.7</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>

    </dependencies>
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末蔫慧,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子权薯,更是在濱河造成了極大的恐慌姑躲,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,546評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件盟蚣,死亡現(xiàn)場離奇詭異黍析,居然都是意外死亡,警方通過查閱死者的電腦和手機屎开,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評論 3 395
  • 文/潘曉璐 我一進店門阐枣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人奄抽,你說我怎么就攤上這事蔼两。” “怎么了逞度?”我有些...
    開封第一講書人閱讀 164,911評論 0 354
  • 文/不壞的土叔 我叫張陵额划,是天一觀的道長。 經常有香客問我档泽,道長俊戳,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,737評論 1 294
  • 正文 為了忘掉前任馆匿,我火速辦了婚禮品抽,結果婚禮上,老公的妹妹穿的比我還像新娘甜熔。我一直安慰自己圆恤,他們只是感情好,可當我...
    茶點故事閱讀 67,753評論 6 392
  • 文/花漫 我一把揭開白布腔稀。 她就那樣靜靜地躺著盆昙,像睡著了一般。 火紅的嫁衣襯著肌膚如雪焊虏。 梳的紋絲不亂的頭發(fā)上淡喜,一...
    開封第一講書人閱讀 51,598評論 1 305
  • 那天,我揣著相機與錄音诵闭,去河邊找鬼炼团。 笑死澎嚣,一個胖子當著我的面吹牛,可吹牛的內容都是我干的瘟芝。 我是一名探鬼主播易桃,決...
    沈念sama閱讀 40,338評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼锌俱!你這毒婦竟也來了晤郑?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,249評論 0 276
  • 序言:老撾萬榮一對情侶失蹤贸宏,失蹤者是張志新(化名)和其女友劉穎造寝,沒想到半個月后,有當地人在樹林里發(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 45,696評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,888評論 3 336
  • 正文 我和宋清朗相戀三年帅刊,在試婚紗的時候發(fā)現(xiàn)自己被綠了定踱。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,013評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情姊舵,我是刑警寧澤,帶...
    沈念sama閱讀 35,731評論 5 346
  • 正文 年R本政府宣布寓落,位于F島的核電站括丁,受9級特大地震影響,放射性物質發(fā)生泄漏伶选。R本人自食惡果不足惜史飞,卻給世界環(huán)境...
    茶點故事閱讀 41,348評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望仰税。 院中可真熱鬧构资,春花似錦、人聲如沸陨簇。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽河绽。三九已至己单,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間耙饰,已是汗流浹背纹笼。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留苟跪,地道東北人廷痘。 一個月前我還...
    沈念sama閱讀 48,203評論 3 370
  • 正文 我出身青樓蔓涧,卻偏偏與公主長得像,于是被迫代替她去往敵國和親笋额。 傳聞我的和親對象是個殘疾皇子元暴,可洞房花燭夜當晚...
    茶點故事閱讀 44,960評論 2 355

推薦閱讀更多精彩內容