【MyBatis】mybatis工具类迭代

news2024/11/15 11:20:13

 目录

MyBatis工具类的迭代

ThreadLocal使用

mybatis工具类终极版:


MyBatis工具类的迭代

public class MyBatisUtil {
     //工具类构造方法私有化
     private void MyBatisUtil() {
     }
     //方法一
     public static SqlSession getSqlSession(){
         try {
             SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
             SqlSessionFactory build = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("UserMapper.xml"));
             SqlSession sqlSession = build.openSession();
             return sqlSession;
         } catch (IOException e) {
            throw new RuntimeException(e);
         }
     }

弊端:每次调用都会创建sqlSessionFactoryBuilder、SqlSessionFactory等大量对象,创建的对象太多,造成资源浪费

   //方法二
     private static SqlSession sqlSession = null;
     static {
         try {
             sqlSession = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("UserMapper.xml")).openSession();
         } catch (IOException e) {
             throw new RuntimeException(e);
         }
     }
 //    弊端:调用一次mybatisutil就创建好了sqlsession,此后的每次调用会公用一个sqlsession对象;   

弊端:由于sqlsession对象的创建是在static静态代码块中的,所以第一次调用mybatisutil就创建好了sqlsession,此后的每次调用会公用一个sqlsession对象;这样也是不行的事物这一块会有问题,然后你每次创建会话的目的就是区分和记录不同的会话,他要一样岂不是不符合初期的设计了;

 //方法三
     private static SqlSessionFactory sqlSessionFactory = null;
     static {
         try {
             sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("UserMapper.xml"));
         } catch (IOException e) {
             throw new RuntimeException(e);
         }
     }
     public SqlSession getSqlSession() {
         return sqlSessionFactory.openSession();
         //每调用一次方法,创建一个sqlsession对象,不共用
     }

之前的这些工具类,刚刚开始学习mybatis时足以使用,但是随着学习的增进,代码量的增大,业务的变多,使用以上工具类就会出现很多的事务问题,例如下面这串代码:

 public class AccountServiceImpl implements AccountService {
         private AccountDao accountDao = new AccountDaoImpl();
  @Override
  public void transfer(String fromActno, String toActno, double money) throws MoneyNotEnoughException, AppException {
  // 查询转出账户的余额
         Account fromAct = accountDao.selectByActno(fromActno);
         if (fromAct.getBalance() < money) {
             throw new MoneyNotEnoughException("对不起,您的余额不⾜。");
         }
         try {
  // 程序如果执⾏到这⾥说明余额充⾜
  // 修改账户余额
              Account toAct = accountDao.selectByActno(toActno);
             fromAct.setBalance(fromAct.getBalance() - money);
             toAct.setBalance(toAct.getBalance() + money);
  // 更新数据库(添加事务)
             SqlSession sqlSession = SqlSessionUtil.openSession();
             accountDao.update(fromAct);
  // 模拟异常
             String s = null;
             s.toString();
             accountDao.update(toAct);
             sqlSession.commit();
             sqlSession.close();
         } catch (Exception e) {
                 throw new AppException("转账失败,未知原因!");
          }
  }
 }

很明显,这串代码会报错。虽然我们在代码中开启了事务管理,但是代码中使用了大量的sqlsession对象,所以导致sqlsession的重复出现导致事务管理出错;错误原因在于空指针异常,第一个update事务提交了,然而第二个update的事务没有提交,最开始开启的sqlsession事务对象并不能控制整个转账过程,原因就是每个update都有属于自己的sqlsession,也就是说他们各自使用的sqlsession都不一样,所以我们如何解决?

那就是让它们使用同一个sqlsession,如何做到呢?使用threadlocal

ThreadLocal使用

修改工具类;

