当前位置: 首页 > news >正文

ThreadLocal简单使用案例

        业务场景:保存业务数据表的时候,同时记录下日志。


import java.sql.Connection;
import java.sql.DriverManager;public class DBUtil {// 数据库配置private static final String driver = "com.mysql.jdbc.Driver";private static final String url = "jdbc:mysql://localhost:3306/test";private static final String username = "root";private static final String password = "root";private static Connection conn = null;public static Connection getDbConnection() {try {Class.forName(driver);conn = DriverManager.getConnection(url, username, password);} catch (Exception e) {e.printStackTrace();}return conn;}// 关闭数据库连接public static void closeDbConnection() {try {if (conn != null) {conn.close();}} catch (Exception e) {e.printStackTrace();}}
}

import com.example.springboottest.util.DBUtil;import java.sql.Connection;
import java.sql.PreparedStatement;
import java.text.SimpleDateFormat;
import java.util.Date;public class ThreadLocalTest3 {private static final String UPDATE_SQL = "update t_test set num = ? where id = ?";private static final String INSERT_SQL = "insert into log (id, desc) values (?, ?)";public static void main(String[] args) {ThreadLocalTest3 service = new ThreadLocalTest3();service.updateBusiness(1, 3000);}public void updateBusiness(int id, int num) {try {// 获取连接Connection conn = DBUtil.getDbConnection();conn.setAutoCommit(false); // 关闭自动提交事务(开启事务)// 执行操作updateBizData(conn, UPDATE_SQL, id, num);// 插入日志insertLog(conn, INSERT_SQL, "描述"); // 提交事务conn.commit();} catch (Exception e) {e.printStackTrace();} finally {// 关闭连接DBUtil.closeDbConnection();}}private void updateBizData(Connection conn, String updateSQL, int id, int num) throws Exception {PreparedStatement pstmt = conn.prepareStatement(updateSQL);pstmt.setInt(1, id);pstmt.setLong(2, num);int rows = pstmt.executeUpdate();if (rows != 0) {System.out.println("业务数据更新成功!");}}private void insertLog(Connection conn, String insertSQL, String desc) throws Exception {PreparedStatement pstmt = conn.prepareStatement(insertSQL);pstmt.setString(1, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS").format(new Date()));pstmt.setString(2, desc);int rows = pstmt.executeUpdate();if (rows != 0) {System.out.println("日志插入成功!");}}
}

        上面的代码直接运行肯定是没有问题的,但是如果在多线程下面去跑,就会报数据库连接关闭的错误。原因很简单,多线程下执行,可能一个线程刚获取到连接另一个线程就已经把连接关闭了,所以就会导致这样的问题,要解决这个问题,ThreaLocal就是一个很好的选择,只需要改调整下DBUtil里面获取连接的代码即可。如下代码所示:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;public class DBUtil {// 数据库配置private static final String driver = "com.mysql.jdbc.Driver";private static final String url = "jdbc:mysql://localhost:3306/test";private static final String username = "root";private static final String password = "root";private static ThreadLocal<Connection> connContainer = new ThreadLocal<Connection>(){//初始化connContainer里面的值,如果不重写则为null;@Overrideprotected Connection initialValue() {try {Class.forName(driver);return  DriverManager.getConnection(url, username, password);} catch (SQLException e) {throw new RuntimeException(e);}}};// 获取连接public static Connection getDbConnection() {Connection conn = connContainer.get();try {if (conn == null) {Class.forName(driver);conn = DriverManager.getConnection(url, username, password);}} catch (Exception e) {e.printStackTrace();} finally {connContainer.set(conn);}return conn;}// 关闭连接public static void closeDbConnection() {Connection conn = connContainer.get();try {if (conn != null) {conn.close();}} catch (Exception e) {e.printStackTrace();} finally {connContainer.remove();}}
}

相关文章:

ThreadLocal简单使用案例

业务场景&#xff1a;保存业务数据表的时候&#xff0c;同时记录下日志。 import java.sql.Connection; import java.sql.DriverManager;public class DBUtil {// 数据库配置private static final String driver "com.mysql.jdbc.Driver";private static final Stri…...

创建型设计模式之建造者模式

文章目录 概述定义建造者模式原理结构图小结 概述 建造者模式又被称为生成器模式&#xff0c;是一种创建型设计模式。 和之前的单例&#xff0c;工厂一样&#xff0c;同属于创建型设计模式。 定义 建造者模式是将一个复杂对象的构建与表示分离&#xff0c;使得同样的构建过程…...

mainwindow 无菜单栏 可拖动,边界可扩大,动画浮现上边框

mainwindow 无菜单栏 可拖动,边界可扩大,动画浮现上边框 #ifndef ANIMATIONWIN_H #define ANIMATIONWIN_H #include namespace Ui {class animationWin; } class animationWin : public QWidget {Q_OBJECT public: explicit animationWin(QWidget *parent = nullptr); …...

机器学习云环境测试

等待创建完成后&#xff0c;点击 PyTorch 打开&#xff0c;创建一个全新的 notebook 在 Cell 中输入如下代码&#xff0c;并点击 Run 完成后点击 New Cell &#xff0c;在 New Cell 中输入如下代码 输入完成后点击 Run &#xff0c;运行 New Cell 。&#xff08;每个 Cell 代…...

扩散模型自动管道AutoPipeline

推荐&#xff1a;write_own_pipeline.ipynb - Colab (google.com) 为您的任务选择一个 AutoPipeline 首先选择一个检查点。例如&#xff0c;如果您对使用 runwayml/stable-diffusion-v1-5 检查点的文本到图像感兴趣&#xff0c;请使用 AutoPipelineForText2Image&#xff1a; f…...

Map六种遍历方式

下面是三组&#xff08;6种&#xff09;&#xff0c;Map 遍历方式的核心代码。 遍历方式有使用到增强for和迭代器。最下面有张图片&#xff0c;对做题有参考意义。 参考代码&#xff1a; Map map new HashMap();map.put("小猫","cat");map.put("小…...

集合-1 数组ArrayListLinkedList

一.数组 1.什么是数组&#xff1f; 数组是一种用连续的内存空间存储相同类型数据的线性数据结构。 2.为什么数组下标是从0开始&#xff1f; &#xff08;1&#xff09;数组根据下标查找元素是基于寻址公式&#xff1a;元素地址数组首地址索引i*数组存储数据类型的大小 &am…...

42-1 应急响应之账户排查

一、用户信息排查 在服务器被入侵后,攻击者可能会建立相关账户(有时是隐藏或克隆账户),方便进行远程控制。攻击者会采用的方法主要有如下几种: 直接建立一个新的账户:攻击者直接创建一个新的账户,有时为了混淆视听,账户名称与系统常用名称相似。 激活一个系统中的默认…...

Python3 笔记:sort() 和 sorted() 的区别

1、sort() 可以对列表中的元素进行排序&#xff0c;会改变原列表&#xff0c;之前的顺序不复存在。 list.sort&#xff08;key&#xff0c; reverse None&#xff09; key&#xff1a;默认值是None&#xff0c;可指定项目进行排序&#xff0c;此参数可省略。 reverse&#…...

vue 引入 emoji 表情包

vue 引入 emoji 表情包 一、安装二、组件内使用 一、安装 npm install --save emoji-mart-vue二、组件内使用 import { Picker } from "emoji-mart-vue"; //引入组件<picker :include"[people,Smileys]" :showSearch"false" :showPreview&q…...

mysql 数据库 增量备份

mysql 数据库 增量备份 https://dev.mysql.com/doc/mysql-enterprise-backup/8.0/en/mysqlbackup.incremental.html 和版本 有关系啊 xtrabackup mysql增量备份与恢复使用详解 https://www.jb51.net/database/297844fzd.htm 存储 引擎 怎么看&#xff1f; 适用于MyISAM存储引…...

SpringBoot之@Builder 注解

&#xff08;1&#xff09;Builder 生成的构造器不是完美的&#xff0c;如果没有提供必须的参数&#xff0c;构造器可能会创建出不完整或者不合法的对象&#xff0c;导致代码报错。 Builder 注解产生的 Builder 类的构造方法默认并不能限定必传参数。 &#xff08;2&#xff…...

云计算的能源消耗如何影响环境?

嗨&#xff0c;亲爱的读者朋友们&#xff0c;今天我们要聊一聊云计算的能源消耗对环境的影响。随着科技的飞速发展&#xff0c;云计算已经成为了企业和个人处理数据的首选方式。但是&#xff0c;你可曾想过&#xff0c;这些“云”究竟消耗了多少能源&#xff0c;对我们的环境又…...

openwrt设置开机自启 tailscale为例

首先下载 tailscale 到 /root 目录下&#xff0c;并按照以下命令运行一次 /root/tailscale/tailscaled --state/root/tailscale/tailscaled.state & /root/tailscale/tailscale up &弹出登录地址并授权即可 创建一个启动脚本位置在/etc/init.d下 vim /etc/init.d/ta…...

副业树洞聊天项目/树洞倾诉/陪陪系统源码/树洞源码下载搭建

随着社会的发展和人们生活水平的提高&#xff0c;越来越多的人在面临心理压力、情感困扰或生活困境时&#xff0c;需要一个可以宣泄、倾诉和寻求支持的平台。而传统的人际交往方式往往会遇到难以排解的问题&#xff0c;比如担心被他人知晓自己的隐私等&#xff0c;这就导致了人…...

UWB论文:Introduction to Impulse Radio UWB Seamless Access Systems(2):脉冲;超宽带;测距;定位

3) 测距/接收器 像全球定位系统&#xff08;GPS&#xff09;这样的系统依赖于单向测距One Way Ranging&#xff08;OWR&#xff09;&#xff0c;其中多个卫星&#xff08;代表固定节点&#xff0c;称为锚点anchors&#xff09;定期传输同步的无线电数据包集合&#xff0c;这允许…...

Spring MVC/Web

1.Spring MVC 的介绍 Spring Web MVC是基于Servlet API构建的原始Web框架&#xff0c;也是Spring框架的一部分。它提供了灵活可扩展的MVC架构&#xff0c;方便开发者构建高性能的Web应用程序&#xff0c;并与 Spring 生态系统无缝集成。 2.MVC 设计模式 MVC&#xff08;Model…...

C++中获取int最大与最小值(补)

上文中&#xff0c;我们学习了C中获取int最大与最小值的两种方法&#xff1a;C库和移位运算&#xff0c;这篇文章将解决在移位运算中遇到的各种报错&#xff0c;并提出一种新的生成int最值的方法 上文链接&#xff1a;http://t.csdnimg.cn/cn7Ad 移位运算取最值常见报错 Dev…...

一个开源的工具类轮子是怎么造出来的

心路历程 为什么要做 在22年9月的某一天&#xff0c;在公司开需求评审时&#xff0c;接到了一个给PDF、图片添加水印的需求。做为一个刚工作的CURD程序员&#xff0c;在遇到这些问题时&#xff0c;第一反应是去github上找找有没有类似的开源框架。但是&#xff0c;出乎我意料…...

零基础学Java第二十二天之迭代器 Iterator

迭代器 Iterator 的理解和相关集合 使用 1、理解 迭代器&#xff08;Iterator&#xff09;是设计模式中的一种&#xff0c;它允许程序员遍历容器&#xff08;例如列表、集合等&#xff09;中的元素&#xff0c;而无需了解容器底层的实现细节。在编程中&#xff0c;迭代器提供了…...

eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)

