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

【MyBatis】mybatis工具类迭代

 目录

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();@Overridepublic 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.lryc.cn/news/199069.html

相关文章:

  • MSQL系列(六) Mysql实战-SQL语句优化
  • kaggle新赛:UBC卵巢癌亚型分类和异常检测大赛【图像分类】
  • 基于nodejs+vue云旅青城系统
  • 《孙哥说Spring5》笔记汇总
  • 在使用了spring-cloud-starter-gateway后,为什么还会发生cors问题
  • CentOS7安装MySQL8.0.28
  • AutoSAR入门:应用背景及简介
  • C++初阶(三)
  • PHP的学习入门建议
  • 骰子涂色(Cube painting, UVa 253)rust解法
  • elasticsearch的docker安装与使用
  • ELK 单机安装
  • 优雅而高效的JavaScript——?? 运算符、?. 运算符和 ?. 运算符
  • Nginx配置负载均衡
  • Ubuntu 20.04 上安装 neo4j
  • 大规模爬虫系统面临的主要挑战及解决思路
  • 统计学习方法 感知机
  • Linux命令(103)之wc
  • 京东店铺公司名爬虫
  • 如何解决不同浏览器的样式兼容性问题?
  • C++ 中迭代器的使用
  • 如何使用BERT生成单词嵌入?
  • 第三章 内存管理 十一、虚拟内存的基本概念
  • web前端面试-- http的各个版本的区别(HTTP/0.9、HTTP/1.0、HTTP/1.1、HTTP/2.0、HTTP/3.0)
  • 统计学习方法 隐马尔可夫模型
  • Cypress 与 Selenium WebDriver
  • Leetcode 第 365 场周赛题解
  • 什么是软件测试? 软件测试都有什么岗位 ?软件测试和调试的区别? 软件测试和开发的区别?软件测试等相关概念入门篇
  • VI/VIM的使用
  • 【虹科干货】Redis Enterprise vs ElastiCache——如何选择缓存解决方案?