mybatis工具类终极版:

 public class SqlSessionUtil {
  private static SqlSessionFactory sqlSessionFactory;
  /**
  * 类加载时初始化sqlSessionFactory对象
  */
  static {
     try {
             SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
             sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"));
         } catch (Exception e) {
             e.printStackTrace();
         }
      }
  private static ThreadLocal<SqlSession> local = new ThreadLocal<>();
  /**
  * 每调⽤⼀次openSession()可获取⼀个新的会话,该会话⽀持⾃动提交。
  *
  * @return 新的会话对象
  */
  public static SqlSession openSession() {
         SqlSession sqlSession = local.get();
         if (sqlSession == null) {
             sqlSession = sqlSessionFactory.openSession();
             local.set(sqlSession);
         }
         return sqlSession;
      }
  /**
  * 关闭SqlSession对象
  * @param sqlSession
  */
  public static void close(SqlSession sqlSession){
         if (sqlSession != null) {
             sqlSession.close();
          }
         local.remove();
     }
 }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1111065.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Xilinx DDR4 MIG 的调试

平台&#xff1a;Vivado2021.1 芯片&#xff1a;xcku115-flva1517-2-i (active) 语言&#xff1a;VerilogHDL 参考文件&#xff1a;pg150.下载地址 pg150-ultrascale-memory-ip.pdf • 查看器 • AMD 自适应计算文档门户 (xilinx.com) DDR4介绍 DDR4&#xff0c;即第四代…

隐藏Zotero批注图标(便利贴)

使用Zotero看文献做批注的时候&#xff0c;会出现图上类似于便利贴的图标&#xff0c;容易遮挡字体。 在"编辑"中选择"首选项"&#xff0c;"翻译"中去掉勾选"自动翻译批注"。 就好了

python二次开发Solidworks:扫描

在新零件文档中创建一个圆形草图和两条线段草图&#xff0c;并将它们插入到模型中。接着&#xff0c;选中圆形草图作为扫描轮廓&#xff0c;并选中两条线段草图并将它们分组为一个对象。最后&#xff0c;使用特征管理器的InsertProtrusionSwept4方法创建扫描特征。 import win…

gson如何序列化子类

需求 目前有一个需求&#xff0c;不同对象有一些公共属性&#xff0c;分别也有一些不同的属性。对方传过来的json字符串中&#xff0c;把这些对象组成了一个数组返回过来的。这样该如何反序列化呢&#xff1f; 举例 定义Person类、Student类、Worker类&#xff1b; Data To…

【MATLAB第80期】基于MATLAB的结构核岭回归SKRR多输入单输出回归预测及分类预测模型

【MATLAB第80期】基于MATLAB的结构核岭回归SKRR多输入单输出回归预测及分类预测模型 SKRR这是Gustau Camps-Valls等人在“用深度结构核回归检索物理参数”中提出的结构核岭回归&#xff08;SKRR&#xff09;方法。 参考文献&#xff1a; Camps-Valls,Retrieval of Physical Pa…

期中考核复现(web)

1z_upload 进到这个页面里面还是挺懵的&#xff0c;什么也不知道 点添加书籍之后发现变成了sql 师兄给了源码&#xff0c;看了之后找到了他的限制函数 但是肯定要先登录才可以 登录还是用bp爆破 最后得到账号密码是admin/admin12345 进来之后就可以看到那个文件上传的地方 上…

RabbitMQ入门到实战教程,MQ消息中间件,消息队列实战

消息队列是目前最常见的微服务中间件之一&#xff0c;而RabbitMq在全球范围内的使用率也是名列前茅。它以稳定性强、并发高、低时延的特点深受广大企业开发者的喜爱。然而市面上一致缺乏一个专门的RabbitMQ课程&#xff0c;所以这套课程应运而生。 微服务一旦拆分&#xff0c;必…

【Bug】【内存相关】偶然发现一个内存溢出Bug复盘

一、问题 跑自动化用例的时候&#xff0c;uat-sg环境&#xff0c;发现SGW经常会返回 502 Bad Gateway响应 二、原因 经过SRE和BE Dev共同排查&#xff0c;502 是从ALB-- > 后端服务 后端服务无法响应导致&#xff0c;ALB会直接给客户端返回502。 服务端&#xff1a;由于c…

C# Winform编程(6)高级控件

C# Winform编程&#xff08;6&#xff09;高级控件 RadioButton&#xff08;单选框&#xff09;PictureBox&#xff08;图像框&#xff09;TabControl&#xff08;选项卡&#xff09;ProgressBar(进度条)TrackBar(滑动条)ImageList&#xff08;图像列表控件&#xff09;ToolBar…

29栈与队列——优先队列