说明&#xff1a; 想象一下&#xff0c;你正在用eNSP搭建一个虚拟的网络世界&#xff0c;里面有虚拟的路由器、交换机、电脑&#xff08;PC&#xff09;等等。这些设备都在你的电脑里面“运行”&#xff0c;它们之间可以互相通信&#xff0c;就像一个封闭的小王国。 但是&#…...

【位运算】消失的两个数字(hard)

消失的两个数字&#xff08;hard&#xff09; 题⽬描述&#xff1a;解法&#xff08;位运算&#xff09;&#xff1a;Java 算法代码&#xff1a;更简便代码 题⽬链接&#xff1a;⾯试题 17.19. 消失的两个数字 题⽬描述&#xff1a; 给定⼀个数组&#xff0c;包含从 1 到 N 所有…...

重启Eureka集群中的节点,对已经注册的服务有什么影响

先看答案&#xff0c;如果正确地操作&#xff0c;重启Eureka集群中的节点&#xff0c;对已经注册的服务影响非常小&#xff0c;甚至可以做到无感知。 但如果操作不当&#xff0c;可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...

视觉slam十四讲实践部分记录——ch2、ch3

ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...

Kubernetes 网络模型深度解析:Pod IP 与 Service 的负载均衡机制,Service到底是什么?

