spring的事務(wù)

Spring中的JdbcTemplate

pom.xml 添加坐標(biāo)

 <dependencies>
        <!--Spring核心容器-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>
        <!--SpringJdbc-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>
        <!--事務(wù)相關(guān)的-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>
        <!--SpringAOP相關(guān)的坐標(biāo)-->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.7</version>
        </dependency>
        <!--數(shù)據(jù)庫驅(qū)動-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>
        <!--druid連接池-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.0.14</version>
        </dependency>
        <!--dbutils連接池-->
        <dependency>
            <groupId>commons-dbutils</groupId>
            <artifactId>commons-dbutils</artifactId>
            <version>1.7</version>
        </dependency>
        <!--Spring整合單元測試-->
        <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>
        <!--連接池-->
        <dependency>
            <groupId>com.zaxxer</groupId>
            <artifactId>HikariCP</artifactId>
            <version>3.1.0</version>
        </dependency>
        
    </dependencies>

Account.java

package perm.coco.bean;

import java.io.Serializable;

public class Account implements Serializable {
    private Integer id;
    private String name;
    private Double money;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Double getMoney() {
        return money;
    }

    public void setMoney(Double money) {
        this.money = money;
    }

    @Override
    public String toString() {
        return "Account{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", money=" + money +
                '}';
    }
}
方式一 : 內(nèi)置JDBC

可以使用 xml方式 或 注解方式

AccountDaoImpl.java

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import perm.coco.bean.Account;
import perm.coco.dao.AccountDao;

/**
 * Spring 內(nèi)置連接池
 */
public class AccountDaoImpl implements AccountDao {

    /**
     * 保存賬戶
     * @param account
     */
    @Override
    public void save(Account account) {

        //1.創(chuàng)建連接池(Spring內(nèi)置的)
        DriverManagerDataSource dataSource = new DriverManagerDataSource();

        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql:///spring");
        dataSource.setUsername("root");
        dataSource.setPassword("root");

        //1.創(chuàng)建JDBCTemplate對象
        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);

        //操作數(shù)據(jù)庫
        String sql = "insert into account (id,name,money) values(?,?,?)";
        jdbcTemplate.update(sql, account.getId(), account.getName(), account.getMoney());
    }
}

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:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!--開啟包掃描-->
    <context:component-scan base-package="perm.coco"></context:component-scan>
    <!--注冊AccountDao-->
    <bean id="accountDao01" class="perm.coco.dao.Impl.AccountDaoImpl"></bean>
</beans>

Test.java

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import perm.coco.bean.Account;
import perm.coco.dao.AccountDao;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = "classpath:applicationContext.xml")
public class AppTest {

    //注入AccountDao
    @Autowired
    private AccountDao accountDao;

    @Test
    public void fun01() {
        Account account = new Account();
        account.setName("coco1");
        account.setMoney(1002.0);

        accountDao.save(account);
    }
}
方式二: 繼承 JdbcDaoSupport

只能使用xml方式裹虫,注解用不了

AccountDaoImpl02.java

import org.springframework.jdbc.core.support.JdbcDaoSupport;
import perm.coco.bean.Account;
import perm.coco.dao.AccountDao;

/**
 * 繼承JdbcSuport
 */
public class AccountDaoImpl02 extends JdbcDaoSupport implements AccountDao {

    /**
     * 內(nèi)置連接池
     * 保存賬戶
     * @param account
     */
    @Override
    public void save(Account account) {
        //操作數(shù)據(jù)庫
        String sql = "insert into account (id,name,money) values(?,?,?)";
        getJdbcTemplate().update(sql, account.getId(), account.getName(), account.getMoney());
    }

}

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:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!--開啟包掃描-->
    <context:component-scan base-package="perm.coco"></context:component-scan>

    <!--使用JdbcDaoSupport,必須要注入dataSource
        父類里面需要這個屬性幔虏,在注入的時候,會創(chuàng)建一個JdbcTemplate對象
        就可以通過 getJdbcTemplate()來獲取直接使用了-->
    <bean id="accountDao02" class="perm.coco.dao.Impl.AccountDaoImpl02">
        <!--注入dataSource-->
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql:///spring"></property>
        <property name="username" value="root"></property>
        <property name="password" value="root"></property>
    </bean>

