当前位置: 首页 > article >正文

Spring框架---JDBC模板技术

 

目录

Spring框架的JDBC模板技术

JDBC模板技术概述

JDBC的模板类的使用

使用Spring框架来管理模板类

Spring框架管理开源的连接池

Spring框架的JDBC模板的简单操作

模拟转账开发

Dao编写的方式(第二种方式)

Spring框架的事务管理

Spring框架的事务管理相关的类和API

Spring框架声明式事务管理


Spring框架的JDBC模板技术

JDBC模板技术概述

Spring框架中提供了很多持久层的模板类来简化编程,使用模板类编写程序会变的简单

  •  template 模板
  • 都是Spring框架提供XxxTemplate

提供了JDBC模板,Spring框架提供的

  •  JdbcTemplate类,Connection 表示连接,管理事务 Statement ResultSet

如果不使用JdbcTemplate,想要实现增删改查需要以下步骤

  1. 加载驱动
  2. 通过Conection接口获取连接
  3. 编写sql语句
  4. 获取执行sql对象,Statment或者PreparedStatment(更推荐,是一种预编译SQL语句的方法,可以防止SQL注入问题,使用?作为占位符)
  5. 执行sql语句,返回查询结果,将结果封装在Result结果集中
  6. 释放资源

JDBC的模板类的使用

引入JdbcTemplate,JdbcTemplate接口会帮我们完成获取连接,执行sql语句并封装结果,释放资源

创建maven项目,引入坐标依赖

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.0.2.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>commons-logging</groupId>
        <artifactId>commons-logging</artifactId>
        <version>1.2</version>
    </dependency>
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.12</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>
    </dependency>

    <!-- AOP联盟 -->
    <dependency>
        <groupId>aopalliance</groupId>
        <artifactId>aopalliance</artifactId>
        <version>1.0</version>
    </dependency>
    <!-- Spring Aspects -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>5.0.2.RELEASE</version>
    </dependency>
    <!-- aspectj -->
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.8.3</version>
    </dependency>

    

    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.6</version>
    </dependency>
    
    <!--JDBC模板-->
    <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>

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

创建spring_db数据库

create database spring_db;
use spring_db;
create table account(
    id int primary key auto_increment,
    name varchar(40),
    money double
)character set utf8 collate utf8_general_ci;

insert into account(name,money) values('aaa',1000);
insert into account(name,money) values('bbb',1000);
insert into account(name,money) values('ccc',1000);

数据库实体类

package com.qcby.demo4;

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

    public Account() {
    }

    public Account(Integer id, String name, Double money) {
        this.id = id;
        this.name = name;
        this.money = 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 +
                '}';
    }
}

测试类

package com.qcby.demo0401Test;

import org.junit.Test;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.jdbc.core.JdbcTemplate;

public class demo1 {

    /**
     * 使用new对象方式完成
     */
    @Test
    public void run1(){
        //创建连接池对象,spring框架内置了连接池对象
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        //设置了4个参数
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/spring_db");
        dataSource.setUsername("root");
        dataSource.setPassword("2020");

        //提供模板,创建对象
        JdbcTemplate template = new JdbcTemplate(dataSource);
        //完成数据的增删改查
        template.update("insert into account values (null,?,?)","熊大",1000);
    }
}

将连接池对象传入到JdbcTemplate中,直接调用JdbcTemplate中的方法即可完成操作

使用Spring框架来管理模板类

上面代码的JdbcTemplate是自己手动new出来的,我们可以把这些类交给Spring框架去管理。

在配置文件中使用Spring管理内置的连接池

<?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: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/aop
                http://www.springframework.org/schema/aop/spring-aop.xsd">
                
                <!-- demo1_1 -->
            <!--配置连接池,使用的是Spring框架内置的连接池-->
            <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
                <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/spring_db"/>
                <property name="username" value="root"/>
                <property name="password" value="2020"/>
            </bean>
            
            <!--配置jdbc模板-->
            <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
                <property name="dataSource" ref="dataSource"/>
            </bean>


</beans>
        

编写测试方法

package com.qcby.demo0401Test;

import com.qcby.demo4.Account;
import com.qcby.demo4.BeanMapper;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.util.List;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext_jdbc.xml")
public class demo1_1 {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    /**
     * 测试的方法
     */
    @Test
    public void run1(){
        jdbcTemplate.update("insert into account values (null,?,?)","ccc",5000);
    }
    }

Spring框架管理开源的连接池

