系列导航

springBoot项目打jar包

1、springboot工程新建(单模块)

2、springboot创建多模块工程

3、springboot连接数据库

4、SpringBoot连接数据库引入druid

5、SpringBoot连接数据库引入mybatis

6、SpringBoot-mybatis分页实现pagehelper

7、SpringBoot-mybatis-plus引入

8、SpringBoot 事务

9、SpringBoot-mybatis-druid多源数据多源数据

10、SpringBoot-mybatis-plus-druid多源数据

11、SpringBoot-mybatis-plus-druid多源数据事务

12、SpringBoot-mybatis-plus-ehcache

13、SpringBoot-配置文件里密码加密

14、SpringBoot-easyexcel导出excle

完结

关于springBoot中的事务如何出里这里做了一些实验分享给大家

1数据库中创建表

oracle脚本

CREATE TABLE TEST_BLOCK_T
(
BLOCK_ID VARCHAR2(10 BYTE) PRIMARY KEY, --编码
BLOCK_NAME VARCHAR2(200 BYTE) --资源名称
);

2、pom.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description> <properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.1.17.RELEASE</spring-boot.version>
</properties> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency> <!-- oracle驱动 -->
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>11.2.0.3</version>
</dependency> <!-- 集成druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency> <!-- 集成mybatis-plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.2.0</version>
</dependency>
</dependencies> <dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement> <build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.1.17.RELEASE</version>
<configuration>
<mainClass>com.example.demo.DemoApplication</mainClass>
</configuration>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> </project>

3、 application.properties配置

# 应用名称
spring.application.name=demo
# 应用服务 WEB 访问端口
server.port=8080 # 数据库设置
spring.datasource.driverClassName=oracle.jdbc.OracleDriver
spring.datasource.url=jdbc:oracle:thin:@192.168.0.100:1521:orcl
spring.datasource.username=zy
spring.datasource.password=1 # druid配置
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
# druid参数调优(可选)
# 初始化大小,最小,最大
spring.datasource.initialSize=5
spring.datasource.minIdle=5
spring.datasource.maxActive=20
# 配置获取连接等待超时的时间
spring.datasource.maxWait=60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
spring.datasource.timeBetweenEvictionRunsMillis=60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
spring.datasource.minEvictableIdleTimeMillis=300000
# 测试连接
spring.datasource.testWhileIdle=true
spring.datasource.testOnBorrow=false
spring.datasource.testOnReturn=false
# 打开PSCache,并且指定每个连接上PSCache的大小
spring.datasource.poolPreparedStatements=true
spring.datasource.maxPoolPreparedStatementPerConnectionSize=20
# 配置监控统计拦截的filters
spring.datasource.filters=stat
# asyncInit是1.1.4中新增加的配置,如果有initialSize数量较多时,打开会加快应用启动时间
spring.datasource.asyncInit=true #mybatis-plus控制台打印sql
mybatis-plus.configuration.log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

4、文件目录

5、源码

启动类

注意要开启事务@EnableTransactionManagement

package com.example.demo;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.transaction.annotation.EnableTransactionManagement; @SpringBootApplication
@EnableTransactionManagement
@MapperScan("com.example.demo.mapper")
public class DemoApplication { public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
} }

数据连接配置类