</beans>

Test.java

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import perm.coco.bean.Account;
import perm.coco.dao.AccountDao;

import javax.annotation.Resource;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = "classpath:applicationContext.xml")
public class AppTest {

    //注入AccountDao
    @Resource(name = "accountDao02")
    private AccountDao accountDao;

    @Test
    public void fun01() {
        Account account = new Account();
        account.setName("coco1");
        account.setMoney(1002.0);

        accountDao.save(account);
    }
}
兩種方式比較

第一種在Dao類中定義JdbcTemplate的方式瘪吏,適用于所有配置方式(xml和注解都可以)

第二種讓Dao繼承JdbcDaoSupport的方式绊寻,只能用于基于XML的方式晒屎,注解用不了.

Spring 配置第三方連接池

c3p0

操作步驟:

  1. 在pom文件中添加c3p0坐標(biāo)
  2. 在配置文件里面配置 c3p0

pom.xml

<dependency>
    <groupId>c3p0</groupId>
    <artifactId>c3p0</artifactId>
    <version>0.9.1.2</version>
</dependency>

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:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!--開啟包掃描-->
    <context:component-scan base-package="perm.coco"></context:component-scan>

    <!--注冊 c3p0 連接池-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
        <property name="jdbcUrl" value="jdbc:mysql:///spring"></property>
        <property name="user" value="root"></property>
        <property name="password" value="root"></property>
    </bean>

    <!--注冊JdbcTemplate-->
    <bean id="JdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <!--注入dataSource-->
        <property name="dataSource" ref="dataSource"></property>
    </bean>
</beans>

AccountDaoImpl.java

package perm.coco.dao.Impl;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import perm.coco.bean.Account;
import perm.coco.dao.AccountDao;

/**
 * c3p0 連接池
 */
@Repository("accountDao")
public class AccountDaoImpl implements AccountDao {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    /**
     * 保存賬戶
     * @param account
     */
    @Override
    public void save(Account account) {
        String sql = "insert into account (id,name,money) values (?,?,?) ";
        jdbcTemplate.update(sql, account.getId(), account.getName(), account.getMoney());
    }
}

Test.java

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import perm.coco.bean.Account;
import perm.coco.dao.AccountDao;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = "classpath:applicationContext.xml")
public class AppTest {

    @Autowired
    private AccountDao accountDao;

    @Test
    public void fun01() {
        Account account = new Account();
        account.setName("hahha");
        account.setMoney(1000.0);

        accountDao.save(account);
    }
}
druid

pom.xml

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.10</version>
</dependency>

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:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!--開啟包掃描-->
    <context:component-scan base-package="perm.coco"></context:component-scan>

    <!--注冊 druid 連接池-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql:///spring"></property>
        <property name="username" value="root"></property>
        <property name="password" value="root"></property>
    </bean>

    <!--注冊JdbcTemplate-->
    <bean id="JdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <!--注入dataSource-->
        <property name="dataSource" ref="dataSource"></property>
    </bean>

</beans>
DBCP
HikariCP

pom.xml

<dependency>
    <groupId>com.zaxxer</groupId>
    <artifactId>HikariCP</artifactId>
    <version>3.1.0</version>
</dependency>

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:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
       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/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 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--開啟包掃描-->
    <context:component-scan base-package="perm.coco"></context:component-scan>

    <!--注冊 hikariCP 連接池-->
    <bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="jdbcUrl" value="jdbc:mysql:///spring"></property>
        <property name="username" value="root"></property>
        <property name="password" value="root"></property>
    </bean>

    <!--  注冊JdbcTemplate-->
    <bean id="dbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <!--注入dataSource-->
        <property name="dataSource" ref="dataSource"></property>
    </bean>
