事务实践 手动创建提交事务 复现幻读 枚举类应用

2024-03-04 22:40

本文主要是介绍事务实践 手动创建提交事务 复现幻读 枚举类应用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

我的项目结构

#我用到的表
DROP TABLE IF EXISTS `goods`;
CREATE TABLE `goods` (
`id` int(11) NOT NULL COMMENT 'id',
`name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL
COMMENT '名称',
`price` decimal(12, 2) NOT NULL COMMENT '价格',
`price_unit` enum('CNY','USD') CHARACTER SET utf8 COLLATE utf8_general_ci
NOT NULL DEFAULT 'CNY' COMMENT '价格单位',
`description` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL
DEFAULT NULL COMMENT '描述',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `IDX_UNIQUE_NAME`(`name`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT =
'商品' ROW_FORMAT = Dynamic#数据库状态设置 对于load_file语句使用不了的去mysql配置文件加配置 具体参考论坛其它教程
show global VARIABLES like '%secure%';
set global require_secure_transport = off;show global variables like 'local_infile';
set global local_infile=1;# 查看mysql自动提交状态
show variables like 'autocommit';# 开启自动提交
set @@autocommit=1;# 关闭自动提交
set @@autocommit=0;

JavaBean 接口没有粘出来 可以照着实现出来

/**
* 货品类
*/
package com.juc.Pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.stereotype.Component;@Data
@Component
@NoArgsConstructor
@AllArgsConstructor
public class Goods {private Integer id; //idprivate String name; //名称private Double price; //价格private price_unit price_unit; //价格单位private String description; //描述}
/**
* 枚举类
*/
package com.juc.Pojo;import com.juc.config.BaseEnum;public enum price_unit implements BaseEnum<price_unit,String> {CNY("1"), USD("2");private String value;price_unit() {}private price_unit(String value) {this.value = value;}public static boolean isChina(String value) {return CNY.getValue().equals(value);}public static boolean isAmerica(String value) {return USD.getValue().equals(value);}@Overridepublic String getValue() {return value;}}

访问层

package com.juc.Controller;import com.juc.Pojo.Goods;
import com.juc.Pojo.price_unit;import com.juc.Service.JUCService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.lang.reflect.Field;import static org.springframework.transaction.annotation.Isolation.REPEATABLE_READ;
import static org.springframework.transaction.annotation.Propagation.REQUIRED;@RestController
@RequestMapping("/JUC")
@Transactional(propagation=REQUIRED ,isolation=REPEATABLE_READ)
public class SQLController {@Autowiredprivate DataSourceTransactionManager dataSourceTransactionManager;@Autowiredprivate TransactionDefinition transactionDefinition;@Autowiredprivate PlatformTransactionManager txManager;@Autowiredprivate JUCService jucService;@Value("${file.setPath}")private String setFilePath;@RequestMapping("/Test")public void SQLTest(){TransactionStatus transactionStatus = null;try{transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);Goods goods01 = new Goods();goods01.setPrice_unit(price_unit.valueOf("CNY"));goods01.setId(2);goods01.setPrice(120.25);goods01.setDescription("键盘连接线");goods01.setName("腹灵");jucService.saveGoods(goods01);Goods goodsBefore4 = jucService.selectById(1);System.out.println("提交前查询---:"+ goodsBefore4);Goods goods02 = new Goods();goods02.setPrice_unit(price_unit.valueOf("CNY"));goods02.setId(1);goods02.setPrice(120.25);goods02.setDescription("键盘,鼠标");jucService.updateGoods(goods02);Goods goodsBefore5 = jucService.selectById(1);System.out.println("提交前查询A1---:"+ goodsBefore5);SQLTest01();Goods goodsBefore1 = jucService.selectById(1);System.out.println("提交前查询A---:"+ goodsBefore1);dataSourceTransactionManager.commit(transactionStatus);//提交Goods goodsAfter = jucService.selectById(1);System.out.println("提交后查询---:"+ goodsAfter);}catch(Exception e){e.printStackTrace();if(transactionStatus!=null){dataSourceTransactionManager.rollback(transactionStatus);//回滚}}}public void SQLTest01(){TransactionStatus transactionStatus2 = dataSourceTransactionManager.getTransaction(transactionDefinition);Goods goods03 = new Goods();goods03.setPrice(599.6);goods03.setDescription("键盘");goods03.setId(1);jucService.updateGoods(goods03);Goods goodsBefore2 = jucService.selectById(1);System.out.println("提交前查询B---:"+ goodsBefore2);dataSourceTransactionManager.commit(transactionStatus2);//提交Goods goodsBefore3 = jucService.selectById(1);System.out.println("提交后查询B---:"+ goodsBefore3);}@RequestMapping("/read")public void readFile(){Goods goods = new Goods();Field[] fields = goods.getClass().getDeclaredFields();int i = fields.length+1;jucService.read(i);jucService.insert(setFilePath);}}

业务层

package com.juc.Service.impl;import com.juc.Dao.GoodsDao;
import com.juc.Pojo.Goods;
import com.juc.Service.JUCService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;import java.io.*;
import java.util.ArrayList;
import java.util.List;@Service
public class JUCServiceImpl implements JUCService {@Autowiredprivate GoodsDao dao;@Value("${file.readPath}")private String readFilePath;@Value("${file.setPath}")private String setFilePath;@Overridepublic Boolean saveGoods(Goods goods) {try{dao.saveGoods(goods);return true;}catch (Exception e){e.printStackTrace();return false;}}@Overridepublic Goods selectById(int id) {try{Goods goods = dao.selectById(id);return goods;}catch (Exception e){e.printStackTrace();return new Goods();}}@Overridepublic Boolean updateGoods(Goods goods) {try {dao.updateGoods(goods);return true;} catch (Exception e) {e.printStackTrace();return false;}}@Overridepublic void read(int ZiDuanNumber) {FileWriter fw = null;try {File fileTxt = new File(setFilePath);FileInputStream file = new FileInputStream(readFilePath);InputStreamReader read = new InputStreamReader(file,"GBK");BufferedReader bufferedReader = new BufferedReader(read);fw = new FileWriter(fileTxt, true);PrintWriter pw = new PrintWriter(fw);String str = "";StringBuilder ZiDuanNumberString = new StringBuilder();for (int i = 0; i < ZiDuanNumber - 1; i++) {ZiDuanNumberString.append(",");}String NumberString = ZiDuanNumberString.toString();while ((str = bufferedReader.readLine()) != null){if (fileTxt == null || fileTxt.length()==0) {while(str.equals(NumberString)){str = bufferedReader.readLine();}List<String> stringList = new ArrayList<>();for (int i = 0; i < str.split(",").length; i++) {if (str.split(",")[i] == null || str.split(",")[i].equals("")) {str.split(",")[i] = "空";stringList.add(str.split(",")[i]);}else{stringList.add(str.split(",")[i]);}}//stringList.remove(stringList.size()-1);pw.println(stringList.toString().substring(1,stringList.toString().length()-1));}else{while(str.equals(NumberString)){str = bufferedReader.readLine();}List<String> stringList = new ArrayList<>();for (int i = 0; i < str.split(",").length; i++) {if (str.split(",")[i] == null || str.split(",")[i].equals("")) {str.split(",")[i] = "空";stringList.add(str.split(",")[i]);}else{stringList.add(str.split(",")[i]);}}//stringList.remove(stringList.size()-1);System.lineSeparator();pw.println(stringList.toString().substring(1,stringList.toString().length()-1));}}pw.flush();fw.flush();pw.close();fw.close();}catch (Exception e){e.printStackTrace();}}@Overridepublic void insert(String path) {dao.load_file(path);}}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" ><mapper namespace= "com.juc.Dao.GoodsDao" ><insert id="load_file">LOAD DATA LOCAL INFILE #{path,jdbcType=VARCHAR} INTO TABLE goods CHARACTER SET utf8FIELDS TERMINATED BY ','LINES TERMINATED BY '\n'</insert><insert id="saveGoods" parameterType="com.juc.Pojo.Goods">insert into goods(id,name,price,price_unit,description)values(#{id,},#{name},#{price},#{price_unit},#{description})</insert><update id="updateGoods" parameterType="com.juc.Pojo.Goods">update goods<set><if test="name != null and name != ''">name = #{name},</if><if test="price != null and price != ''">price = #{price},</if><if test="@com.juc.Pojo.price_unit@isChina(price_unit)">price_unit = #{price_unit},</if><if test="@com.juc.Pojo.price_unit@isAmerica(price_unit)">price_unit = #{price_unit},</if><if test="description != null and description != ''">description = #{description},</if></set>where id = #{id}</update><select id="selectById" parameterType="int" resultType="com.juc.Pojo.Goods">select * from goods where id = #{id}</select>
</mapper>
#项目访问
server:port: 8080
#数据库
spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/rjd?serverTimezone=UTC&allowLoadLocalInfile=trueusername: rootpassword: 123456
#mybatis配置
mybatis:type-aliases-package: com.juc.Pojomapper-locations: classpath:mapper/*.xmltypeHandlersPackage: com.juc.config
#属性名
file:readPath: D:/day01/lianxi01/src/Test.csv #此处换成自己的文件路径setPath: D:/day01/lianxi01/src/Data.txt  #中间暂存文件 方便校验
<?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><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.5.4</version><relativePath/></parent><groupId>com.JUC</groupId><artifactId>JUC</artifactId><version>0.0.1-SNAPSHOT</version><properties><java.version>1.8</java.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-devtools</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.2.0</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.26</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.24</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
//配置枚举类的转换 以便存入数据库
//接口 只有拿值的方法也可以写入拿属性名的方法
package com.juc.config;public interface BaseEnum<E extends Enum<?>, T> {/*** 获取枚举的值* @return 枚举的值*/T getValue();}
//抽象类
package com.juc.config;import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Objects;/*** 参考 http://blog.csdn.net/fighterandknight/article/details/51520595* 进行对本地项目的优化* <p>* 解决 Mybatis 中枚举的问题,* 获取 ResultSet 的值都是获取字符串的,然后比较字符串,以便通用。** @author Zhang Kai* @version 1.0* @since <pre>2018/2/9 17:26</pre>*/
public abstract class BaseEnumTypeHandler<E extends Enum<E> & BaseEnum> extends BaseTypeHandler<E> {/*** 枚举的class*/private Class<E> type;/*** 枚举的每个子类枚*/private E[] enums;/*** 一定要有默认的构造函数,不然抛出 not found method 异常*/public BaseEnumTypeHandler() {}/*** 设置配置文件设置的转换类以及枚举类内容,供其他方法更便捷高效的实现** @param type 配置文件中设置的转换类*/public BaseEnumTypeHandler(Class<E> type) {if (type == null) {throw new IllegalArgumentException("Type argument cannot be null");}this.type = type;this.enums = type.getEnumConstants();if (this.enums == null) {throw new IllegalArgumentException(type.getSimpleName()+ " does not represent an enum type.");}}@Overridepublic void setNonNullParameter(PreparedStatement ps, int i, E parameter,JdbcType jdbcType) throws SQLException {/** BaseTypeHandler已经帮我们做了parameter的null判断* 数据库存储的是枚举的值,所以我们这里使用 value , 如果需要存储 name,可以自定义修改*/if (jdbcType == null) {ps.setString(i, Objects.toString(parameter.getValue()));} else {ps.setObject(i, parameter.getValue(), jdbcType.TYPE_CODE);}}@Overridepublic E getNullableResult(ResultSet rs, String columnName)throws SQLException {String i = rs.getString(columnName);if (rs.wasNull()) {return null;} else {return locateEnumStatus(i);}}@Overridepublic E getNullableResult(ResultSet rs, int columnIndex)throws SQLException {String i = rs.getString(columnIndex);if (rs.wasNull()) {return null;} else {return locateEnumStatus(i);}}@Overridepublic E getNullableResult(CallableStatement cs, int columnIndex)throws SQLException {String i = cs.getString(columnIndex);if (cs.wasNull()) {return null;} else {return locateEnumStatus(i);}}/*** 枚举类型转换,由于构造函数获取了枚举的子类 enums,让遍历更加高效快捷,* <p>* 我将取出来的值 全部转换成字符串 进行比较,** @param value 数据库中存储的自定义value属性* @return value 对应的枚举类*/private E locateEnumStatus(String value) {for (E e : enums) {String simpleName = e.getClass().getSimpleName();//单个判断if("price_unit".equals(simpleName)){if ("CNY".equals(value)){value = "1";} else if ("USD".equals(value)) {value = "2";}}if (Objects.toString(e.getValue()).equals(value)) {return e;}}throw new IllegalArgumentException("未知的枚举类型:" + value + ",请核对"+ type.getSimpleName());}
}//实现类
package com.juc.config;
import com.juc.Pojo.price_unit;
import org.apache.ibatis.type.MappedTypes;/*** 枚举转换的公共模块** @author Zhang Kai* @version 1.0* @since <pre>2018/2/9 18:12</pre>*/
@MappedTypes(value = {price_unit.class})
public class SysEnumTypeHandler<E extends Enum<E> & BaseEnum> extends BaseEnumTypeHandler<E> {/*** 设置配置文件设置的转换类以及枚举类内容,供其他方法更便捷高效的实现** @param type 配置文件中设置的转换类*/public SysEnumTypeHandler(Class<E> type) {super(type);}
}

这篇关于事务实践 手动创建提交事务 复现幻读 枚举类应用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/774591

相关文章

Python标准库之数据压缩和存档的应用详解

《Python标准库之数据压缩和存档的应用详解》在数据处理与存储领域,压缩和存档是提升效率的关键技术,Python标准库提供了一套完整的工具链,下面小编就来和大家简单介绍一下吧... 目录一、核心模块架构与设计哲学二、关键模块深度解析1.tarfile:专业级归档工具2.zipfile:跨平台归档首选3.

使用IDEA部署Docker应用指南分享

《使用IDEA部署Docker应用指南分享》本文介绍了使用IDEA部署Docker应用的四步流程:创建Dockerfile、配置IDEADocker连接、设置运行调试环境、构建运行镜像,并强调需准备本... 目录一、创建 dockerfile 配置文件二、配置 IDEA 的 Docker 连接三、配置 Do

Android Paging 分页加载库使用实践

《AndroidPaging分页加载库使用实践》AndroidPaging库是Jetpack组件的一部分,它提供了一套完整的解决方案来处理大型数据集的分页加载,本文将深入探讨Paging库... 目录前言一、Paging 库概述二、Paging 3 核心组件1. PagingSource2. Pager3.

深入浅出SpringBoot WebSocket构建实时应用全面指南

《深入浅出SpringBootWebSocket构建实时应用全面指南》WebSocket是一种在单个TCP连接上进行全双工通信的协议,这篇文章主要为大家详细介绍了SpringBoot如何集成WebS... 目录前言为什么需要 WebSocketWebSocket 是什么Spring Boot 如何简化 We

Java Stream流之GroupBy的用法及应用场景

《JavaStream流之GroupBy的用法及应用场景》本教程将详细介绍如何在Java中使用Stream流的groupby方法,包括基本用法和一些常见的实际应用场景,感兴趣的朋友一起看看吧... 目录Java Stream流之GroupBy的用法1. 前言2. 基础概念什么是 GroupBy?Stream

python中列表应用和扩展性实用详解

《python中列表应用和扩展性实用详解》文章介绍了Python列表的核心特性:有序数据集合,用[]定义,元素类型可不同,支持迭代、循环、切片,可执行增删改查、排序、推导式及嵌套操作,是常用的数据处理... 目录1、列表定义2、格式3、列表是可迭代对象4、列表的常见操作总结1、列表定义是处理一组有序项目的

C#中的Converter的具体应用

《C#中的Converter的具体应用》C#中的Converter提供了一种灵活的类型转换机制,本文详细介绍了Converter的基本概念、使用场景,具有一定的参考价值,感兴趣的可以了解一下... 目录Converter的基本概念1. Converter委托2. 使用场景布尔型转换示例示例1:简单的字符串到

2025版mysql8.0.41 winx64 手动安装详细教程

《2025版mysql8.0.41winx64手动安装详细教程》本文指导Windows系统下MySQL安装配置,包含解压、设置环境变量、my.ini配置、初始化密码获取、服务安装与手动启动等步骤,... 目录一、下载安装包二、配置环境变量三、安装配置四、启动 mysql 服务,修改密码一、下载安装包安装地

Spring Boot Actuator应用监控与管理的详细步骤

《SpringBootActuator应用监控与管理的详细步骤》SpringBootActuator是SpringBoot的监控工具,提供健康检查、性能指标、日志管理等核心功能,支持自定义和扩展端... 目录一、 Spring Boot Actuator 概述二、 集成 Spring Boot Actuat

在Java中使用OpenCV实践

《在Java中使用OpenCV实践》用户分享了在Java项目中集成OpenCV4.10.0的实践经验,涵盖库简介、Windows安装、依赖配置及灰度图测试,强调其在图像处理领域的多功能性,并计划后续探... 目录前言一 、OpenCV1.简介2.下载与安装3.目录说明二、在Java项目中使用三 、测试1.测