Spring JDBC及声明式事务

embedded/2024/10/16 4:33:08/

目录

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/beanshttps://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttps://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/txhttps://www.springframework.org/schema/tx/spring-tx.xsdhttp://www.springframework.org/schema/aophttps://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 {@Resourceprivate JdbcTemplate jdbcTemplate;@Overridepublic 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;}@Overridepublic 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 {@Resourceprivate StudentDao studentDao;@Overridepublic 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);}}@Overridepublic 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/beanshttps://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttps://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/txhttps://www.springframework.org/schema/tx/spring-tx.xsdhttp://www.springframework.org/schema/aophttps://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 {@Resourceprivate StudentDao studentDao;@Transactional //添加事务支持@Overridepublic 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);}}@Overridepublic 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.ppmy.cn/embedded/118669.html

相关文章

自己开发一个网站系列之-从基础到高级

自己开发一个网站系列之-从基础到高级 在上一篇博客中&#xff0c;我们介绍了网页开发的基础知识&#xff0c;包括HTML、CSS和JavaScript的基本用法。这是一个很好的起点&#xff0c;但如果你想进一步提升自己的技能&#xff0c;掌握更多高级概念和技术&#xff0c;就必须深入…

【CSS】字体文本

color 颜色font-size 大小font-family 字体font-style 样式font-weight 加粗text-decoration 下划线text-shadow 阴影text-transform 大小写变换text-indent 缩进text-align 水平对齐 、vertical-align垂直对齐text-overflow 溢出word-wrap 换行word-break 截断white-space 空白…

基于深度学习的虚拟环境生成

基于深度学习的虚拟环境生成是利用深度学习技术自动创建复杂的三维虚拟场景和环境。这一领域在游戏开发、虚拟现实&#xff08;VR&#xff09;、增强现实&#xff08;AR&#xff09;、模拟训练等方面有广泛的应用。以下是这一领域的主要技术和方法概述&#xff1a; 1. 生成对抗…

MATLAB Function模块用法案例

Simulink中的MATLAB Function模块是一个非常灵活的工具&#xff0c;允许用户直接在Simulink模型中嵌入MATLAB代码&#xff0c;以实现自定义的算法或功能 MATLAB Function模块的基本用法 添加模块&#xff1a; 在Simulink的模型窗口中&#xff0c;通过搜索“MATLAB Function”…

PostgreSQL分区表

一、分区表的作用 1. 将数据按指定的方法打算到子分区&#xff0c;提高 SQL 性能。 2. 解决时序类、流水类业务大表在进行老旧数据清理时 delete 引起的性能及磁盘空间碎片问题。 3. 利用子分区卸载、重新挂载功能&#xff0c;对数据进行暂时性的隐藏、维护。 4. 数据归档治…

c++----继承(初阶)

大家好呀&#xff0c;今天我们也是多久没有更新博客了&#xff0c;今天来讲讲我们c加加中的一个比较重要的知识点继承。首先关于继承呢&#xff0c;大家从字面意思看&#xff0c;是不是像我们平常日常生活中很容易出现的&#xff0c;比如说电视剧里面什么富豪啊&#xff0c;去了…

数据结构(7.3_5)——红黑树的插入和删除

红黑树的插入 注意&#xff1a;插入时候重点考察“不红红”特性&#xff08;红黑树的性质&#xff09; 染色&#xff1a;哪几个结点有变动就红的变黑&#xff0c;黑的变红 RR、LL、LR、RL从爷结点开始算起 非根结点的插入只需要判断是否违背的“不红红”特性 练习&#xff1…

设计模式-行为型模式-中介者模式

1.中介者模式定义 定义一个单独的&#xff08;中介&#xff09;对象&#xff0c;来封装一组对象之间的交互&#xff0c;将这组对象之间的交互委派给中介对象交互&#xff0c;从而避免对象之间的交互&#xff1b; 中介者模式主要解决对象间的交互复杂性问题&#xff0c;而代理模…