</beans>
Spring引入 Properties配置文件
  • 步驟

    1.定義jdbc.properties文件

    2.在spring核心配置文件里面引入配置文件

    3.根據(jù)key獲得值

jdbc.properties

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

applicationContext.xml 頁面使用

  • 引入配置文件方式一(不推薦使用)
 <!-- 引入properties配置文件:方式一 (繁瑣不推薦使用) -->
<bean id="properties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> 
    <property name="location" value="classpath:jdbc.properties" />
</bean>
  • 引入配置文件方式二
 <!-- 引入properties配置文件:方式二 (簡單推薦使用) -->
 <!--properties配置文件中的key一定要是帶點分隔的佑附。例如jdbc.url-->
 <context:property-placeholder location="classpath:jdbc.properties" />
  • bean標(biāo)簽中引用配置文件內(nèi)容
 <!-- hikariCP 連接池 -->
<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource">
    <property name="jdbcUrl" value="${jdbc.url}" />
    <property name="driverClassName" value="${jdbc.driver}" />
    <property name="username" value="${jdbc.username}" />
    <property name="password" value="${jdbc.password}" />
</bean>

注意:在使用<context:property-placeholder/>標(biāo)簽時搞乏,properties配置文件中的key一定要是帶點分隔的。例如jdbc.url

Spring管理事物

簡介

? 由于Spring對持久層的很多框架都有支持 眠屎, Hibernate 剔交、 jdbc 、 MyBatis 由于使用的框架不同改衩,所以使用事務(wù)管理操作API 也不盡相同岖常。 為了規(guī)范這些操作, Spring統(tǒng)一定義一個事務(wù)的規(guī)范 葫督,這其實是一個接口 竭鞍。這個接口的名稱 : PlatformTrasactionManager.并且它對已經(jīng)做好的框架都有支持.

? 如果dao層使用的是JDBC 或者mybatis,那么 可以使用DataSourceTransactionManager 來處理事務(wù)

? 如果dao層使用的是 Hibernate, 那么可以使用HibernateTransactionManager 來處理事務(wù)

事務(wù)特性
  • 原子型:事務(wù)是不可分割的工作單位,事務(wù)的操作要么都發(fā)生橄镜,要么都不發(fā)生
  • 一致性:事務(wù)前后數(shù)據(jù)的完整性必須保持一致
  • 隔離性:多個用戶并發(fā)訪問數(shù)據(jù)庫時偎快,一個用戶的事務(wù)不能被其他用戶的事務(wù)所干擾,多個并發(fā)事務(wù)之間數(shù)據(jù)要互相隔離
  • 持久性:一個事務(wù)一旦被提交洽胶,它對數(shù)據(jù)庫中數(shù)據(jù)的改變是永久性的晒夹。即使數(shù)據(jù)庫發(fā)送故障也不應(yīng)該對其有任何影響
事務(wù)的 API

聲明事務(wù)管理機制(3個核心接口對象)

  1. PlatformTransactionManager 事務(wù)管理器
  • commit 提交事務(wù)
  • rollback 回滾
  • getTransaction() 獲取事務(wù)狀態(tài)
  1. TransactionDefinition 事務(wù)定義信息
  • 隔離級別

  • 事務(wù)的傳播行為

  • 超時信息

  • 只讀

  1. TransactionStatus 事務(wù)具體運行狀態(tài)

注意:事務(wù)結(jié)束,必須通過 commit姊氓。rollback是作為標(biāo)記作為回滾丐怯。如果只是回滾,后面不操作翔横,數(shù)據(jù)庫與在關(guān)閉連接時,會自己commit

事務(wù)的傳播行為
事務(wù)的傳播行為的作用