配置开源的连接池,使用Druid开源的连接池,引入坐标如下

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

创建属性文件jdbc.properties

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring_db
jdbc.username=root
jdbc.password=2020

完成核心配置

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

    <!-- demo1_1 -->
    <!--配置连接池,使用的是Spring框架内置的连接池-->
    <!--<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">-->
        <!--<property name="driverClassName" value="com.mysql.jdbc.Driver"/>-->
        <!--<property name="url" value="jdbc:mysql://localhost:3306/spring_db"/>-->
        <!--<property name="username" value="root"/>-->
        <!--<property name="password" value="2020"/>-->
    <!--</bean>-->


    <!--使用开源连接池-->
    <!--<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">-->
        <!--<property name="driverClassName" value="com.mysql.jdbc.Driver"/>-->
        <!--<property name="url" value="jdbc:mysql://localhost:3306/spring_db"/>-->
        <!--<property name="username" value="root"/>-->
        <!--<property name="password" value="2020"/>-->
    <!--</bean>-->



    <!--加载属性文件-->
    <!--<bean id="placeholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">-->
        <!--<property name="location" value="classpath:jdbc.properties"/>-->
    <!--</bean>-->

    <!--第二种写法:使用提供标签的方式-->
    <context:property-placeholder location="jdbc.properties"/>

    <!--加载属性的文件-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driverClassName}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

    <!--配置jdbc模板-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>


</beans>

Spring框架的JDBC模板的简单操作

增删改查代码编写

package com.qcby.demo0401Test;

import com.qcby.demo4.Account;
import com.qcby.demo4.BeanMapper;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.util.List;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext_jdbc.xml")
public class demo1_1 {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    /**
     * 测试的方法
     */
    @Test
    public void run1(){
        jdbcTemplate.update("insert into account values (null,?,?)","ccc",5000);
    }

    /**
     * 修改
     */
    @Test
    public void run2(){
        jdbcTemplate.update("update account set name = ?,money = ? where id = ?","小小怪下士",3000,7);
    }

    /**
     * 删除
     */
    @Test
    public void run3(){
        jdbcTemplate.update("delete from account where id = ?",8);
    }

    /**
     * 通过id查询
     */
    @Test
    public void run4(){
        Account account = jdbcTemplate.queryForObject("select * from account where id = ?", new BeanMapper(), 6);
        System.out.println(account);
    }

    /**
     * 查询所有的数据
     */
    @Test
    public void run5(){
        List<Account> list = jdbcTemplate.query("select * from account",new BeanMapper());
        for(Account account:list){
            System.out.println(account);
        }
    }
}

模拟转账开发

引入依赖

<dependencies>
    <!--spring的核心-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.0.2.RELEASE</version>
    </dependency>
    <!--日志-->
    <dependency>
        <groupId>commons-logging</groupId>
        <artifactId>commons-logging</artifactId>
        <version>1.2</version>
    </dependency>
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.12</version>
    </dependency>
    <!--Junit测试-->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
    <!--数据库连接池-->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.10</version>
    </dependency>
    <!--Spring整合junit测试-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>5.0.2.RELEASE</version>
        <scope>test</scope>
    </dependency>
    <!--mysql-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.6</version>
    </dependency>

    <!-- AOP联盟 -->
    <dependency>
        <groupId>aopalliance</groupId>
        <artifactId>aopalliance</artifactId>
        <version>1.0</version>
    </dependency>
    <!-- Spring Aspects -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>5.0.2.RELEASE</version>
    </dependency>
    <!-- aspectj -->
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.8.3</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>5.0.2.RELEASE</version>
    </dependency>

</dependencies>

service代码的编写

package com.qcby.service;

import com.qcby.model.Account;

public interface AccountService {
    public void updateSaveAll(Account account1, Account account2);
}
package com.qcby.service.Impl;

import com.qcby.dao.AccountDao;
import com.qcby.model.Account;
import com.qcby.service.AccountService;


public class AccountServiceImpl implements AccountService{

    private AccountDao accountDao;


    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }

    @Override
    public void updateSaveAll(Account account1, Account account2) {
        //try {
            //TxUtils.startTransaction();
            //保存账号1
            accountDao.updateSaveAll(account1);
            //显示除零错误
            //int a=1/0;
            //保存账户2
            accountDao.updateSaveAll(account2);
            //TxUtils.commit();
        //}catch (Exception e){
            //e.printStackTrace();
            //TxUtils.rollback();
        //}

    }
}