package com.example.demo.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary; import javax.sql.DataSource;
import java.sql.SQLException; @Configuration
public class DruidConfig {
private Logger logger = LoggerFactory.getLogger(DruidConfig.class); @Value("${spring.datasource.url}")
private String dbUrl; @Value("${spring.datasource.username}")
private String username; @Value("${spring.datasource.password}")
private String password; @Value("${spring.datasource.driver-class-name}")
private String driverClassName; @Value("${spring.datasource.initial-size}")
private int initialSize; @Value("${spring.datasource.min-idle}")
private int minIdle; @Value("${spring.datasource.max-active}")
private int maxActive; @Value("${spring.datasource.max-wait}")
private int maxWait; @Value("${spring.datasource.time-between-eviction-runs-millis}")
private int timeBetweenEvictionRunsMillis; @Value("${spring.datasource.min-evictable-idle-time-millis}")
private int minEvictableIdleTimeMillis; // @Value("${spring.datasource.validation-query}")
// private String validationQuery; @Value("${spring.datasource.test-while-idle}")
private boolean testWhileIdle; @Value("${spring.datasource.test-on-borrow}")
private boolean testOnBorrow; @Value("${spring.datasource.test-on-return}")
private boolean testOnReturn; @Value("${spring.datasource.pool-prepared-statements}")
private boolean poolPreparedStatements; @Value("${spring.datasource.max-pool-prepared-statement-per-connection-size}")
private int maxPoolPreparedStatementPerConnectionSize; @Value("${spring.datasource.filters}")
private String filters; @Bean //声明其为Bean实例
@Primary //在同样的DataSource中,首先使用被标注的DataSource
public DataSource dataSource(){
DruidDataSource datasource = new DruidDataSource(); datasource.setUrl(this.dbUrl);
datasource.setUsername(username);
datasource.setPassword(password);
datasource.setDriverClassName(driverClassName); //configuration
datasource.setInitialSize(initialSize);
datasource.setMinIdle(minIdle);
datasource.setMaxActive(maxActive);
datasource.setMaxWait(maxWait);
datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
// datasource.setValidationQuery(validationQuery);
datasource.setTestWhileIdle(testWhileIdle);
datasource.setTestOnBorrow(testOnBorrow);
datasource.setTestOnReturn(testOnReturn);
datasource.setPoolPreparedStatements(poolPreparedStatements);
datasource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
try {
datasource.setFilters(filters);
} catch (SQLException e) {
logger.error("druid configuration initialization filter", e);
}
// datasource.setConnectionProperties(connectionProperties); return datasource;
}
}

controller类

package com.example.demo.controller;

import com.example.demo.service.TransActionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController; @RestController
@RequestMapping("/hello")
public class TransActionController { @Autowired
TransActionService transActionService; @GetMapping("/test1")
@ResponseBody
public String test1() {
transActionService.test1();
return "success";
} @GetMapping("/test2")
@ResponseBody
public String test2() {
transActionService.test2();
return "success";
} @GetMapping("/test3")
@ResponseBody
public String test3() {
transActionService.test3();
return "success";
} @GetMapping("/test3_1")
@ResponseBody
public String test3_1() {
transActionService.test3_1();
return "success";
} @GetMapping("/test4")
@ResponseBody
public String test4() {
transActionService.test4();
return "success";
}
}

实体类

package com.example.demo.domain;

import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName; /**
* <p>
* 。
* </p>
*
* @author yc
* @since 2021-09-18
*/
@TableName(value = "TEST_BLOCK_T")
public class Block {
private static final long serialVersionUID = 1L; @TableId
private String blockId;
/**
* $field.comment。
*/
private String blockName; public String getBlockId() {
return blockId;
} public void setBlockId(String blockId) {
this.blockId = blockId;
} public String getBlockName() {
return blockName;
} public void setBlockName(String blockName) {
this.blockName = blockName;
} @Override
public String toString() {
return "XyDicBlockT{" +
"blockId='" + blockId + '\'' +
", blockName='" + blockName + '\'' +
'}';
}
}

mapper类

package com.example.demo.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.demo.domain.Block; public interface BlockMapper extends BaseMapper<Block> { }

service类

package com.example.demo.service;