? 我們一般都是將事務(wù)設(shè)置在Service層,那么當(dāng)我們調(diào)用Service層的一個方法的時候, 它能夠保證我們的這個方法中,執(zhí)行的所有的對數(shù)據(jù)庫的更新操作保持在一個事務(wù)中读跷, 在事務(wù)層里面調(diào)用的這些方法要么全部成功,要么全部失敗禾唁。

? 如果你的Service層的這個方法中效览,除了調(diào)用了Dao層的方法之外, 還調(diào)用了本類的其他的Service方法荡短,那么在調(diào)用其他的Service方法的時候钦铺, 我必須保證兩個service處在同一個事務(wù)中,確保事物的一致性肢预。

? 事務(wù)的傳播特性就是解決這個問題的矛洞。

事務(wù)的傳播行為的取值

保證在同一個事務(wù)里面:

  • PROPAGATION_REQUIRED:默認(rèn)值,也是最常用的場景.

    如果當(dāng)前沒有事務(wù)烫映,就新建一個事務(wù)沼本,
    如果已經(jīng)存在一個事務(wù)中,加入到這個事務(wù)中锭沟。

  • PROPAGATION_SUPPORTS:

    如果當(dāng)前沒有事務(wù)抽兆,就以非事務(wù)方式執(zhí)行。

    如果已經(jīng)存在一個事務(wù)中族淮,加入到這個事務(wù)中辫红。

  • PROPAGATION_MANDATORY

    如果當(dāng)前沒有有事務(wù)凭涂,就拋出異常;

    如果已經(jīng)存在一個事務(wù)中,加入到這個事務(wù)中贴妻。

保證不在同一個事物里:

  • PROPAGATION_REQUIRES_NEW

    如果當(dāng)前有事務(wù)切油,把當(dāng)前事務(wù)掛起,創(chuàng)建新的事務(wù)但獨自執(zhí)行

  • PROPAGATION_NOT_SUPPORTED

    如果當(dāng)前存在事務(wù),就把當(dāng)前事務(wù)掛起名惩。不創(chuàng)建事務(wù)

  • PROPAGATION_NEVER

    如果當(dāng)前存在事務(wù)澎胡,拋出異常

  • PROPAGATION_NESTED

    嵌套事務(wù) ,只對DataSourceTransactionManager有效 娩鹉,底層使用JDBC的SavePoint機制攻谁,允許在同一個事務(wù)設(shè)置保存點,回滾保存點

編程式事務(wù)管理

pom.xml

<dependencies>
    <!--Spring核心容器-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.0.2.RELEASE</version>
    </dependency>
    <!--SpringJdbc-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>5.0.2.RELEASE</version>
    </dependency>
    <!--SpringAOP相關(guān)的坐標(biāo)-->
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.8.7</version>
    </dependency>
    <!--事務(wù)相關(guān)的-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-tx</artifactId>
      <version>5.0.2.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.6</version>
    </dependency>
    <!--Spring整合單元測試-->
    <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>

    <dependency>
      <groupId>com.zaxxer</groupId>
      <artifactId>HikariCP</artifactId>
      <version>3.1.0</version>
    </dependency>

  </dependencies>

AccountServicesImpl.java

import com.zaxxer.hikari.HikariDataSource;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import perm.coco.dao.AccountDao;
import perm.coco.service.AccountService;
import sun.instrument.TransformerManager;

public class AccountServiceImpl implements AccountService {

