spring boot最新教程(三):Spring Boot整合JdbcTemplate以及事务管理

2023-11-01

一  JdbcTemplate的使用

       Spring对数据库的操作在jdbc上面做了深层次的封装,使用spring的注入功能,可以把DataSource注册到JdbcTemplate之中。 JdbcTemplate 是在JDBC API基础上提供了更抽象的封装,并提供了基于方法注解的事务管理能力。 通过使用SpringBoot自动配置功能并代替我们自动配置beans. 在maven中,我们需要增加spring-boot-starter-jdbc模块

<!-- jdbcTemplate 以及事务支持-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-jdbc</artifactId>
		</dependency>

点开spring boot的自动配置包spring-boot-autoconfigure-1.5.2.RELEASE.jar,找到如下所示代码


发现spring boot已经自动帮我们初始化好了jdbcTemplate对象,并且默认采用tomcat数据源dataSource,当然我们提供的数据源,系统将采用我们自定义的数据源!

完整的pom文件如下所示:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.wx</groupId>
	<artifactId>springboot02</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.2.RELEASE</version>
	</parent>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<!-- jdbcTemplate 以及事务支持-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-jdbc</artifactId>
		</dependency>

		<!-- MySQL连接 -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.apache.tomcat.embed</groupId>
			<artifactId>tomcat-embed-jasper</artifactId>
			<scope>provided</scope>
		</dependency>
		<!-- jstl标签库 -->
		<dependency>
			<groupId>jstl</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>
		<!-- 阿里巴巴json解析包 -->
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
			<version>1.1.15</version>
		</dependency>
		<!-- 阿里巴巴druid连接池 -->
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid</artifactId>
			<version>1.0.9</version>
		</dependency>
	</dependencies>
	<build>
		<finalName>${project.artifactId}</finalName>
		<plugins>
			<!-- java编译插件 -->
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<configuration>
					<source>1.7</source>
					<target>1.7</target>
					<encoding>UTF-8</encoding>
				</configuration>
			</plugin>
			<!-- 如果你不想用maven命令运行spring boot可以不用作此配置 -->
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>

	</build>
</project>

好,接下来我们来看代码

sql脚本

CREATE TABLE users
(
  userId INT PRIMARY KEY AUTO_INCREMENT,
  userName VARCHAR(20) NOT NULL,
  PASSWORD VARCHAR(20) NOT NULL,
  email VARCHAR(50)
);
INSERT INTO users(userName,PASSWORD,email) VALUES('jack','123','jack@126.com');
INSERT INTO users(userName,PASSWORD,email) VALUES('mike','123','mike@126.com');
INSERT INTO users(userName,PASSWORD,email) VALUES('麻子','123','mazi@126.com');

CREATE TABLE account (
  acctId INT(11) NOT NULL,
  userName VARCHAR(20) NOT NULL,
  balance DOUBLE DEFAULT NULL,
  PRIMARY KEY (acctId)
)

INSERT INTO account VALUES(100,'麻子',2000);
INSERT INTO account VALUES(101,'小丽',2000);

数据源的配置类如下

package com.wx.boot;

import java.sql.SQLException;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

import com.alibaba.druid.pool.DruidDataSource;

@Configuration
@PropertySource(value = { "classpath:druidConfig.properties",
"classpath:jdbc.properties" }, ignoreResourceNotFound = true)
public class DataSourceConfig {
	@Value("${driverClassName}")
	private String driverClassName;
	@Value("${url}")
	private String url;
	@Value("${duridUserName}")
	private String username;
	@Value("${password}")
	private String password;
	@Value("${filters}")
	private String filters;
	@Value("${initialSize}")
	private int initialSize;
	@Value("${maxActive}")
	private int maxActive;
	@Value("${minIdle}")
	private int minIdle;
	@Value("${maxWait}")
	private int maxWait;
	@Value("${validationQuery}")
	private String validationQuery;
	@Value("${testWhileIdle}")
	private boolean testWhileIdle;
	@Value("${testOnBorrow}")
	private boolean testOnBorrow;
	@Value("${testOnReturn}")
	private boolean testOnReturn;
	@Value("${maxPoolPreparedStatementPerConnectionSize}")
	private int maxPoolPreparedStatementPerConnectionSize;
	@Value("${removeAbandoned}")
	private boolean removeAbandoned;
	@Value("${removeAbandonedTimeout}")
	private int removeAbandonedTimeout;
	@Value("${timeBetweenEvictionRunsMillis}")
	private int timeBetweenEvictionRunsMillis;
	@Value("${minEvictableIdleTimeMillis}")
	private int minEvictableIdleTimeMillis;
	