import com.example.demo.domain.Block;
import com.example.demo.mapper.BlockMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport; import java.sql.SQLException; @Service
public class TransActionService { //SpringBoot在使用事物Transactional的时候,要在main方法上加上 @EnableTransactionManagement
// 注解开发事物声明,在使用的service层的公共方法加上 @Transactional (spring)注解。 @Autowired
BlockMapper BlockMapper; @Autowired
private DataSourceTransactionManager dataSourceTransactionManager;
@Autowired
private TransactionDefinition transactionDefinition; //那么首先我们来看下 @Transactional 这个注解的使用方法吧,只需要你在需要添加公共方法上面添加该注解即可。
// 但是这么使用的话需要你将异常抛出,由spring进行去控制。
@Transactional
public void test1() {
Block block1 = new Block();
block1.setBlockId("1");
BlockMapper.insert(block1); Block block2 = new Block();
block2.setBlockId("1");
BlockMapper.insert(block2);
} //如果我们在使用事物 @Transactional 的时候,想自己对异常进行处理的话,那么我们可以进行手动回滚事物。
// 在catch中加上 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
// 方法进行手动回滚。不过需要注意的是发生异常需要第一时间进行手动回滚事物,也就是要在异常抛出之前!
@Transactional
public boolean test2() {
try {
Block block1 = new Block();
block1.setBlockId("1");
BlockMapper.insert(block1); Block block2 = new Block();
block2.setBlockId("1");
BlockMapper.insert(block2);
} catch (Exception e) {
System.out.println("发生异常,进行手动回滚!");
// 手动回滚事物
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
e.printStackTrace();
}
return false;
} //如果我们在使用事物 @Transactional 的时候,调用了其他的子方法进行了数据库的操作,
//但是我们想使其事物生效的话,我们可以使用rollbackFor注解或者将该子方法的异常抛出由调用的方法进行处理,
//不过这里需要注意的是,子方法也必须是公共的方法!
@Transactional
public boolean test3() {
try {
deal1();
deal2();
} catch (Exception e) {
System.out.println("发生异常,进行手动回滚!");
// 手动回滚事物
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
e.printStackTrace();
}
return false;
} public void deal1() throws SQLException { Block block = new Block();
block.setBlockId("1");
BlockMapper.insert(block);
System.out.println("执行方法deal1:"); } @Transactional(rollbackFor = SQLException.class)
public void deal2() { Block block = new Block();
block.setBlockId("1");
BlockMapper.insert(block);
System.out.println("执行方法deal2:");
} //这样写经过测试事务也是生效的。好像子方法里不加throws SQLException 和 @Transactional(rollbackFor = SQLException.class) 事务也是生效的
@Transactional
public boolean test3_1() {
deal1_1();
deal2_1();
return false;
} public void deal1_1() {
Block block = new Block();
block.setBlockId("1");
BlockMapper.insert(block);
System.out.println("执行方法deal1_1:");
} public void deal2_1() {
Block block = new Block();
block.setBlockId("1");
BlockMapper.insert(block);
System.out.println("执行方法deal2_1:");
} //----------------------------------- // 如果我们不想使用事物 @Transactional 注解,想自己进行事物控制(编程事物管理),控制某一段的代码事物生效,
// 但是又不想自己去编写那么多的代码,那么可以使用springboot中的DataSourceTransactionManager和TransactionDefinition这两个类来结合使用,
// 能够达到手动控制事物的提交回滚。不过在进行使用的时候,需要注意在回滚的时候,要确保开启了事物但是未提交,
// 如果未开启或已提交的时候进行回滚是会在catch里面发生异常的!
public boolean test4() {
/*
* 手动进行事物控制
*/
TransactionStatus transactionStatus=null;
boolean isCommit = false;
try {
transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition); // 进行新增/修改
Block block1 = new Block();
block1.setBlockId("1");
BlockMapper.insert(block1); Block block2 = new Block();
block2.setBlockId("1");
BlockMapper.insert(block2);
//手动提交
dataSourceTransactionManager.commit(transactionStatus);
isCommit= true;
System.out.println("手动提交事物成功!"); } catch (Exception e) {
//如果未提交就进行回滚
if(!isCommit){
System.out.println("发生异常,进行手动回滚!");
//手动回滚事物
dataSourceTransactionManager.rollback(transactionStatus);
}
e.printStackTrace();
}
return false;
} }

6、启动项目测试项目

1、测试1-1

(1)TEST_BLOCK_T中数据清空

(2)TransActionService中test1()注销掉@Transactional

//@Transactional

public void test1()

postman中执行

代码报主键冲突,但是数据库里有一条数据,说明该方法没有事务

2、测试1-2

(1)TEST_BLOCK_T中数据清空

(2)TransActionService中test1()增加@Transactional

@Transactional

public void test1()

postman中执行

代码报主键冲突,数据库一条数据也没有,说明事务生效

其他几个测试差不多就不重复了。自己看代码实验,代码里注释还比较清晰