    //注入dao
    private AccountDao accountDao;
    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }

    //注入transactionTemplate
    private TransactionTemplate transactionTemplate;
    public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
        this.transactionTemplate = transactionTemplate;
    }

    @Override
    public void transfer(String outUsername, String inUsername, Double money) {

        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                //轉(zhuǎn)出
                accountDao.out(outUsername, money);
                //    int i = 1 / 0;
                //轉(zhuǎn)入
                accountDao.in(inUsername, money);
            }
        });
    }


    public void transfer02(String outUsername, String inUsername, Double money) {

        //1.創(chuàng)建數(shù)據(jù)源
        HikariDataSource dataSource = new HikariDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/spring");
        dataSource.setUsername("root");
        dataSource.setPassword("root");

        //1. 創(chuàng)建事務(wù)管理器
        DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(dataSource);

        //創(chuàng)建事務(wù)管理器模板
        TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);

        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                //轉(zhuǎn)出
                accountDao.out(outUsername, money);
                //    int i = 1 / 0;
                //轉(zhuǎn)入
                accountDao.in(inUsername, 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:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!--注冊AccountDao-->
    <bean id="accountDao" class="perm.coco.dao.Impl.AccountDaoImpl">
        <!--注入JdbcTemplate-->
        <property name="jdbcTemplate" ref="jdbcTemplate"></property>
    </bean>

    <!--注冊JdbcTemplate-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <!--注入dataSource-->
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!--引入配置文件-->
    <!--properties配置文件中的key一定要是帶點分隔的弯予。例如jdbc.url-->
    <context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>

    <!--注冊dataSource-->
    <bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource">
        <!--注入四個基本屬性-->
        <property name="driverClassName" value="${jdbc.driver}"></property>
        <property name="jdbcUrl" value="${jdbc.url}"></property>
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>


    <!--編程式事務(wù)-->
    <!--注冊事務(wù)管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--注入dataSource-->
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!--配置事物管理的模板-->
    <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
        <!--注入transactionManager-->
        <property name="transactionManager" ref="transactionManager"></property>
    </bean>

    <!--注冊AccountService-->
    <bean id="accountService" class="perm.coco.service.Impl.AccountServiceImpl">
        <!--注入AccountDao-->
        <property name="accountDao" ref="accountDao"></property>
        <!--業(yè)務(wù)層注入事務(wù)模板-->
        <property name="transactionTemplate" ref="transactionTemplate"></property>
    </bean>

</beans>
聲明事務(wù)管理-基于TransactionProxyFactoryBean

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:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- &lt;!&ndash;開啟包掃描&ndash;&gt;
     <context:component-scan base-package="perm.coco"></context:component-scan>-->

    <!--注冊AccountDao-->
    <bean id="accountDao" class="perm.coco.dao.Impl.AccountDaoImpl">
        <!--注入JdbcTemplate-->
        <property name="jdbcTemplate" ref="jdbcTemplate"></property>
    </bean>

    <!--注冊AccountService-->
    <bean id="accountService" class="perm.coco.service.Impl.AccountServiceImpl">
        <!--注入AccountDao-->
        <property name="accountDao" ref="accountDao"></property>
    </bean>

    <!--注冊JdbcTemplate-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <!--注入dataSource-->
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!--引入配置文件-->
    <!--properties配置文件中的key一定要是帶點分隔的戚宦。例如jdbc.url-->
    <context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>

    <!--注冊dataSource-->
    <bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource">
        <!--注入四個基本屬性-->
        <property name="driverClassName" value="${jdbc.driver}"></property>
        <property name="jdbcUrl" value="${jdbc.url}"></property>
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>

    <!--注冊事務(wù)管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--注入dataSource-->
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!--配置業(yè)務(wù)層代理-->
    <!--只能對一個類配置-->
    <bean id="accountServiceProxy"
          class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
        <!--配置目標(biāo)對象-->
        <property name="target" ref="accountService"></property>
        <!--注入事務(wù)管理器transactionManager -->
        <property name="transactionManager" ref="transactionManager"></property>
        <!--注入事務(wù)屬性-->
        <property name="transactionAttributes">
            <props>
                <!--prop的格式
                    key:方法名, *代表所有的方法名
                    propagation:事務(wù)的傳播行為
                    isolation:事務(wù)的隔離性
                    readonly:只讀
                    -Exception:發(fā)生哪些異常回滾事務(wù)
                    +Exception:發(fā)生哪些異常不回滾事務(wù)
                -->
                <prop key="*">PROPAGATION_REQUIRED</prop>
            </props>
        </property>
    </bean>
</beans>

AccountServicesImpl.java

import perm.coco.dao.AccountDao;
import perm.coco.service.AccountService;

public class AccountServiceImpl implements AccountService {

    //注入dao
    private AccountDao accountDao;
    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }

    @Override
    public void transfer(String outUsername, String inUsername, Double money) {
        //轉(zhuǎn)出
        accountDao.out(outUsername, money);
        //int i = 1 / 0;
        //轉(zhuǎn)入
        accountDao.in(inUsername, money);
    }
}
聲明事務(wù)管理-基于AspectJ(xml)

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:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
       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/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 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!-- &lt;!&ndash;開啟包掃描&ndash;&gt;
     <context:component-scan base-package="perm.coco"></context:component-scan>-->

    <!--注冊AccountDao-->
    <bean id="accountDao" class="perm.coco.dao.Impl.AccountDaoImpl">
        <!--注入JdbcTemplate-->
        <property name="jdbcTemplate" ref="jdbcTemplate"></property>
    </bean>

    <!--注冊AccountService-->
    <bean id="accountService" class="perm.coco.service.Impl.AccountServiceImpl">
        <!--注入AccountDao-->
        <property name="accountDao" ref="accountDao"></property>
    </bean>

    <!--注冊JdbcTemplate-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <!--注入dataSource-->
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!--引入配置文件-->
    <!--properties配置文件中的key一定要是帶點分隔的锈嫩。例如jdbc.url-->
    <context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>

    <!--注冊dataSource-->
    <bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource">
        <!--注入四個基本屬性-->
        <property name="driverClassName" value="${jdbc.driver}"></property>
        <property name="jdbcUrl" value="${jdbc.url}"></property>
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>

    <!--注冊事務(wù)管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--注入dataSource-->
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!--配置事務(wù)通知:事務(wù)增強-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <!--配置事務(wù)的屬性-->
        <tx:attributes>
            <tx:method name="transfer" propagation="REQUIRED" isolation="SERIALIZABLE"/>
            <tx:method name="updata*" propagation="REQUIRED" isolation="SERIALIZABLE"/>
        </tx:attributes>
    </tx:advice>

    <!--配置切面-->
    <aop:config>
        <!--配置切入點-->
        <aop:pointcut id="pointcut01" expression="execution(* perm.coco.service.*.*(..))"></aop:pointcut>

        <!--配置切面-->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut01"></aop:advisor>
    </aop:config>
