spring的事务

Spring中的JdbcTemplate

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>
        <!--事务相关的-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>
        <!--SpringAOP相关的坐标-->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.7</version>
        </dependency>
        <!--数据库驱动-->
        <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 +
                '}';
    }
}
方式一 : 内置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 内置连接池
 */
public class AccountDaoImpl implements AccountDao {

    /**
     * 保存账户
     * @param account
     */
    @Override
    public void save(Account account) {

        //1.创建连接池(Spring内置的)
        DriverManagerDataSource dataSource = new DriverManagerDataSource();

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

        //1.创建JDBCTemplate对象
        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);

        //操作数据库
        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 {

    /**
     * 内置连接池
     * 保存账户
     * @param account
     */
    @Override
    public void save(Account account) {
        //操作数据库
        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
        父类里面需要这个属性,在注入的时候,会创建一个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坐标
  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.根据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标签中引用配置文件内容
 <!-- 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/>标签时,properties配置文件中的key一定要是带点分隔的。例如jdbc.url

Spring管理事物

简介

​ 由于Spring对持久层的很多框架都有支持 , Hibernate 、 jdbc 、 MyBatis 由于使用的框架不同,所以使用事务管理操作API 也不尽相同。 为了规范这些操作, Spring统一定义一个事务的规范 ,这其实是一个接口 。这个接口的名称 : PlatformTrasactionManager.并且它对已经做好的框架都有支持.

​ 如果dao层使用的是JDBC 或者mybatis,那么 可以使用DataSourceTransactionManager 来处理事务

​ 如果dao层使用的是 Hibernate, 那么可以使用HibernateTransactionManager 来处理事务

事务特性
  • 原子型:事务是不可分割的工作单位,事务的操作要么都发生,要么都不发生
  • 一致性:事务前后数据的完整性必须保持一致
  • 隔离性:多个用户并发访问数据库时,一个用户的事务不能被其他用户的事务所干扰,多个并发事务之间数据要互相隔离
  • 持久性:一个事务一旦被提交,它对数据库中数据的改变是永久性的。即使数据库发送故障也不应该对其有任何影响
事务的 API

声明事务管理机制(3个核心接口对象)

  1. PlatformTransactionManager 事务管理器
  • commit 提交事务
  • rollback 回滚
  • getTransaction() 获取事务状态
  1. TransactionDefinition 事务定义信息
  • 隔离级别

  • 事务的传播行为

  • 超时信息

  • 只读

  1. TransactionStatus 事务具体运行状态

注意:事务结束,必须通过 commit。rollback是作为标记作为回滚。如果只是回滚,后面不操作,数据库与在关闭连接时,会自己commit

事务的传播行为
事务的传播行为的作用

​ 我们一般都是将事务设置在Service层,那么当我们调用Service层的一个方法的时候, 它能够保证我们的这个方法中,执行的所有的对数据库的更新操作保持在一个事务中, 在事务层里面调用的这些方法要么全部成功,要么全部失败。

​ 如果你的Service层的这个方法中,除了调用了Dao层的方法之外, 还调用了本类的其他的Service方法,那么在调用其他的Service方法的时候, 我必须保证两个service处在同一个事务中,确保事物的一致性。

​ 事务的传播特性就是解决这个问题的。

事务的传播行为的取值

保证在同一个事务里面:

  • PROPAGATION_REQUIRED:默认值,也是最常用的场景.

    如果当前没有事务,就新建一个事务,
    如果已经存在一个事务中,加入到这个事务中。

  • PROPAGATION_SUPPORTS:

    如果当前没有事务,就以非事务方式执行。

    如果已经存在一个事务中,加入到这个事务中。

  • PROPAGATION_MANDATORY

    如果当前没有有事务,就抛出异常;

    如果已经存在一个事务中,加入到这个事务中。

保证不在同一个事物里:

  • PROPAGATION_REQUIRES_NEW

    如果当前有事务,把当前事务挂起,创建新的事务但独自执行

  • PROPAGATION_NOT_SUPPORTED

    如果当前存在事务,就把当前事务挂起。不创建事务

  • PROPAGATION_NEVER

    如果当前存在事务,抛出异常

  • PROPAGATION_NESTED

    嵌套事务 ,只对DataSourceTransactionManager有效 ,底层使用JDBC的SavePoint机制,允许在同一个事务设置保存点,回滚保存点

编程式事务管理

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相关的坐标-->
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.8.7</version>
    </dependency>
    <!--事务相关的-->
    <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) {
                //转出
                accountDao.out(outUsername, money);
                //    int i = 1 / 0;
                //转入
                accountDao.in(inUsername, money);
            }
        });
    }


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

        //1.创建数据源
        HikariDataSource dataSource = new HikariDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/spring");
        dataSource.setUsername("root");
        dataSource.setPassword("root");

        //1. 创建事务管理器
        DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(dataSource);

        //创建事务管理器模板
        TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);

        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                //转出
                accountDao.out(outUsername, money);
                //    int i = 1 / 0;
                //转入
                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>


    <!--编程式事务-->
    <!--注册事务管理器-->
    <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>
        <!--业务层注入事务模板-->
        <property name="transactionTemplate" ref="transactionTemplate"></property>
    </bean>

</beans>
声明事务管理-基于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>

    <!--注册事务管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--注入dataSource-->
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!--配置业务层代理-->
    <!--只能对一个类配置-->
    <bean id="accountServiceProxy"
          class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
        <!--配置目标对象-->
        <property name="target" ref="accountService"></property>
        <!--注入事务管理器transactionManager -->
        <property name="transactionManager" ref="transactionManager"></property>
        <!--注入事务属性-->
        <property name="transactionAttributes">
            <props>
                <!--prop的格式
                    key:方法名, *代表所有的方法名
                    propagation:事务的传播行为
                    isolation:事务的隔离性
                    readonly:只读
                    -Exception:发生哪些异常回滚事务
                    +Exception:发生哪些异常不回滚事务
                -->
                <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) {
        //转出
        accountDao.out(outUsername, money);
        //int i = 1 / 0;
        //转入
        accountDao.in(inUsername, money);
    }
}
声明事务管理-基于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>

    <!--注册事务管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--注入dataSource-->
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!--配置事务通知:事务增强-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <!--配置事务的属性-->
        <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) {
        //转出
        accountDao.out(outUsername, money);
        int i = 1 / 0;
        //转入
        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" 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>

    <!--注册事务管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--注入dataSource-->
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!--开启事务注解-->
    <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) {
        //转出
        accountDao.out(outUsername, money);
       // int i = 1 / 0;
        //转入
        accountDao.in(inUsername, money);
    }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,591评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,448评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,823评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,204评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,228评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,190评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,078评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,923评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,334评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,550评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,727评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,428评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,022评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,672评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,826评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,734评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,619评论 2 354

推荐阅读更多精彩内容

  • Spring Boot 参考指南 介绍 转载自:https://www.gitbook.com/book/qbgb...
    毛宇鹏阅读 46,806评论 6 342
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,652评论 18 139
  • 1.DAO和事务管理的牵绊 事务管理的目的是保证数据操作的事务性(原子性、一致性、隔离性、持久性,即所谓的ACID...
    小螺钉12138阅读 490评论 1 2
  • 1.数据库事务基础知识 1.1.何为数据库事务 数据库事务的4个特性 原子性:组成一个事务的多个数据库操作是一个不...
    小螺钉12138阅读 1,575评论 1 18
  • 看山似水云清风淡 出淤泥不染似佳人 来此岚山细看星辰 点点细雨润如油膏 赞不绝口小小诗词
    啊呼阅读 855评论 0 0