spring的事务

Spring中的JdbcTemplate

pom.xml 添加坐标

 
        
        
            org.springframework
            spring-context
            5.0.2.RELEASE
        
        
        
            org.springframework
            spring-jdbc
            5.0.2.RELEASE
        
        
        
            org.springframework
            spring-tx
            5.0.2.RELEASE
        
        
        
            org.aspectj
            aspectjweaver
            1.8.7
        
        
        
            mysql
            mysql-connector-java
            5.1.6
        
        
        
            com.alibaba
            druid
            1.0.14
        
        
        
            commons-dbutils
            commons-dbutils
            1.7
        
        
        
            org.springframework
            spring-test
            5.0.2.RELEASE
        
        
        
            junit
            junit
            4.12
            test
        
        
        
            com.zaxxer
            HikariCP
            3.1.0
        
        
    

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




    
    
    
    

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




    
    

    
    
        
        
    

    
        
        
        
        
    


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


    c3p0
    c3p0
    0.9.1.2

applicationContext.xml




    
    

    
    
        
        
        
        
    

    
    
        
        
    

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


    com.alibaba
    druid
    1.1.10

applicationContext.xml




    
    

    
    
        
        
        
        
    

    
    
        
        
    


DBCP
HikariCP

pom.xml


    com.zaxxer
    HikariCP
    3.1.0

applicationContext.xml




    
    

    
    
        
        
        
        
    

    
    
        
        
    

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 页面使用

  • 引入配置文件方式一(不推荐使用)
 
 
    

  • 引入配置文件方式二
 
 
 
  • bean标签中引用配置文件内容
 

    
    
    
    

注意:在使用标签时,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


    
    
      org.springframework
      spring-context
      5.0.2.RELEASE
    
    
    
      org.springframework
      spring-jdbc
      5.0.2.RELEASE
    
    
    
      org.aspectj
      aspectjweaver
      1.8.7
    
    
    
      org.springframework
      spring-tx
      5.0.2.RELEASE
    
    
      mysql
      mysql-connector-java
      5.1.6
    
    
    
      org.springframework
      spring-test
      5.0.2.RELEASE
    
    
    
      junit
      junit
      4.12
      test
    

    
      com.zaxxer
      HikariCP
      3.1.0
    

  

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




    
    
        
        
    

    
    
        
        
    

    
    
    

    
    
        
        
        
        
        
    


    
    
    
        
        
    

    
    
        
        
    

    
    
        
        
        
        
    


声明事务管理-基于TransactionProxyFactoryBean

applicationContext.xml




    

    
    
        
        
    

    
    
        
        
    

    
    
        
        
    

    
    
    

    
    
        
        
        
        
        
    

    
    
        
        
    

    
    
    
        
        
        
        
        
        
            
                
                PROPAGATION_REQUIRED
            
        
    


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




    

    
    
        
        
    

    
    
        
        
    

    
    
        
        
    

    
    
    

    
    
        
        
        
        
        
    

    
    
        
        
    

    
    
        
        
            
            
        
    

    
    
        
        

        
        
    

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




    

    
    
        
        
    

    
    
        
        
    

    
    
        
        
    

    
    
    

    
    
        
        
        
        
        
    

    
    
        
        
    

    
    

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);
    }
}

你可能感兴趣的:(spring的事务)