8、SpringBoot 事务的更多相关文章

  1. 【原创】003 | 搭上基于SpringBoot事务思想实战专车

    前言 如果这是你第二次看到师长,说明你在觊觎我的美色! 点赞+关注再看,养成习惯 没别的意思,就是需要你的窥屏^_^ 专车介绍 该趟专车是开往基于Spring Boot事务思想实战的专车,在上一篇 搭 ...

  2. 【原创】004 | 搭上SpringBoot事务诡异事件分析专车

    前言 如果这是你第二次看到师长,说明你在觊觎我的美色! 点赞+关注再看,养成习惯 没别的意思,就是需要你的窥屏^_^ 本专车系列文章 目前连载到第四篇,本专题是深入讲解Springboot源码,毕竟是 ...

  3. SpringBoot学习笔记(三):SpringBoot集成Mybatis、SpringBoot事务管理、SpringBoot多数据源

    SpringBoot集成Mybatis 第一步我们需要在pom.xml里面引入mybatis相关的jar包 <dependency> <groupId>org.mybatis. ...

  4. java事务/springboot事务/redis事务

    java事务(数据库事务):jdbc事务--ACID springboot事务:@Transactional--ACID redis事务:命令集合 将redis事务与mysql事务对比:   Mysq ...

  5. springboot 事务创建流程源码分析

    springboot 事务创建流程源码分析 目录 springboot 事务创建流程源码分析 1. 自动加载配置 2. InfrastructureAdvisorAutoProxyCreator类 3 ...

  6. springboot事务的传播行为和隔离级别

    springboot事务的传播行为和隔离级别 在springboot中事务的传播行为和隔离级别都是在TransactionDefinition这个接口中定义的 传播行为定义了7种,分别用0-6来表示 ...

  7. springboot 事务执行全流程分析

    springboot 事务执行全流程分析 目录 springboot 事务执行全流程分析 1. 事务方法执行前的准备工作 2. 业务代码的调用 3. 事务方法执行后处理 4. 业务代码在事务和非事务中 ...

  8. 第六章 springboot + 事务(转载)

    本篇博客转发自:http://www.cnblogs.com/java-zhao/p/5350106.html 在实际开发中,其实很少会用到事务,一般情况下事务用的比较多的是在金钱计算方面. myba ...

  9. 第六章 springboot + 事务

    在实际开发中,其实很少会用到事务,一般情况下事务用的比较多的是在金钱计算方面. mybatis与spring集成后,其事务该怎么做?其实很简单,直接在上一节代码的基础上在相应的方法(通常是servic ...

  10. SpringBoot事务注解@Transactional

    SpringBoot提供了非常方便的事务操作,通过注解就可以实现事务的回滚,非常方便快捷,下面我们就说一下如何进行事务操作. 1. 事务说明 在Spring中,事务有两种实现方式,分别是编程式事务管理 ...

随机推荐

  1. dev-c++ 使用教程

    Dev C++ 支持单个源文件的编译,如果你的程序只有一个源文件(初学者基本都是在单个源文件下编写代码),那么不用创建项目,直接运行就可以:如果有多个源文件,才需要创建项目. 一.新建源文件 1.通过 ...

  2. LeetCode-Java:122. 买卖股票的最佳时机Ⅱ

    题目 给你一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格. 在每一天,你可以决定是否购买和/或出售股票.你在任何时候 最多 只能持有 一股 股票.你也可以先购买, ...

  3. [P7880][Ynoi2006] rldcot

    [Ynoi2006] rldcot 题目描述 给定一棵 \(n\) 个节点的树,树根为 \(1\),每个点有一个编号,每条边有一个边权. 定义 \(dep(x)\) 表示一个点到根简单路径上边权的和, ...

  4. [ABC262C] Min Max Pair

    Problem Statement You are given a sequence $a = (a_1, \dots, a_N)$ of length $N$ consisting of integ ...

  5. Object.defineProperty用法

    1.能干啥? Object.defineProperty()可以给传入的对象动态的添加或修改属性 2.怎么玩? Object.defineProperty(obj,prop,desc)它有三个参数: ...

  6. JDK8提供的常用计量单位

    时间计量单位:Duration @DurationUnit(ChronoUnit.HOURS) private Duration serverTimeout; 空间计量单位:DataSize @Dat ...

  7. Pikachu漏洞靶场 Burte Force(暴力破解)

    Burte Force(暴力破解) 文章目录 Burte Force(暴力破解) 概述 1.基于表单的暴力破解 2.验证码绕过(on server) 3.验证码绕过(on client) 4.toke ...

  8. 1.7每日总结-vue链mysql4

    新建/server/router.js,用于配置对应路由let express = require('express')let router = express.Router()let user = ...

  9. 神经网络优化篇:梯度检验应用的注意事项(Gradient Checking Implementation Notes)

    梯度检验应用的注意事项 分享一些关于如何在神经网络实施梯度检验的实用技巧和注意事项. 首先,不要在训练中使用梯度检验,它只用于调试.意思是,计算所有\(i\)值的\(d\theta_{\text{ap ...

  10. Spring 中循环依赖的处理

    Spring 提供了十分强大的依赖注入功能,使得我们不再需要手动去管理对象的依赖项.然而,在实际的使用场景中,可能会遇到类似下面的依赖异常: Exception encountered during ...