dao代码的编写

package com.qcby.dao;

import com.qcby.model.Account;

public interface AccountDao {
    public void updateSaveAll(Account account);
}
package com.qcby.dao.Impl;

import com.qcby.dao.AccountDao;
import com.qcby.model.Account;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.support.JdbcDaoSupport;


public class AccountDaoImpl implements AccountDao {

    private JdbcTemplate jdbcTemplate;

    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    //实现两个账户的转账
    @Override
    public void updateSaveAll(Account account) {

        jdbcTemplate.update("update account set money = money + ? where name = ?",account.getMoney(),account.getName());


    }
}

配置文件代码编写

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

    <bean id="accountService" class="com.qcby.service.Impl.AccountServiceImpl">
        <property name="accountDao" ref="accountDao"/>
    </bean>


    <bean id="accountDao" class="com.qcby.dao.Impl.AccountDaoImpl">
        <property name="jdbcTemplate" ref="jdbcTemplate"/>
    </bean>

    <!--配置Jdbc模板类-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!--使用提供标签的方式-->
    <context:property-placeholder location="classpath:jdbc.properties"/>

    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driverClassName}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

</beans>

测试代码编写

package com.qcby.Test;

import com.qcby.model.Account;
import com.qcby.service.AccountService;
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;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class Test01 {

    @Autowired
    private AccountService accountService;

    @Test
    public void TestPay(){
        Account account1 = new Account(null,"aaa",-1000.00);
        Account account2 = new Account(null,"bbb",1000.00);
        accountService.updateSaveAll(account1,account2);
    }
}

Dao编写的方式(第二种方式)

package com.qcby.dao.Impl;

import com.qcby.dao.AccountDao;
import com.qcby.model.Account;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.support.JdbcDaoSupport;


public class AccountDaoImpl2 extends JdbcDaoSupport implements AccountDao {


    //实现两个账户的转账
    @Override
    public void updateSaveAll(Account account) {

        this.getJdbcTemplate().update("update account set money = money + ? where name = ?",account.getMoney(),account.getName());


    }
}
<?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: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/aop
                http://www.springframework.org/schema/aop/spring-aop.xsd">

    <bean id="accountService" class="com.qcby.service.Impl.AccountServiceImpl">
        <property name="accountDao" ref="accountDao"/>
    </bean>

    <bean id="accountDao" class="com.qcby.dao.Impl.AccountDaoImpl2">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!--<bean id="accountDao" class="com.qcby.dao.Impl.AccountDaoImpl">
        <property name="jdbcTemplate" ref="jdbcTemplate"/>
    </bean>-->

    <!--配置Jdbc模板类-->
    <!--<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">-->
        <!--<property name="dataSource" ref="dataSource"/>-->
    <!--</bean>-->

    <!-- 第二种写法:使用提供标签的方式-->
    <context:property-placeholder location="classpath:jdbc.properties"/>
    <!--加载属性的文件-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driverClassName}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

</beans>
package com.qcby.Test;

import com.qcby.model.Account;
import com.qcby.service.AccountService;
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;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext_dao2.xml")
public class Test02 {

    @Autowired
    private AccountService accountService;

    @Test
    public void TestPay(){
        Account account1 = new Account(null,"aaa",-1000.00);
        Account account2 = new Account(null,"bbb",1000.00);
        accountService.updateSaveAll(account1,account2);
    }
}

其余地方没有改变

Spring框架的事务管理

Spring框架的事务管理相关的类和API

PlatformTransactionManager接口

​ 平台事务管理器。该接口有具体的实现类,根据不同的持久层框架,需要选择不同的实现类!相当于JdbcUtil工具类,这个接口中提供了提交事务,回滚事务等方法。

​ 接口方法如下:

​ DataSourceTransactionManager 使用的Spring的JDBC模板或者MyBatis框架时选择

​ HibernateTransactionManager 使用的是Hibernate的框架时选择

方法

说明

TransactionStatus getTransaction(TransactionDefinition definition)

获取事务状态信息

void commit(TransactionStatus status)

提交事务

void rollback(TransactionStatus status)

回滚事务

TransactionDefinition接口,事务定义信息接口

方法

说明

int getPropagationBehavior()

获得事务的隔离级别

int getIsolationLevel();

获得事务的传播行为

int getTimeout();

获得超过时间

boolean isReadOnly();

是否为只读