Pod IP 的本质与特性 Pod IP 的定位 纯端点地址&#xff1a;Pod IP 是分配给 Pod 网络命名空间的真实 IP 地址&#xff08;如 10.244.1.2&#xff09;无特殊名称&#xff1a;在 Kubernetes 中&#xff0c;它通常被称为 “Pod IP” 或 “容器 IP”生命周期&#xff1a;与 Pod …...

stm32wle5 lpuart DMA数据不接收

配置波特率9600时&#xff0c;需要使用外部低速晶振...

SpringAI实战:ChatModel智能对话全解

一、引言&#xff1a;Spring AI 与 Chat Model 的核心价值 &#x1f680; 在 Java 生态中集成大模型能力&#xff0c;Spring AI 提供了高效的解决方案 &#x1f916;。其中 Chat Model 作为核心交互组件&#xff0c;通过标准化接口简化了与大语言模型&#xff08;LLM&#xff0…...

ubuntu系统文件误删(/lib/x86_64-linux-gnu/libc.so.6)修复方案 [成功解决]

报错信息&#xff1a;libc.so.6: cannot open shared object file: No such file or directory&#xff1a; #ls, ln, sudo...命令都不能用 error while loading shared libraries: libc.so.6: cannot open shared object file: No such file or directory重启后报错信息&…...

车载诊断架构 --- ZEVonUDS(J1979-3)简介第一篇

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 做到欲望极简,了解自己的真实欲望,不受外在潮流的影响,不盲从,不跟风。把自己的精力全部用在自己。一是去掉多余,凡事找规律,基础是诚信;二是…...

__VUE_PROD_HYDRATION_MISMATCH_DETAILS__ is not explicitly defined.

这个警告表明您在使用Vue的esm-bundler构建版本时&#xff0c;未明确定义编译时特性标志。以下是详细解释和解决方案&#xff1a; ‌问题原因‌&#xff1a; 该标志是Vue 3.4引入的编译时特性标志&#xff0c;用于控制生产环境下SSR水合不匹配错误的详细报告1使用esm-bundler…...