	@Bean(initMethod="init",destroyMethod="close")
	public DruidDataSource dataSource(){
		DruidDataSource dataSource=new DruidDataSource();
		try {
			dataSource.setUrl(url);
			dataSource.setDriverClassName(driverClassName);
			dataSource.setUsername(username);
			dataSource.setPassword(password);
			dataSource.setFilters(filters);
			dataSource.setInitialSize(initialSize);
			dataSource.setMaxActive(maxActive);
			dataSource.setMinIdle(minIdle);
			dataSource.setMaxWait(maxWait);
			dataSource.setValidationQuery(validationQuery);
			dataSource.setTestWhileIdle(testWhileIdle);
			dataSource.setTestOnBorrow(testOnBorrow);
			dataSource.setTestOnReturn(testOnReturn);
			dataSource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
			dataSource.setRemoveAbandoned(removeAbandoned);
			dataSource.setRemoveAbandonedTimeout(removeAbandonedTimeout);
			dataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
			dataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
			System.out.println("连接池启动成功");
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return dataSource;
	}
}

其它配置请参考前面的文章

重点来看dao层代码

package com.wx.dao.user;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import com.wx.entitys.UserEntity;

@Repository("userDao")
public class UserDaoImpl implements IUserDao {
	@Autowired
	private JdbcTemplate jdbcTemplate;
	
	//判断用户是否登录成功
	public boolean isLogin(UserEntity paramUser) {
		boolean flag=false;
		String sqlStr="select * from users where userName=? and passWord=?";
		List<UserEntity> userList=jdbcTemplate.query(sqlStr, 
				new Object[]{paramUser.getUserName(),paramUser.getPassWord()}, 
				new BeanPropertyRowMapper(UserEntity.class));
		if(userList!=null && userList.size()>0){
			flag=true;
		}
		return flag;
	}
	
	//判断用户是否存在
	public boolean isUserExist(String userName) {
		boolean flag=false;
		String sqlStr="select * from users where userName=?";
		List<UserEntity> userList=jdbcTemplate.query(sqlStr, new Object[]{userName}, 
				new BeanPropertyRowMapper(UserEntity.class));
		if(userList!=null && userList.size()>0){
			flag=true;
		}
		return flag;
	}
	
	//保存用户
	public void save(UserEntity user) {
		String sqlStr="insert into users(userName,passWord,email) values(?,?,?)";
		jdbcTemplate.update(sqlStr, 
				user.getUserName(),user.getPassWord(),user.getEmail());
	}
}

二   事务问题

1. 传统事务处理方式

Spring支持使用注解配置声明式事务,所使用的注解是@Transactional。

首先仍然需要在Spring配置文件中配置事务管理类,并添加对注解配置的事务的支持,代码如示
<!-- 定义事务管理器 -->
	<bean id="txManager"
		class="org.springframework.orm.hibernate3.HibernateTransactionManager">
		<property name="sessionFactory" ref="sessionFactory" />
	</bean>
	<tx:annotation-driven transaction-manager="txManager" />

经过如上配置,程序便支持使用@Transactional来配置事务了,代码如下所示:

public class UserService {
	private UserDao userDao;
	
	@Transactional(readOnly=false, propagation=Propagation.REQUIRES_NEW)
	public void addUser(User user) {
		this.userDao.save(user);
	}
}

在业务方法上添加@Transactional就为该方法添加了事务处理,@Transactional中也可以设置事务属性的值,默认的@Transactional设置如下。

(1)事务传播设置是PROPACrATION_REQUIRED。

(2) 事务隔离级别是ISOLATION DEFAULT。

(3) 事务是读/写。

(4) 事务超时默认是依赖于事务系统的,或者事务超时没有被支持。

(5) 任何RuntimeException将触发事务回滚,但是任何checked Exception将不触发事务回滚。

这些默认的设置当然也是可以被改变的。@Transactional注解的各种属性设置总结如表所示。

表 @Transactional注解的属性

属  性

类  型

说    明

propagation

枚举型:Propagation

可选的传播性设置。使用举例:@Transacli onal(propagation=Propagation.REQUIRES_NEW)

isolation

枚举型:Esolation

可选的隔离性级别。使用举例:@Transactional(isolation=Isolation.READ COMMITTED)

readOnly

布尔型

是否为只读型事务。使用举例:

@Trans actional(readOnly=true)

tlmeoUt

int型(以秒为单位)

事务超时。使用举例:@T ransactional(timeout=1 0)

roIlbackFor

一组Class类的实例,必须是Throwable的予类

一组异常类,遇到时必须进行圆滚。使用举例:

@Transactional(rollbackFor={S QLException.class}),多个异常可用英文逗号隔开

rollbackForClassName

一组Class类的名称,必须是Throwable的子类

一组异常类名,遇到时必须进行圆滚。使用举例:

@Transactional(rollbackForClassName={”SQLException”}),多个异常可用英文逗号隔开

noRollbackFor

一组Class类的实例,必须是Throwable的子类

一组异常类,遇到时必须不圆滚

noRollbackForClassName

一组Class类的名字,必须是Throwable的子类

一组异常类名,遇到时必须不圆滚

2.  spring boot事务处理方式

在Spring Boot中推荐使用@Transactional注解来申明事务。

首先需要导入依赖:

<dependency>		     <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>

当引入jdbc依赖之后,Spring Boot会自动默认分别注入DataSourceTransactionManager或JpaTransactionManager,所以我们不需要任何额外配置就可以用@Transactional注解进行事务的使用。spring-boot-starter-jdbc会触发DataSourceTransactionManagerAutoConfiguration这个自动化配置类,会构造事务管理器,如下图:


在业务类中添加@Transactional注解:

package com.wx.biz;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.wx.dao.account.IAccountDao;

@Service("acctBiz")
public class AccountBiz {
	@Autowired
	private IAccountDao acctDao;
	