</beans>

AccountServiceImpl.xml

import perm.coco.dao.AccountDao;
import perm.coco.service.AccountService;

public class AccountServiceImpl implements AccountService {

    //注入dao
    private AccountDao accountDao;
    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }

    @Override
    public void transfer(String outUsername, String inUsername, Double money) {
        //轉(zhuǎn)出
        accountDao.out(outUsername, money);
        int i = 1 / 0;
        //轉(zhuǎn)入
        accountDao.in(inUsername, money);
    }
}
聲明事務(wù)管理-注解

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:context="http://www.springframework.org/schema/context" 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/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">

    <!-- &lt;!&ndash;開啟包掃描&ndash;&gt;
     <context:component-scan base-package="perm.coco"></context:component-scan>-->

    <!--注冊AccountDao-->
    <bean id="accountDao" class="perm.coco.dao.Impl.AccountDaoImpl">
        <!--注入JdbcTemplate-->
        <property name="jdbcTemplate" ref="jdbcTemplate"></property>
    </bean>

    <!--注冊AccountService-->
    <bean id="accountService" class="perm.coco.service.Impl.AccountServiceImpl">
        <!--注入AccountDao-->
        <property name="accountDao" ref="accountDao"></property>
    </bean>

    <!--注冊JdbcTemplate-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <!--注入dataSource-->
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!--引入配置文件-->
    <!--properties配置文件中的key一定要是帶點分隔的受楼。例如jdbc.url-->
    <context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>

    <!--注冊dataSource-->
    <bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource">
        <!--注入四個基本屬性-->
        <property name="driverClassName" value="${jdbc.driver}"></property>
        <property name="jdbcUrl" value="${jdbc.url}"></property>
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>

    <!--注冊事務(wù)管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--注入dataSource-->
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!--開啟事務(wù)注解-->
    <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