事务的传播行为

  1. REQUIRED(默认):如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。
  2. SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务方式执行。
  3. MANDATORY:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
  4. REQUIRES_NEW:总是创建一个新的事务,如果当前存在事务,则挂起当前事务。
  5. NOT_SUPPORTED:总是以非事务方式执行,如果当前存在事务,则挂起当前事务。
  6. NEVER:总是以非事务方式执行,如果当前存在事务,则抛出异常。
  7. NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则表现同REQUIRED。

Spring框架声明式事务管理

配置文件方式

引入依赖

<dependencies>
    <!--spring的核心-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.0.2.RELEASE</version>
    </dependency>
    <!--日志-->
    <dependency>
        <groupId>commons-logging</groupId>
        <artifactId>commons-logging</artifactId>
        <version>1.2</version>
    </dependency>
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.12</version>
    </dependency>
    <!--Junit测试-->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
    <!--数据库连接池-->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.10</version>
    </dependency>
    <!--Spring整合junit测试-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>5.0.2.RELEASE</version>
        <scope>test</scope>
    </dependency>
    <!--mysql-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.6</version>
    </dependency>

    <!-- AOP联盟 -->
    <dependency>
        <groupId>aopalliance</groupId>
        <artifactId>aopalliance</artifactId>
        <version>1.0</version>
    </dependency>
    <!-- Spring Aspects -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>5.0.2.RELEASE</version>
    </dependency>
    <!-- aspectj -->
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.8.3</version>
    </dependency>

    <!-- JdbcTemplate模板 -->
    <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>

</dependencies>

编写实体类

package com.qcby.model;

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

    public Account() {
    }

    public Account(Integer id, String name, Double money) {
        this.id = id;
        this.name = name;
        this.money = 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 +
                '}';
    }
}

编写配置文件

对updateSaveAll进行增强,设置隔离级别为READ_COMMITTED读已提交

可以解决在转账过程中出错所造成的转账丢失问题

DEFAULT使用默认隔离级别

事务隔离级别

  1. READ_UNCOMMITTED(读未提交)
  2. READ_COMMITTED(读已提交)
  3. REPEATABLE_READ(可重复读)
  4. SERIALIZABLE(串行化)
<?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:aop="http://www.springframework.org/schema/aop"
       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/aop
                http://www.springframework.org/schema/aop/spring-aop.xsd
                http://www.springframework.org/schema/tx
                http://www.springframework.org/schema/tx/spring-tx.xsd">

    <!--使用提供标签的方式-->
    <context:property-placeholder location="classpath:jdbc.properties"/>

    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driverClassName}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

    <!--配置平台事务管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!--配置事务的通知(没有自己编写切面类,通知方法也不是自己编写,Spring框架提供的)-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <!-- 对updateSaveAll进行增强,设置隔离级别,传播行为,超时的时间  -->
            <tx:method name="updateSaveAll" isolation="DEFAULT" propagation="REQUIRED"/>
            <tx:method name="find*" read-only="true"/>
        </tx:attributes>

    </tx:advice>

    <!--配置AOP的增强-->
    <aop:config>

        <!--SPringle框架提供系统通知,使用advisor标签-->
        <aop:advisor advice-ref="txAdvice" pointcut="execution(public * com.qcby.service.Impl.AccountServiceImpl.updateSaveAll(..))"/>
    </aop:config>

    <!-- 配置Jdbc模板类-->
    <!--<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>-->

    <!--配置service-->
    <bean id="accountService" class="com.qcby.service.Impl.AccountServiceImpl">
        <property name="accountDao" ref="accountDao"/>
    </bean>

    <!--配置dao-->
    <!--<bean id="accountDao" class="com.qcby.dao.Impl.AccountDaoImpl">
        <property name="jdbcTemplate" ref="jdbcTemplate"/>
    </bean>-->

    <bean id="accountDao" class="com.qcby.dao.Impl.AccountDaoImpl">
        <property name="dataSource" ref="dataSource"/>
    </bean>
  1. name:切点方法名称
  2. isolation:事务的隔离级别
  3. propogation:事务的传播行为
  4. timeout:超时时间
  5. read-only:是否只读

持久层

package com.qcby.dao;

import com.qcby.model.Account;

public interface AccountDao {
    public void updateSaveAll(Account account);
}
package com.qcby.dao.Impl;

import com.qcby.dao.AccountDao;
import com.qcby.model.Account;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.support.JdbcDaoSupport;


