Spring JDBC及声明式事务

news2024/9/27 13:46:00

目录

Spring JDBC基础概念        

Spring声明式事务

 事务传播方式


Spring JDBC基础概念        

        Spring JDBC 封装了原生的JDBC API,使得处理关系型数据库更加简单。Spring JDBC的核心是JdbcTemplate,里面封装了大量数据库CRUD的操作。使用Spring JDBC有如下步骤:

1、pom增加依赖

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.20.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.6</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.2.22.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.16</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
        </dependency>

spring-context是spring的核心,负责容器中对象实例创建;spring-jdbc是对原生jdbc的封装;logback-classic主要为了数据库操作时辅助信息的日志输出。

2、IOC容器实例化数据源对象dataSource和JdbcTemplate对象

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/tx
        https://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd">
    <context:component-scan base-package="com.text"/>

    <bean id="dataSource"  class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://xxx.xxx.xxx.xxx:3306/test"></property>
        <property name="username" value="test"></property>
        <property name="password" value="test"></property>
    </bean>
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
</beans>

 3、在各个DAO实现类中注入JdbcTemplate对象,通过JdbcTemplate的API实现数据库CRUD

JdbcTemplate的API重要的API:

  • jdbcTemplate.query* :各种查询方法
  • jdbcTemplate.update:各种新增、修改、删除等方法

示例:学生信息查询、新增

package com.text.dao.impl;

import com.text.dao.StudentDao;
import com.text.entity.Student;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import javax.annotation.Resource;

@Repository
public class StudentDaoImpl implements StudentDao {

    @Resource
    private JdbcTemplate jdbcTemplate;
    @Override
    public Student getById(String id) throws Exception {
        String sql = "select * from student where id = ?";
        Student student = jdbcTemplate.queryForObject(sql, new Object[]{id}, new BeanPropertyRowMapper<>(Student.class));
        return student;
    }

    @Override
    public void insert(Student student) throws Exception {
        String sql = "insert into student(id,name,age) values (?,?,?)";
        jdbcTemplate.update(sql,new Object[]{student.getId(),student.getName(),student.getAge()});
    }
}

Spring声明式事务

        上文的案例中,没有添加事务支持,如果在Service层封装了Dao层并且做了批量操作的动作,在批量操作时系统出现异常,会出现部分数据提交到数据库的情况,不满足数据同时提交、同时回滚的情况,参考代码如下:

1、Service服务类

package com.text.service;

import com.text.entity.Student;

public interface StudentService {
    void batchSave() throws Exception;
    Student searchById(String id) throws Exception;
}
package com.text.service.impl;

import com.text.dao.StudentDao;
import com.text.entity.Student;
import com.text.service.StudentService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

@Service
public class StudentServiceImpl implements StudentService {

    @Resource
    private StudentDao studentDao;

    @Override
    public void batchSave() throws Exception {
        for(int i=10;i<=20;i++) {
            if(i==15) {
                throw new RuntimeException("系统出现异常");
            }
            Student student = new Student(i+"","张三"+i,20);
            this.studentDao.insert(student);
        }
    }

    @Override
    public Student searchById(String id) throws Exception {
        return this.studentDao.getById(id);
    }
}

 2、测试类

package com.text;

import com.text.entity.Student;
import com.text.service.StudentService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Application {
    public static void main(String[] args) throws Exception {
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        StudentService studentService = context.getBean("studentServiceImpl", StudentService.class);
        Student student = studentService.searchById("1");
        System.out.println(student);
        studentService.batchSave();
    }
}

3、运行结果分析:

 

从程序运行结果可以看出,程序循环插入10条数据时,程序每次都获取新的数据库连接,程序执行到第15条时,系统发生异常,前面10-14条数据提交到了数据库,不满足10条数据同时提交或同时回滚,通过配置事务管理器可以解决此问题。

        Spring声明式事务是针对编程式事务而言的,编程式事务就是在程序内部手工的编写Commit和Rollback方法进行事务的提交和回滚,编写相对麻烦,本文重点讨论基于注解声明式事务

        Spring声明式事务,实现的原理就是AOP的环绕通知,在程序全部执行正常后,自动提交事务,在程序出现异常时,自动回滚事务。实现基于注解Spring声明式事务,经过如下步骤:

1、配置事务管理器及开启注解形式的声明式事务

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/tx
        https://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd">
    <context:component-scan base-package="com.text"/>

    <bean id="dataSource"  class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://xxx.xxx.xxx.xxx:3306/test"></property>
        <property name="username" value="test"></property>
        <property name="password" value="test"></property>
    </bean>
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!--事务管理器-->
    <bean id="transactionManager"     class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!-- 启用注解形式声明式事务 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>
</beans>

2、在需要事务的服务类上添加注解@Transactional

package com.text.service.impl;

import com.text.dao.StudentDao;
import com.text.entity.Student;
import com.text.service.StudentService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

@Service
public class StudentServiceImpl implements StudentService {

    @Resource
    private StudentDao studentDao;