目录 LeetCode之路——347. 前 K 个高频元素 分析 优先队列 简单示例 运行结果 源码简析 LeetCode之路——347. 前 K 个高频元素 给你一个整数数组 nums 和一个整数 k &#xff0c;请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。 示例 1: 输入: num…

一剑破万法:noexcept与C++异常导致的coredump

作为C/C程序员&#xff0c;最不想见到的就是coredump。导致coredump的原因有很多&#xff0c;今天我来谈一下其中一种十分常见的原因&#xff0c;那就是由于C异常没有被catch导致的coredump。 从一篇知乎文章讲起 先看一位知友的文章&#xff1a; C11 std::thread异常coredu…

[ROS2系列] ORBBEC(奥比中光)AstraPro相机在ROS2进行rtabmap 3D建图

目录 背景&#xff1a; 一、驱动AstraPro摄像头 二、安装rtabmap error1&#xff1a;缺包 三、尝试 四、参数讲解 五、运行 error2: Did not receive data since 5 seconds! 六、效果​编辑 error4: 背景&#xff1a; 1、设备&#xff1a;pc&#xff1b;jeston agx …

使用kyuubi查询出现集群单节点cpu飙升问题

问题现象&#xff1a; 单节点cpu飙升 初步定位原因是: 业务人在查询操作时&#xff0c;表被锁表&#xff0c;查询不出结果&#xff0c;就反复执行&#xff0c;导致堆积&#xff0c;并kyuubi又是高并发操作。 &#xff08;当一些操作在共享锁阻塞期间积压时&#xff0c;这些操…

Leetcode 349 两个数组的交集 (*哈希数组,*HashSet,*HashMap)

Leetcode 349 两个数组的交集 &#xff08;*哈希数组&#xff0c;*HashSet&#xff0c;*HashMap&#xff09; 解法1 [用数组构建hashmap] &#x1f60b;HashSet and .HashMap1.HashSet2.HashMap 解法2 [使用HashSet]⭐️ 解法1 [用数组构建hashmap] &#x1f60b; 自己的笨比方…

【ES实战】ES主副分片数据不一致分析

ES主副分片数据不一致分析 文章目录 ES主副分片数据不一致分析问题描述问题重现问题分析修复方案 问题描述 在请求索引中的某一条数据时&#xff0c;时而查询有结果&#xff0c;时而无结果。两种情况交替出现。 问题重现 通过对问题数据的点查&#xff0c;确实重现了该现象 …

CSDN 操作

CSDN的目录界面&#xff0c;会随着浏览器界面的大小而变化&#xff0c;分布在左边位置或者右边位置。 目录界面在右&#xff1a; 目录界面在左&#xff1a; 按键Ctrl&#xff0c; 滑动鼠标滚轮&#xff0c;就可以放大或者缩小界面。

Intelijj使用Gitee团队开发

初始化项目到Gitee服务器 成功标识&#xff1a; 添加团队成员 点击管理——仓库成员设置——开发者 2.添加仓库成员 &#xff08;最多不超过5人&#xff09; 3.通过链接或者二维码邀请新成员&#xff0c;或者可以自己手动添加新成员并提交 多人项目仓库创建完成 通…

有什么小程序可以下载视频号的视频?

​最近有一些朋友问我&#xff0c;【视频号下载助手】和【视频下载bot】小程序&#xff0c;有什么作用&#xff1f; 首先视频号下载助手是协助用户进行下载的&#xff0c;但由于下载要符合平台规定&#xff0c;我们就将视频下载助手与视频下载bot小程序想结合的模式&#xff0…

盛水最多的容器

题目&#xff1a; 给定一个长度为 n 的整数数组 height 。有 n 条垂线&#xff0c;第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。 找出其中的两条线&#xff0c;使得它们与 x 轴共同构成的容器可以容纳最多的水。 返回容器可以储存的最大水量。 说明&#xff1a;你…

uniapp高德地图ios 使用uni.chooseLocation选取位置显示没有搜索到相关数据

uniapp云打包后&#xff0c;高德地图ios选取位置显示“ 对不起&#xff0c;没有搜索到相关数据” 详细问题描述 废话不多说&#xff0c;直接上图 解决方案 1.打开高德地图开发平台 2.重新创建key 3.获取云打包时的ios报名作为安全码 4.使用生成的高德key更改manifest.json里…