/*public class AccountDaoImpl implements AccountDao {

    private JdbcTemplate jdbcTemplate;

    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    //实现两个账户的转账
    @Override
    public void updateSaveAll(Account account) {

        jdbcTemplate.update("update account set money = money + ? where name = ?",account.getMoney(),account.getName());


    }
}*/

public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao {


    //实现两个账户的转账
    @Override
    public void updateSaveAll(Account account) {

        this.getJdbcTemplate().update("update account set money = money + ? where name = ?",account.getMoney(),account.getName());


    }
}

业务层没有改动

配置文件+注解的方式

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

    <!--开启注解的扫描-->
    <context:component-scan base-package="com.qcby"/>

    <!--使用提供标签的方式-->
    <context:property-placeholder location="classpath:jdbc.properties"/>

    <!--加载属性的文件-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driverClassName}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

    <!--配置平台事务管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>


    <!-- 配置Jdbc模板类-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!--开启事务注解的支持-->
    <tx:annotation-driven transaction-manager="transactionManager"/>


</beans>

service代码

package com.qcby.service.Impl;


import com.qcby.dao.AccountDao;
import com.qcby.model.Account;
import com.qcby.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional(isolation = Isolation.DEFAULT)
public class AccountServiceImpl implements AccountService {

    @Autowired
    private AccountDao accountDao;


    @Override
    public void updateSaveAll(Account account1, Account account2) {

            //保存账号1
            accountDao.updateSaveAll(account1);
            //显示除零错误
            //int a=1/0;
            //保存账户2
            accountDao.updateSaveAll(account2);


    }
}

纯注解的方式

package com.qcby.utils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.annotation.Resource;
import javax.sql.DataSource;

/**
 * 配置类
 * @author Administrator
 */
@Configuration
@ComponentScan("com.qcby")
@EnableTransactionManagement//开启事务注解
public class SpringConfig {
    @Bean(name="dataSource")
    public DataSource createDataSource() throws Exception {
        // 创建连接池对象,Spring框架内置了连接池对象
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        // 设置4个参数
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/spring_db");
        dataSource.setUsername("root");
        dataSource.setPassword("2020");
        return dataSource;
    }
    @Resource(name="dataSource")        // 不仅可以作用在属性上,也可以作用方法上。
    @Bean(name="jdbcTemplate")          // 把JdbcTemplate保存到IOC容器中
    public JdbcTemplate createJdbcTemplate(DataSource dataSource) {
        JdbcTemplate template = new JdbcTemplate(dataSource);
        return template;
    }

    @Resource(name="dataSource")
    @Bean(name="transactionManager")
    public PlatformTransactionManager createTransactionManager(DataSource dataSource){
        DataSourceTransactionManager manager = new DataSourceTransactionManager(dataSource);
        return manager;
    }
}

http://www.kler.cn/a/385088.html

相关文章:

  • 【启程Golang之旅】一站式理解Go语言中的gRPC
  • c++程序设计速学4字符串处理
  • 谷歌地图和高德地图JSAPI宝典(Vue2和Vu3通用)
  • 软件设计师-上午题-14 信息安全(5分)
  • RAG(检索增强生成)的实现流程;RAG怎么实现检索增强的
  • 分布式——BASE理论
  • 新华三H3CNE网络工程师认证—VLAN的配置
  • 23种设计模式总结
  • PyQt6应用程序中,如何实现多种语言支持
  • ajax关于axios库的运用小案例
  • 网页版五子棋——匹配模块(客户端开发)
  • 一、文心一言问答系统为什么要分对话,是否回学习上下文?二、文心一言是知识检索还是大模型检索?三、文心一言的词向量、词语种类及多头数量
  • Python中处理Excel的基本概念(如工作簿、工作表等)
  • 【数据结构】一文讲解线性表之顺序表概念及其基本操作(附C语言源码)
  • 鸿蒙的进击之路
  • 享元模式在 JDK 中的应用解析
  • MySQL 多数据库备份与恢复,包括查询,函数,SP
  • 笔记--(5)、acl ACL
  • 哈希表(Hash Table)、跳表(Skip List) 和 有序字典(Ordered Dictionary) 的详细介绍
  • 51c大模型~合集17
  • 当RFID技术遇上消防应急管理,智慧响应来袭!
  • node.js实现批量修改git项目的数据源
  • ffmpeg命令——从wireshark包中的rtp包中分离h264
  • 云原生+AI核心技术&最佳实践
  • 外包干了2年,快要废了。。
  • 【Golang】Golang的Map的底层原理