	//把转账封装成一个方法,保证事务的原子性
	@Transactional
	public void doTransfer(Integer srcUserId,Integer targetUserId,double amount){
		acctDao.doPay(srcUserId, amount);
		acctDao.doReceive(targetUserId, amount);
	}
	@Transactional
	public void doPay(Integer userId, double amount){
		acctDao.doPay(userId, amount);
	}
	@Transactional
	public void doReceive(Integer userId, double amount){
		acctDao.doReceive(userId, amount);
	}
}

我们也可以在dao层添加事务,下面来演示事务隔离级别

package com.wx.dao.account;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.wx.entitys.AccountEntity;

@Repository(value="acctDao")
public class AcountDaoImpl implements IAccountDao{
	@Autowired
	private JdbcTemplate jdbcTemplate;
	
	@SuppressWarnings("unchecked")
	//演示事务隔离级别,每次开启一个新事务,而不是使用已经开启的事务
	@Transactional(propagation=Propagation.REQUIRES_NEW)
	public int doPay(Integer acctId, double money) {
		int result=0;
		String sqlStr="update account set balance=balance-? where userId=?";
		result=jdbcTemplate.update(sqlStr, money,acctId);
		if(result==0){
			throw new RuntimeException("支付失败...");
		}
		return result;
	}
	
	@SuppressWarnings("unchecked")
	@Transactional(propagation=Propagation.REQUIRES_NEW)
	public int doReceive(Integer acctId, double money) {
		int result=0;
		String sqlStr="update account set balance=balance+? where userId=?";
		result=jdbcTemplate.update(sqlStr, money,acctId);
		if(result==0){
			throw new RuntimeException("收款失败...");
		}
		return result;
	}
}

@Transactional不仅可以注解在方法上,也可以注解在类上。当注解在类上的时候意味着所有的public方法都是开启事务的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

spring boot最新教程(三):Spring Boot整合JdbcTemplate以及事务管理 的相关文章

随机推荐

  • linux配置jdk,jenkins,python3,git

    一 安装jdk 自动化测试的主要目的是为了执行回归测试 当然 为了模拟真实的用户操作 一般都是在UAT或者生产环境进行回归测试 为了尽量避免内网和外网解析对测试结果的影响 将自动化测试服务部署在外网的服务器是比较好的选择 今天申请的测试服务
  • java中instanceof用法

    java 中的instanceof 运算符是用来在运行时 color red b 指出对象是否是特定类的一个实例 b color instanceof通过返回一个布尔值来指出 这个对象是否是这个特定类或者是它的子类的一个实例 用法 resu
  • 马尔科夫区制转换matlab,马尔科夫区制转移混频向量自回归(MS-MF-VAR)模型及其Gauss实现...

    导读 马尔科夫区制转移向量自回归模型可以进行实时 real time 预测分析 扩展容纳混合频率和锯齿数据 可以看作是MF VAR模型的马尔科夫区制转移 Markov switching 扩展 从经验上讲 该模型能够非常准确地捕捉到美国的经
  • Python3.0 基础系列教程(目录)

    准备写一篇python的系列教程 目录暂定如下 如果有更好的建议 麻烦下方留言 如无意外 大约一周2 3篇 敬请期待 环境安装篇 1 下载并安装Python3 0 2 第一个python程序 3 安装集成开发环境ide 基础知识篇 基本数据
  • go:chan分为阻塞和非阻塞

    一句话总结 ch make chan int 由于没有缓冲发送和接收需要同步 ch make chan int 2 有缓冲不要求发送和接收操作同步 1 无缓冲时 发送阻塞直到数据被接收 接收阻塞直到读到数据 package main imp
  • 【华为OD机试真题】单核CPU任务调度