    @Transactional //添加事务支持
    @Override
    public void batchSave() throws Exception {
        for(int i=10;i<=20;i++) {
            if(i==15) {
                throw new RuntimeException("系统出现异常");
            }
            Student student = new Student(i+"","张三"+i,20);
            this.studentDao.insert(student);
        }
    }

    @Override
    public Student searchById(String id) throws Exception {
        return this.studentDao.getById(id);
    }
}

3、测试类(和上面一致),运行后结果:

     

从运行结果看出,由于service的批量插入方法上添加了事务支持,批量新增时,用的是同一个数据库连接,系统发生异常后,数据没有出现部分提交的情况。

 事务传播方式

        Spring事务的默认的事务传播特性是Required,即当前环境没有事务,则创建一个事务,如果已经在一个事务中,则加入这个事务中。几种事务传播特性如下:

  1. required  如果有事务正在运行,当前方法就在这个事务内运行,否则就启动一个新的事务,并在自己的事务内运行;
  2. requires_new 总是主动开启事务;如果存在外层事务,就将外层事务挂起
  3. supports 如果不存在外层事务,就不开启事务;否则使用外层事务
  4. not_supported 当前的方法不应该运行在事务中,如果当前有运行的事务,将它挂起
  5. mandatory 当前的方法必须运行在事务内部,如果没有正在运行的事务,就抛出异常
  6. never 当前的方法不应该运行在事务中,如果运行在事务中就抛出异常
  7. nested 如果有事务在运行,当前的方法就应该在这个事务的嵌套事务内运行,否则就启动一个新的事务,并在它自己的事务内运行    

示例:requires_new 总是主动开启事务;如果存在外层事务,就将外层事务挂起

A方法调用了B和C,其中A,B和C采用的是requires_new 传播特性,则程序内部事务如下示意图:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2170137.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

八大核心能力铸就销售精英:解锁成功销售的密钥

成功销售&#xff0c;既是精妙绝伦的艺术展现&#xff0c;也是融汇多元技能的卓越实践。无论企业处于初创的萌芽阶段&#xff0c;还是屹立行业的巅峰之列&#xff0c;跨越销售高峰的征途上&#xff0c;销售人员所掌握的八大核心能力&#xff0c;如同星辰指引&#xff0c;不可或…

高性能、高可靠,MK SD卡让数据存储无忧!

文章目录 SD卡&#xff08;Secure Digital Memory Card&#xff09;&#xff0c;作为当代数字生活中不可或缺的存储媒介&#xff0c;凭借其卓越的数据传输效率、灵活的热插拔功能以及惊人的存储容量&#xff0c;在多个领域大放异彩。从日常使用的智能手机、平板电脑到追求极致体…

【ARM】解决ArmDS Fast Models 中部分内核无法上电的问题

【更多软件使用问题请点击亿道电子官方网站】 1、 文档目标 解决ArmDS Fast Models 中部分内核无法上电的问题。 2、 问题场景 在调用ArmDS的Fast Models中的Cortex-A55的模型&#xff0c;只有Core 0是上电状态&#xff0c;而Core 1处于掉电状态&#xff0c;如图2-1所示&…

美国林氏集团宣布全面进军Web3领域

吉隆坡&#xff0c;马来西亚——近日举行的第六界博览会上&#xff0c;美国林氏集团董事局主席林建中先生宣布&#xff0c;集团将通过旗下的大东亚银行创建一个全新的、合规的区块链交易所&#xff0c;并正式进军Web3、元宇宙及AI领域。同时&#xff0c;美国林氏集团将利用其在…

物流的总结

pc端&#xff08;商家端到仓、冷链&#xff0c;管理端冷链数据&#xff09;、H5、小程序&#xff08;冷链&#xff09; 冷链快运系统介绍文档 1. 系统概述 冷链快运系统致力于确保温控产品在运输过程中的安全与质量&#xff0c;通过高效的运单管理、异常处理及预约服务&#…

彻底解决找不到vcomp140.dll,无法继续执行代码问题

1. msvcp140.dll 简介 1.1 定义与作用 msvcp140.dll 是 Microsoft Visual C 2015 Redistributable Package 的一部分&#xff0c;它是一个动态链接库&#xff08;DLL&#xff09;文件&#xff0c;包含了运行使用 Visual C 2015 编译的应用程序所必需的 C 运行时库函数。这个文…

【web阅读记录】web相关概念及知识整理

刷到了一篇web相关的入门贴。解答了一些多年来的疑惑。这是一些在阅读过程中的笔记记录. 参考链接&#xff1a; https://www.jianshu.com/nb/4686146 服务器/客户机 ---->浏览器 JavaScript与Java没有任何关系 Node.js:一个javaScript运行环境 框架(FrameWork):由基本原…

Angular由一个bug说起之十:npm Unsupported engine

我们在用npm下载包的时候&#xff0c;有时候会碰到这样的提示 这是npm的警告&#xff0c;说我们使用的nodejs版本与下载的包所要求的nodejs版本不一致。 这是因为有些包它对nodejs的版本有要求&#xff0c;然后就会在package.json文件里的engines字段里声明它所要求的nodejs版本…

