MyBatis见解4
10.MyBatis的动态SQL
10.5.trim标签
trim标签可以代替where标签、set标签
- mapper
//修改public void updateByUser2(User user);
<update id="updateByUser2" parameterType="User">update user<!-- 增加SET前缀,忽略,后缀 --><trim prefix="SET" suffixOverrides=","><if test="birthday!=null">birthday=#{birthday},</if><if test="sex!=null and username != '' ">sex=#{sex},</if><if test="address!=null and username != '' ">address=#{address},</if></trim>where id=#{id}</update>
insert 用法
void addUser(User user);
<insert id="addUser" parameterType="user">INSERT INTO user<!--trim标签一定要包括if标签,作用:prefix:加上前缀,“(”suffix:加上后缀,“)”prefixOverrides:去除多余的前缀内容suffixOverrides:去除多余的后缀内容,“,”--><trim prefix="(" suffix=")" suffixOverrides=","><if test="username!=null and username!=''">username,</if></trim><trim prefix="VALUES(" suffix=")" suffixOverrides=","><if test="username!=null and username!=''">#{username},</if></trim></insert>
10.6.foreach标签
foreach标签的常见使用场景是集合进行遍历
- mapper
//批量删除public void deleteUserByIds(@Param("ids") List<Integer> ids);//批量添加public void insertUsers(@Param("userList") List<User> userList);
//批量删除public void deleteUserByIds(@Param("ids") List<Integer> ids);//批量添加public void insertUsers(@Param("userList") List<User> userList);
- 测试
@Testpublic void testDeleteUserByIds(){UserDao userDao = sqlSession.getMapper(UserDao.class);List<Integer> ids = new ArrayList();ids.add(50);ids.add(64);ids.add(67);userDao.deleteUserByIds(ids);}@Testpublic void testInsertUsers(){UserDao userDao = sqlSession.getMapper(UserDao.class);long start = System.currentTimeMillis();List<User> userList = new ArrayList<>();for(int i = 0 ;i < 10000; i++) {User user = new User();user.setUsername("刘德华");user.setPassword("111");user.setBirthday(new Date());user.setSex("男");user.setAddress("香港");//userDao.insertUser(user);userList.add(user);}userDao.insertUsers(userList);long end = System.currentTimeMillis();System.out.println("一万条数据总耗时:" + (end-start) + "ms" );sqlSession.commit();}
10.7.sql标签
sql元素标签用来定义可重复使用的SQL代码片段,使用时只需要用include元素标签引用即可
- mapper
//复杂条件查询public List<User> findByUser3(User user);
<!-- 定义SQL片段 --><sql id="query_user_where"><if test="username!=null and username != ''">and username=#{username}</if><if test="birthday!=null">and birthday=#{birthday}</if><if test="sex!=null and sex != ''">and sex=#{sex}</if><if test="address!=null and address != ''">and address=#{address}</if></sql><select id="findByUser3" resultType="User">select * from user<where><include refid="query_user_where"></include></where></select>
- 测试
@Testpublic void testFindAll3(){UserDao userDao = sqlSession.getMapper(UserDao.class);User user = new User();user.setAddress("香港");user.setUsername("刘德华");List<User> userList = userDao.findByUser3(user);for(User u : userList){System.out.println(u);}}
11.MyBatis的缓存
创建工程:

11.1缓存介绍
-
为什么使用缓存?
首次访问时,查询数据库,并将数据存储到内存中;再次访问时直接访问缓存,减少IO、硬盘读写次数、提高效率
-
Mybatis中的一级缓存和二级缓存?
-
一级缓存:
它指的是mybatis中的SqlSession对象的缓存。当我们执行完查询之后,查询的结果会同时存在在SqlSession为我们提供的一块区域中。当我们再次查询同样的数据,mybatis会先去SqlSession中查询是否有,有的话直接拿出来使用。当SqlSession对象消失时,Mybatis的一级缓存也就消失了。
-
二级缓存:
它指的是Mybatis中SqlSessionFactory对象的缓存,由同一个SqlSessioFactory对象创建的SqlSession共享其缓存。

-
11.2.一级缓存
11.2.1.mapper
public interface UserDao {//根据id查询用户信息public User findUserById(Integer id);
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.by.dao.UserDao"><select id="findUserById" resultType="User" parameterType="int">select * from user where id=#{id}</select>
</mapper>
11.2.2.测试一级缓存
@Testpublic void testFindUserById() throws Exception{SqlSession sqlSession1 = sqlSessionFactory.openSession();UserDao userDao = sqlSession1.getMapper(UserDao.class);User user1 = userDao.findUserById(41);//执行查询System.out.println("第一次查询:" + user1);User user2 = userDao.findUserById(41);//不执行查询System.out.println("第二次查询:" + user2);SqlSession sqlSession2 = sqlSessionFactory.openSession();userDao = sqlSession2.getMapper(UserDao.class);User user3 = userDao.findUserById(41);//执行查询System.out.println("第三次查询:" + user1);}
11.2.3.一级缓存的分析
一级缓存是SqlSession范围的缓存,当调用SqlSession的commit(),close()等方法时,就会清空一级缓存。

-
第一次发起查询用户id为 1 的用户信息,先去找缓存中是否有id为 1 的用户信息,如果没有,从数据库查询用户信息。 得到用户信息,将用户信息存储到一级缓存中。
-
如果sqlSession去执行 commit操作(执行插入、更新、删除),清空 SqlSession 中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。
-
第二次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,缓存中有,直接从缓存中获取用户信息。
11.2.4.测试清空一级缓存
xxxxxxxxxx @Test public void testFindUserById() throws Exception{ UserDao userDao = sqlSession.getMapper(UserDao.class); User user1 = userDao.findUserById(41);//执行查询 System.out.println("第一次查询:" + user1); User user2 = userDao.findUserById(41);//不执行查询 System.out.println("第二次查询:" + user2); sqlSession.commit(); User user3 = userDao.findUserById(41);//执行查询 System.out.println("第三次查询:" + user1); }
11.3.二级缓存
11.3.1.pojo
注意:当我们在使用二级缓存时,所缓存的类一定要实现java.io.Serializable接口,这种就可以使用序列化方式来保存对象。
public class User implements Serializable {private Integer id;private String username;private String password;private Date birthday;private String sex;private String address;//set get... ...
}
11.3.2.开启二级缓存
- 在SqlMapConfig.xml 文件开启二级缓存
<settings><!-- 开启二级缓存的支持 --><setting name="cacheEnabled" value="true"/>
</settings>
- 配置相关的Mapper映射文件
<mapper namespace="com.by.dao.UserDao"><!-- 开启二级缓存的支持 --><cache></cache>
11.3.3.测试二级缓存
@Testpublic void testSecondUserById(){SqlSession sqlSession1 = sqlSessionFactory.openSession();UserDao userDao = sqlSession1.getMapper(UserDao.class);User user1 = userDao.findUserById(41);//执行查询System.out.println("第一次查询:" + user1);sqlSession1.commit();//二级缓存在sqlSession.commit()或者sqlSession.close()之后生效SqlSession sqlSession2 = sqlSessionFactory.openSession();UserDao userDao2 = sqlSession2.getMapper(UserDao.class);User user2 = userDao2.findUserById(41);//不执行查询System.out.println("第二次查询:" + user2);}
11.3.4.二级缓存分析
二级缓存是mapper映射级别的缓存,多个SqlSession去操作同一个Mapper映射的sql语句,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的。
二级缓存结构图:

11.3.5.测试清空二级缓存
@Test
public void testSecondUserById(){SqlSession sqlSession1 = sqlSessionFactory.openSession();UserDao userDao = sqlSession1.getMapper(UserDao.class);User user1 = userDao.findUserById(43);//执行查询System.out.println("第一次查询:" + user1);sqlSession1.commit();SqlSession sqlSession3 = sqlSessionFactory.openSession();UserDao userDao3 = sqlSession3.getMapper(UserDao.class);userDao3.deleteUserById(41);sqlSession3.commit();SqlSession sqlSession2 = sqlSessionFactory.openSession();UserDao userDao2 = sqlSession2.getMapper(UserDao.class);User user2 = userDao2.findUserById(43);不执行查询System.out.println("第二次查询:" + user2);sqlSession2.commit();sqlSession2.close();
}
12.MyBatis的注解开发-了解
创建工程:

12.1.注解开发的缺点
MyBatis可以在接口中直接添加MyBatis注解,完成CRUD。
但注解模式属于硬编码到.java文件中,失去了使用配置文件外部修改的优势,可结合需求选用。
12.2.mapper
public interface UserDao {/*** 查询所有用户* @return*/@Select("select * from user")public List<User> findAll();/*** 保存操作* @param user* @return*/@Insert("insert into user(username,sex,birthday,address)values(#{username},“+"#{sex},#{birthday},#{address})")@SelectKey(keyColumn="id",keyProperty="id",resultType=Integer.class,before =false,statement = { "select last_insert_id()" })int saveUser(User user);/*** 更新操作* @param user* @return*/@Update("update user set username=#{username},address=#{address}," +"sex=#{sex},birthday=#{birthday} where id =#{id} ")void updateUser(User user);/*** 删除用户* @param id* @return*/@Delete("delete from user where id = #{id} ")void deleteUser(Integer id);/*** 查询使用聚合函数* @return*/@Select("select count(*) from user ")int findTotal();/*** 根据id查询用户* @return*/@Select("select * from user where id = #{id} ")public User findById(Integer id);/*** 一对多* @return*/@Results(id="resultMap",value= {@Result(id=true,column="id",property="id"),@Result(column="username",property="username"),@Result(column="sex",property="sex"),@Result(column="address",property="address"),@Result(column="birthday",property="birthday"),@Result(column="id",property="accounts",many=@Many(select="com.by.dao.AccountDao.findByuId",fetchType= FetchType.LAZY))})@Select("select * from user")public List<User> findAll2();
}
public interface AccountDao {@Results(id="accountMap",value= {@Result(id=true,column="id",property="id"),@Result(column="uid",property="uid"),@Result(column="money",property="money"),@Result(column="uid",property="user",one=@One(select="com.by.dao.UserDao.findById",fetchType= FetchType.LAZY))})@Select("select * from account")List<Account> findAll();@Select("select * from account where uid = #{uid} ")List<Account> findByuId(Integer id);
}
12.3.pojo
public class User implements Serializable {private Integer id;private String username;private String password;private Date birthday;private String sex;private String address;private List<Account> accounts;//一对多关系映射private List<Account> accounts;// get set toString方法省略
}
public class Account implements Serializable {private Integer id;private Integer uid;private Double money;//一对一关系映射private User user;// get set toString方法省略
}
12.4.测试
@Testpublic void testFindAll() throws Exception{UserDao userDao = sqlSession.getMapper(UserDao.class);List<User> userList = userDao.findAll2();for(User user : userList){System.out.println(user);}}
相关文章:
MyBatis见解4
10.MyBatis的动态SQL 10.5.trim标签 trim标签可以代替where标签、set标签 mapper //修改public void updateByUser2(User user);<update id"updateByUser2" parameterType"User">update user<!-- 增加SET前缀,忽略,后缀…...
Linux操作系统——进程(三) 进程优先级
进程优先级 首先呢,我们知道一个进程呢(或者也可以叫做一个任务),它呢有时候要在CPU的运行队列中排队,要么有时候阻塞的时候呢又要在设备的等待队列中排队,其实我们排队的本质就是:确认优先级。…...
插入排序详解(C语言)
前言 插入排序是一种简单直观的排序算法,在小规模数据排序或部分有序的情况下插入排序的表现十分良好,今天我将带大家学习插入排序的使用。let’s go ! ! ! 插入排序 插入排序的基本思想是将待排序的序列分为已排序和未排序两部分。初始时,…...
Json和Xml
一、前言 学习心得:C# 入门经典第8版书中的第21章《Json和Xml》 二、Xml的介绍 Xml的含义: 可标记性语言,它将数据以一种特别简单文本格式储存。让所有人和几乎所有的计算机都能理解。 XML文件示例: <?xml version"1.…...
STM32 支持IAP的bootloader开发,使用串口通过Ymodem协议传输固件
资料下载: https://download.csdn.net/download/vvoennvv/88658447 一、概述 关于IAP的原理和Ymodem协议,本文不做任何论述,本文只论述bootloader如何使用串口通过Ymodem协议接收升级程序并进行IAP升级,以及bootloader和主程序两个工程的配置…...
【SVN】centos7搭建svn--亲测能通
centos7.6搭建svn 1 知识小课堂1.1 CentOS1.2 SVN 2 搭建过程2.1 前期准备2.2 通过yum命令安装svnserve2.3 创建版本库目录2.4 创建svn版本库2.5 配置修改2.5 防火墙配置2.6 启动或关闭svn服务器2.6.1 进程守护2.6.2 检测svn端口3690是否已经监听:2.6.3 关闭SVN 2.7…...
MY FILE SERVER: 1
下载地址 https://download.vulnhub.com/myfileserver/My_file_server_1.ova 首先我们需要发现ip 我的kali是59.162所以167就是靶机的 然后我们拿nmap扫一下端口 nmap -sV -p- 192.168.59.167 扫完发现有七个端口开放 按照习惯先看80 没看到有啥有用信息,用nikto扫一下 nik…...
Day70力扣打卡
打卡记录 收集足够苹果的最小花园周长(找规律 二分) 链接 class Solution:def minimumPerimeter(self, neededApples: int) -> int:l, r 1, 10 ** 5while l < r:mid (l r) >> 1if 2 * (2 * (mid ** 3) 3 * (mid ** 2) mid) > nee…...
3. 行为模式 - 迭代器模式
亦称: Iterator 意图 迭代器模式是一种行为设计模式, 让你能在不暴露集合底层表现形式 (列表、 栈和树等) 的情况下遍历集合中所有的元素。 问题 集合是编程中最常使用的数据类型之一。 尽管如此, 集合只是一组对象的…...
rsync文件同步
场景:主要是用来发布文件。 一、rsync服务器端架设 1、安装 wget https://download.samba.org/pub/rsync/src/rsync-3.0.6.tar.gz tar -zxvf rsync-3.0.6.tar.gz ./configure --prefix/usr/local/rsync make make install 2、配置 2.1、配置rsyncd.conf 不存在…...
docker 安装mysql 8.0.35
1.拉取镜像 docker pull mysql:8.0.35 2.创建相关挂载目录与文件 mkdir -p /opt/mysql8/conf mkdir -p /opt/mysql8/data mkdir -p /opt/mysql8/logs 或者:mkdir -p /opt/mysql8/{data,conf,logs,mysqld,mysql-files} 文件与文件夹授权:chmod -R 775 /opt/mysql8/* 3.运…...
力扣labuladong一刷day46天并查集
力扣labuladong一刷day46天并查集 文章目录 力扣labuladong一刷day46天并查集一、323. 无向图中连通分量的数目二、130. 被围绕的区域三、990. 等式方程的可满足性 一、323. 无向图中连通分量的数目 题目链接:https://leetcode.cn/problems/number-of-connected-co…...
C++11(上):新特性讲解
C11新特性讲解 前言1.列表初始化1.1{ }初始化1.2std::initializer_list 2.类型推导2.1 auto2.2 typeid2.3 decltype 3.范围for4.STL的变化4.1新容器4.2容器的新方法 5.右值引用和移动语义5.1 左值引用和右值引用5.2 左值引用与右值引用比较5.3 右值引用的使用场景5.4 右值、左值…...
将mapper.xml保存为idea的文件模板
将mapper.xml保存为idea的文件模板 在idea的File and Code Templates中将需要使用模板的内容添加为模板文件。 那么接下来请看图,跟着步骤操作吧。 mapper.xml文件内容 <?xml version"1.0" encoding"UTF-8"?> <!DOCTYPE mapper P…...
LabVIEW在横向辅助驾驶系统开发中的应用
LabVIEW在横向辅助驾驶系统开发中的应用 随着横向辅助驾驶技术的快速发展,越来越多的研究致力于提高该系统的效率和安全性。项目针对先进驾驶辅助系统(ADAS)中的横向辅助驾驶进行深入研究。在这项研究中,LabVIEW作为一个强大的系…...
STM32移植LVGL图形库
1、问题1:中文字符keil编译错误 解决方法:在KEIL中Options for Target Flash -> C/C -> Misc Controls添加“--localeenglish”。 问题2:LVGL中显示中文字符 使用 LVGL 官方的在线字体转换工具: Online font converter -…...
迪文屏开发保姆级教程5—表盘时钟和文本RTC显示
这篇文章要讲啥事呢? 本篇文章主要介绍了在DGBUS平台上使用表盘时钟和文本时钟RTC显示功能的方法。 文哥悄悄话: 官方开发指南PDF:(不方便下载的私聊我发给你) https://download.csdn.net/download/qq_21370051/8864…...
免费IDEA插件推荐-Apipost-Helper
IDEA插件市场中的API调试插件不是收费(Fast Request )就是不好用(apidoc、apidocx等等)今天给大家介绍一款国产的API调试插件:Apipost-Helper,完全免费且好看好用! 这款插件由Apipost团队开发的…...
Django(二)
1.django框架 1.1 安装 pip install django3.21.2 命令行 创建项目 cd 指定目录 django-admin startproject 项目名mysite ├── manage.py [项目的管理工具] └── mysite├── __init__.py├── settings.py 【配置文件,只有一部分…...
Kafka集群架构服务端核心概念
目录 Kafka集群选举 controller选举机制 Leader partition选举 leader partition自平衡 partition故障恢复机制 follower故障 leader故障 HW一致性保障 HW同步过程 Epoch Kafka集群选举 1. 在多个broker中, 需要选举出一个broker, 担任controller. 由controller来管理…...
XML Group端口详解
在XML数据映射过程中,经常需要对数据进行分组聚合操作。例如,当处理包含多个物料明细的XML文件时,可能需要将相同物料号的明细归为一组,或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码,增加了开…...
练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...
Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...
Android第十三次面试总结(四大 组件基础)
Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成,用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机: onCreate() 调用时机:Activity 首次创建时调用。…...
Mysql中select查询语句的执行过程
目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析(Parser) 2.4、执行sql 1. 预处理(Preprocessor) 2. 查询优化器(Optimizer) 3. 执行器…...
Oracle11g安装包
Oracle 11g安装包 适用于windows系统,64位 下载路径 oracle 11g 安装包...
算法打卡第18天
从中序与后序遍历序列构造二叉树 (力扣106题) 给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。 示例 1: 输入:inorder [9,3,15,20,7…...
LangChain 中的文档加载器(Loader)与文本切分器(Splitter)详解《二》
🧠 LangChain 中 TextSplitter 的使用详解:从基础到进阶(附代码) 一、前言 在处理大规模文本数据时,特别是在构建知识库或进行大模型训练与推理时,文本切分(Text Splitting) 是一个…...
AD学习(3)
1 PCB封装元素组成及简单的PCB封装创建 封装的组成部分: (1)PCB焊盘:表层的铜 ,top层的铜 (2)管脚序号:用来关联原理图中的管脚的序号,原理图的序号需要和PCB封装一一…...
CppCon 2015 学习:Reactive Stream Processing in Industrial IoT using DDS and Rx
“Reactive Stream Processing in Industrial IoT using DDS and Rx” 是指在工业物联网(IIoT)场景中,结合 DDS(Data Distribution Service) 和 Rx(Reactive Extensions) 技术,实现 …...