    单核CPU任务调度 考察的知识的点就一个优先队列 队列排序 题目描述 现在有一个CPU和一些任务需要处理 已提前获知每个任务的任务D 优先级 所需执行时间和到达时间 CPU同时只能运行一个任务 请编写一个任务调度程序 采用 可抢占优先权调度
  • Scala 的安装教程

    Scala 语言可以运行在Window Linux Unix Mac OS X等系统上 Scala是基于java之上 大量使用java的类库和变量 使用 Scala 之前必须先安装 Java gt 1 5版本 Mac OS X 和 Linu
  • git 提交新的工程

    git cmd exe 环境 windows git 提交新的工程 查看版本号 E software Git gt git version git version 2 15 1 windows 2 添加用户配置 E software Git
  • Error: EBUSY: resource busy or locked, lstat ‘D:\DumpStack.log.tmp‘

    问题 vue项目启动成功后报错 Error EBUSY resource busy or locked lstat D DumpStack log tmp 解决 1 npm cache clean force 2 npm install
  • 关于Apache/Tomcat/JBOSS/Nginx/lighttpd/Jetty等一些常见服务器的区别比较和理解

    今天是个很丰富的日子 早上一上班 第一个听到的惊爆消息就是楷子得了肠胃炎 一大早去医院挂水了 随后风胜和笑虎也没来 后来得知他们俩去去华星现代产业园参加培训 内容是关于Apache与Nginx的 于是乎 我非常感兴趣地查了一下培训用的PPT
  • C#按钮事件中有循环,用另一个按钮控制停止,暂停,继续程序执行

    首先在窗体上有 lable1 运行显示 button1 开始 button2 暂停和继续 button3 停止 窗体上还放Timer控件timer1 代码实现如下 using System using System Collections
  • vue+elementUI table表格嵌套表单,功能包含联动下拉框、动态增加行

    一 需求说明 vue elementUI table表格里嵌套表单 支持动态增加一行和删除一行 含checkbox复选框 联动下拉框 不同的活动名称 所对应的活动选项下拉框的值不同 针对不同的选项 值的表现形式也要发生对应的变化 如 日期形
  • An attempt was made to call a method that does not exist. The attempt was made from the following lo

    APPLICATION FAILED TO START Description An attempt was made to call a method that does not exist The attempt was made fr
  • springboot学习(三)——使用HttpMessageConverter进行http序列化和反序列化

    以下内容 如有问题 烦请指出 谢谢 对象的序列化 反序列化大家应该都比较熟悉 序列化就是将object转化为可以传输的二进制 反序列化就是将二进制转化为程序内部的对象 序列化 反序列化主要体现在程序I O这个过程中 包括网络I O和磁盘I
  • 链塔智库

    链塔智库整理最近一周内区块链相关政策 业内动态 人物观点 为大家梳理呈现各个领域的最新发展 目录 一 各地政策要闻 四川 探索建立基于区块链技术的数字资产交易平台 首个区块链领域国家标准在成都举行首场征求意见会 重庆出台优化工业园区规划建设
  • 云计算概念详解

    1 云计算的定义 1 云计算是一种能够通过网络以便利的按需的方式获取云计算资源 网络 服务器 存储 应用和服务 的模式 2 这些资源来自一个共享的 可配置的资源池 并能够快速获取和释放 提供资源的网络称为云 3 云模式能够提高可用性 4 云
  • IDEA下载与安装,保姆级教程

    这里写自定义目录标题 1 搜索idea 2 选择官方网站 3 官网进入下载页面 4 版本选择问题 5 Ultimate和Community对比 6 下载 7 安装 1 搜索idea 2 选择官方网站 以前idea的官网后面有官网俩字 现在没
  • Open NMT-py 玩具模型使用说明

    前排提示 本文仅适合纯萌新玩家 算是官方指南的补档 大佬请直接关闭网页 避免浪费时间 截至到2023 3 15 最新的OpenNMT py环境要求 Python gt 3 7 PyTorch gt 1 9 0 如果是老版本的OpenNMT
  • https网络编程——使用openssl库自建根证书

    参考 如何自建根证书 使用openssl库自建根证书带图详解 地址 https qingmu blog csdn net article details 108217572 spm 1001 2014 3001 5502 目录 根证书的普通
  • spring boot最新教程(三):Spring Boot整合JdbcTemplate以及事务管理

    一 JdbcTemplate的使用 Spring对数据库的操作在jdbc上面做了深层次的封装 使用spring的注入功能 可以把DataSource注册到JdbcTemplate之中 JdbcTemplate 是在JDBC API基础上提供