ElasticSearch的安装与使用

ElasticSearch的安装与使用 docker安装 docker进行安装Elasticsearch 1.拉取镜像 docker pull elasticsearch:7.6.22.创建实例 mkdir -p /docker/elasticsearch/config mkdir -p /docker/elasticsearch/data echo "http.host: 0.0.0.0" >> /docker/elastic…

【C++】红黑树的封装——同时实现map和set

目录 红黑树的完善默认成员函数迭代器的增加 红黑树的封装红黑树模板参数的控制仿函数解决取K问题对Key的非法操作 insert的调整map的[]运算符重载 在list模拟实现一文中&#xff0c;介绍了如何使用同一份代码封装出list的普通迭代器和const迭代器。今天学习STL中两个关联式容器…

DTH11温湿度传感器

DHT11 是一款温湿度复合传感器&#xff0c;常用于单片机系统中进行环境温湿度的测量。以下是对 DHT11 温湿度传感器的详细讲解&#xff1a; 一、传感器概述 DHT11 数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。它应用专用的数字模块采集技术和温湿度传感…

如何在Unity WebGL上实现一套全流程简易的TextureStreaming方案

项目介绍 《云境》是一款使用Unity引擎开发的WebGL产品&#xff0c;有展厅&#xff0c;剧本&#xff0c;Avatar换装&#xff0c;画展&#xff0c;语音聊天等功能&#xff0c;运行在微信小程序和PC&#xff0c;移动端网页&#xff0c;即开即用。 当前问题和现状 当前项目…

Qt-QTableWidget多元素控件(37)

目录 描述 QTableWidget 方法 QTableWidgetItem 信号 QTableWidgetItem 方法 使用 图形化界面操作 代码操作 描述 这是一个表格控件&#xff0c;表格中的每一个单元格&#xff0c;都是一个 QTableWidgetItem 对象 QTableWidget 方法 item(int row,int column)根据⾏数…

[半导体检测-7]:半导体检测技术:无图案晶圆检测与图案晶圆检测

前言&#xff1a; 半导体检测技术中&#xff0c;无图案晶圆检测与图案晶圆检测是两种重要的检测方式&#xff0c;它们在检测原理、应用场景及挑战等方面存在显著差异。以下是对这两种检测技术的详细分析&#xff1a; 一、无图案晶圆检测 1. 检测原理 无图案晶圆检测主要关注…

DRF实操学习——收货地址的设计

DRF实操学习——收货地址的设计 1.行政区划表的设计2. 行政区划表接口演示1.返回所有的省份2. 查询指定上级行政区划的所有子区划&#xff0c;以及展示自身区划 3.行政区划表接口重写补充&#xff1a;前端请求逻辑4. 优化5.收货地址的设计6. 收货地址表接口重写7.优化1. 优化返…

Android 12系统源码_输入系统(三)输入事件的加工和分发

前言 上一篇文章我们具体分析了InputManagerService的构造方法和start方法&#xff0c;知道IMS的start方法经过层层调用&#xff0c;最终会触发Navite层InputDispatcher的start方法和InputReader的start方法。InputDispatcher的start方法会启动一个名为InputDispatcher的线程&…

混拨动态IP代理的优势是什么

在当今互联网时代&#xff0c;隐私保护和网络安全成为了人们关注的焦点。无论是个人用户还是企业&#xff0c;都希望能够在网络上自由、安全地进行各种活动。混拨动态IP代理作为一种新兴的技术手段&#xff0c;正逐渐受到大家的青睐。那么&#xff0c;混拨动态IP代理到底有哪些…

【工具】JDK版本不好管理,SDKMAN来帮你

前言 &#x1f34a;缘由 SDKMAN真是好&#xff0c;JDK切换没烦恼 &#x1f423; 闪亮主角 大家好&#xff0c;我是JavaDog程序狗 今天跟大家能分享一个JDK版本管理工具SDKMAN 当你同时使用JDK 1.8的和JDK 17并行维护两个项目时。每次在两个项目之间并行开发&#xff0c;切…

进阶数据库系列(十三):PostgreSQL 分区分表

概述 在组件开发迭代的过程中&#xff0c;随着使用时间的增加&#xff0c;数据库中的数据量也不断增加&#xff0c;因此数据库查询越来越慢。 通常加速数据库的方法很多&#xff0c;如添加特定的索引&#xff0c;将日志目录换到单独的磁盘分区&#xff0c;调整数据库引擎的参…

2.4卷积3

2.4卷积3 文章学习自https://zhuanlan.zhihu.com/p/41609577&#xff0c;详细细节请读原文。 狄拉克 δ \delta δ 函数&#xff1a; δ ( x ) { ∞ , x 0 0 , x ≠ 0 \delta (x){\begin{cases} \infty ,& x0\\ 0,& x\neq 0\end{cases}} δ(x){∞,0,​x0x0​ 并…