</beans>

AccountServiceImpl.java

package perm.coco.service.Impl;

import org.springframework.transaction.annotation.Transactional;
import perm.coco.dao.AccountDao;
import perm.coco.service.AccountService;

@Transactional
public class AccountServiceImpl implements AccountService {

    //注入dao
    private AccountDao accountDao;

    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }
    
    @Override
    public void transfer(String outUsername, String inUsername, Double money) {
        //轉(zhuǎn)出
        accountDao.out(outUsername, money);
       // int i = 1 / 0;
        //轉(zhuǎn)入
        accountDao.in(inUsername, money);
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市祠挫,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌悼沿,老刑警劉巖等舔,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異糟趾,居然都是意外死亡慌植,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進店門义郑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蝶柿,“玉大人,你說我怎么就攤上這事非驮〗惶溃” “怎么了?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵劫笙,是天一觀的道長芙扎。 經(jīng)常有香客問我,道長填大,這世上最難降的妖魔是什么戒洼? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮允华,結(jié)果婚禮上圈浇,老公的妹妹穿的比我還像新娘寥掐。我一直安慰自己,他們只是感情好磷蜀,可當(dāng)我...
    茶點故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布召耘。 她就那樣靜靜地躺著,像睡著了一般蠕搜。 火紅的嫁衣襯著肌膚如雪怎茫。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天妓灌,我揣著相機與錄音轨蛤,去河邊找鬼。 笑死虫埂,一個胖子當(dāng)著我的面吹牛祥山,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播掉伏,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼缝呕,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了斧散?” 一聲冷哼從身側(cè)響起供常,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎鸡捐,沒想到半個月后栈暇,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡箍镜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年源祈,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片色迂。...
    茶點故事閱讀 39,795評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡香缺,死狀恐怖毙死,靈堂內(nèi)的尸體忽然破棺而出闪萄,到底是詐尸還是另有隱情胆筒,我是刑警寧澤堤框,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布秉剑,位于F島的核電站镰惦,受9級特大地震影響慨畸,放射性物質(zhì)發(fā)生泄漏伞梯。R本人自食惡果不足惜写隶,卻給世界環(huán)境...
    茶點故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一倔撞、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧慕趴,春花似錦痪蝇、人聲如沸鄙陡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽趁矾。三九已至,卻和暖如春给僵,著一層夾襖步出監(jiān)牢的瞬間毫捣,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工帝际, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留蔓同,地道東北人。 一個月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓蹲诀,卻偏偏與公主長得像斑粱,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子脯爪,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,724評論 2 354

推薦閱讀更多精彩內(nèi)容

  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,810評論 6 342
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理则北,服務(wù)發(fā)現(xiàn),斷路器痕慢,智...
    卡卡羅2017閱讀 134,654評論 18 139
  • 1.DAO和事務(wù)管理的牽絆 事務(wù)管理的目的是保證數(shù)據(jù)操作的事務(wù)性(原子性尚揣、一致性、隔離性掖举、持久性快骗,即所謂的ACID...
    小螺釘12138閱讀 491評論 1 2
  • 1.數(shù)據(jù)庫事務(wù)基礎(chǔ)知識 1.1.何為數(shù)據(jù)庫事務(wù) 數(shù)據(jù)庫事務(wù)的4個特性 原子性:組成一個事務(wù)的多個數(shù)據(jù)庫操作是一個不...
    小螺釘12138閱讀 1,575評論 1 18
  • 看山似水云清風(fēng)淡 出淤泥不染似佳人 來此嵐山細看星辰 點點細雨潤如油膏 贊不絕口小小詩詞
    啊呼閱讀 856評論 0 0