MyBatis
2021-07-07 10:16:32 25 举报
AI智能生成
本人对MyBatis的一些理解和案例
作者其他创作
大纲/内容
小试身手
目录浏览
创建数据库
创建Maven项目
导入架包地址
在 properties 下导入下面的包地址
<dependencies>
<!-- 测试环境 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- 德鲁伊数据池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<!-- 数据库 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
<scope>runtime</scope>
</dependency>
<!-- mybatis 核心-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
<!-- lombok:用来写实体类 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
</dependencies>
<!-- 测试环境 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- 德鲁伊数据池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<!-- 数据库 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
<scope>runtime</scope>
</dependency>
<!-- mybatis 核心-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
<!-- lombok:用来写实体类 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
</dependencies>
编写实体类
Dao层
编写MyBatisUtils封装类
编写MyBatis核心配置文件
mybatis.properties
mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<!-- configuration:核心配置文件 -->
<configuration>
<!-- 引入外部文件 -->
<properties resource="mybatis.properties"/>
<environments default="development">
<environment id="development">
<!--transactionManager:事务管理-->
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<!-- 需要管理的 Mapper 地址【不要忘记后缀名】 -->
<mapper resource="userMapper.xml"/>
</mappers>
</configuration>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<!-- configuration:核心配置文件 -->
<configuration>
<!-- 引入外部文件 -->
<properties resource="mybatis.properties"/>
<environments default="development">
<environment id="development">
<!--transactionManager:事务管理-->
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<!-- 需要管理的 Mapper 地址【不要忘记后缀名】 -->
<mapper resource="userMapper.xml"/>
</mappers>
</configuration>
userMapper.xml
<?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">
<!-- namespace:全限类名【要绑定的 Dao/Mapper 接口】 -->
<mapper namespace="com.zhibang.dao.UserDao">
<!-- id:Dao/Mapper 接口的方法 resultType:返回类型的全限类名 -->
<select id="selectUser" resultType="com.zhibang.entity.User">
<!-- SQL语句 -->
select * from ssm.user;
</select>
</mapper>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace:全限类名【要绑定的 Dao/Mapper 接口】 -->
<mapper namespace="com.zhibang.dao.UserDao">
<!-- id:Dao/Mapper 接口的方法 resultType:返回类型的全限类名 -->
<select id="selectUser" resultType="com.zhibang.entity.User">
<!-- SQL语句 -->
select * from ssm.user;
</select>
</mapper>
注:放在resources目录下
编写测试类
测试
注:写在 text/java 下
*CRUD
概述
基于XML配置
select(查询)
Dao层接口
userMapper.xml配置
测试
XMl属性解析
resultType
制定返回类型,查询是有结果的,结果啥类型,你得告诉我
parameterType
参数类型,查询是有参数的,参数啥类型,你得告诉我
id
制定对应的方法,就是你的告诉我你这sql对应的是Dao层的哪个方法
#{id}
sql中的变量,要保证大括号的变量必须在User对象里有,
当然你可以使用map,这或啥也能干,这要你将来传进的map有id这个key就行
当然你可以使用map,这或啥也能干,这要你将来传进的map有id这个key就行
#{}
占位符,其实就是咱们的【PreparedStatement】处理这个变量【推荐使用】
insert(插入)
Dao层接口
userMapper.xml配置
测试
注:记得提交事务
update(修改)
Dao层接口
/**
* 修改用户信息
* @param user
* @return
*/
int updateUser(User user);
userMapper.xml配置
测试
注:记得提交事务
delete(删除)
Dao层接口
userMapper.xml配置
测试
注:记得提交事务
模糊查询
Dao层接口
userMapper.xml配置
测试
解析
${}:直接进行字符串替换
Map的使用
Dao层接口
userMapper.xml配置
测试
解析
map可以代替任何的实体类,所以当我们数据比较复杂时,
可以适当考虑使用map来完成相关工作
可以适当考虑使用map来完成相关工作
别名小插曲
userMapper.xml配置
添加parameterType属性为map,效果一样
别名图片解析
别名总结
就是基本八大数据类型在前面加 _ 下划线,
其他的都是 首字母小写。
其他的都是 首字母小写。
*动态sql
概述
MyBatis提供了对SQL语句动态的组装能力,
大量的判断都可以在 MyBatis的映射XML文件里面配置,
以达到许多我们需要大量代码才能实现的功能,
大大减少了我们编写代码的工作量。
大量的判断都可以在 MyBatis的映射XML文件里面配置,
以达到许多我们需要大量代码才能实现的功能,
大大减少了我们编写代码的工作量。
元素
if 元素
简介
if 元素相当于Java中的if语句,它常常与test属性联合使用。
choose、when、otherwise元素
有些时候我们还需要多种条件的选择,
在Java中我们可以使用switch、case、default语句,
而在映射器的动态语句中可以使用choose、when、otherwise元素。
在Java中我们可以使用switch、case、default语句,
而在映射器的动态语句中可以使用choose、when、otherwise元素。
where元素
trim元素
概述
有时候我们要去掉一些特殊的SQL语法,
比如常见的and、or,此时可以使用trim元素。
比如常见的and、or,此时可以使用trim元素。
prefix
语句的前缀
prefixOverrides
你需要去掉
的那种字符串
的那种字符串
suffix
语句的后缀
suffixOverrides
去掉的后缀字符串
案例
set元素
概述
在update语句中,如果我们只想更新某几个字段的值,
这个时候可以使用set元素配合if元素来完成。
这个时候可以使用set元素配合if元素来完成。
案例
注
set元素遇到 , 逗号会自动把,去掉
foreach元素
概述
是一个循环语句,它的作用是遍历集合,可以支持数组、List、Set接口。
案例
XML配置解析
collection
传递进来的参数名称
item
循环中当前的元素
index
当前元素在集合的位置下标
open 和 close
以什么符号将这些集合元素包装起来
separator
各个元素的间隔符
SQL片段
概述
有时候可能某个 sql 语句我们用的特别多,
为了增加代码的重用性,简化代码,
我们需要将这些重复的代码抽取出来,
然后使用时直接调用。
为了增加代码的重用性,简化代码,
我们需要将这些重复的代码抽取出来,
然后使用时直接调用。
案例
注
要放在 mapper 标签里面
Mybatis缓存
为什么要用缓存?
如果缓存中有数据,就不用从数据库获取,大大提高系统性能
mybatis提供一级缓存和二级缓存
种类
一级缓存
概述
sqlsession级别的缓存
在操作数据库时,需要构造sqlsession对象,
在对象中有一个数据结构(HashMap)用于存储缓存数据
在对象中有一个数据结构(HashMap)用于存储缓存数据
不同的sqlsession之间的缓存区域是互相不影响的。
实现原理
实现原理解析
第一次发起查询sql查询用户id为1的用户,先去找缓存中是否有id为1的用户,
如果没有,再去数据库查询用户信息。得到用户信息,将用户信息存储到一级缓存中。
如果没有,再去数据库查询用户信息。得到用户信息,将用户信息存储到一级缓存中。
如果sqlsession执行了commit操作(插入,更新,删除),会清空sqlsession中的一级缓存,避免脏读。
第二次发起查询id为1的用户,缓存中如果找到了,直接从缓存中获取用户信息
mybatis默认支持并开启一级缓存。
案例
必须配置日志,要不看不见
编写接口方法
接口对应的Mapper文件
测试
打印结果
总结
一级缓存失效
sqlSession不同
当sqlSession对象相同的时候,查询的条件不同,查询的结果不同,
原因是第一次查询时候一级缓存中没有第二次查询所需要的数据
原因是第一次查询时候一级缓存中没有第二次查询所需要的数据
当sqlSession对象相同,两次查询之间进行了插入的操作
当sqlSession对象相同,手动清除了一级缓存中的数据
二级缓存
概述
二级缓存是mapper级别的缓存
多个sqlsession去操作同一个mapper的sql语句,
多个sqlsession可以共用二级缓存,
所得到的数据会存在二级缓存区域。
多个sqlsession可以共用二级缓存,
所得到的数据会存在二级缓存区域。
二级缓存是跨sqlsession的
二级缓存相比一级缓存的范围更大(按namespace来划分),
多个sqlsession可以共享一个二级缓存。
多个sqlsession可以共享一个二级缓存。
图解
实现原理
案例
开启二级缓存
<settings>
<!--开启二级缓存-->
<setting name="cacheEnabled" value="true"/>
</settings> <!-- 需要将映射的javabean类实现序列化 -->
<!--开启二级缓存-->
<setting name="cacheEnabled" value="true"/>
</settings> <!-- 需要将映射的javabean类实现序列化 -->
开启本Mapper的namespace下的二级缓存
<cache eviction="LRU" flushInterval="100000"/>
案例 cache 属性的简介
eviction:回收策略(缓存满了的淘汰机制)
LRU(Least Recently Used),最近最少使用的,最长时间不用的对象
FIFO(First In First Out),先进先出,按对象进入缓存的顺序来移除他们
SOFT,软引用,移除基于垃圾回收器状态和软引用规则的对象
WEAK,弱引用,更积极的移除基于垃圾收集器状态和弱引用规则的对象。
这里采用的是LRU,移除最长时间不用的对形象
这里采用的是LRU,移除最长时间不用的对形象
flushInterval:刷新间隔时间,单位为毫秒
这里配置的是100秒刷新,如果你不配置它,那么当SQL被执行的时候才会去刷新缓存。
size:引用数目
一个正整数,代表缓存最多可以存储多少个对象,不宜设置过大。
设置过大会导致内存溢出。这里配置的是1024个对象
设置过大会导致内存溢出。这里配置的是1024个对象
readOnly:只读
意味着缓存数据只能读取而不能修改,这样设置的好处是我们可以快速读取缓存,
缺点是我们没有办法修改缓存,他的默认值是false,不允许我们修改。
缺点是我们没有办法修改缓存,他的默认值是false,不允许我们修改。
禁用二级缓存
在statement中可以设置useCache=false,禁用当前select语句的二级缓存,默认情况为true
<select id="getStudentById" parameterType="java.lang.Integer" resultType="Student" useCache="false">
在实际开发中,针对每次查询都需要最新的数据sql,要设置为useCache="false" ,禁用二级缓存
刷新缓存(清空缓存)
flushCache标签
<select id="getStudentById" parameterType="java.lang.Integer" resultType="Student" flushCache="true">
一般下执行完commit操作都需要刷新缓存,flushCache="true 表示刷新缓存,可以避免脏读
二级缓存应用场景
对于访问多的查询请求并且用户对查询结果实时性要求不高的情况下,
可采用mybatis二级缓存,降低数据库访问量,提高访问速度,
如电话账单查询,根据需求设置相应的flushInterval:刷新间隔时间,
比如三十分钟,24小时等。
可采用mybatis二级缓存,降低数据库访问量,提高访问速度,
如电话账单查询,根据需求设置相应的flushInterval:刷新间隔时间,
比如三十分钟,24小时等。
二级缓存局限性
mybatis二级缓存对细粒度的数据级别的缓存实现不好,
比如如下需求:对商品信息进行缓存,由于商品信息查询访问量大,
但是要求用户每次都能查询最新的商品信息,
此时如果使用mybatis的二级缓存就无法实现当一个商品变化时只刷新该商品的缓存信息而不刷新其它商品的信息,
因为mybaits的二级缓存区域以mapper为单位划分,
当一个商品信息变化会将所有商品信息的缓存数据全部清空。
解决此类问题需要在业务层根据需求对数据有针对性缓存。
比如如下需求:对商品信息进行缓存,由于商品信息查询访问量大,
但是要求用户每次都能查询最新的商品信息,
此时如果使用mybatis的二级缓存就无法实现当一个商品变化时只刷新该商品的缓存信息而不刷新其它商品的信息,
因为mybaits的二级缓存区域以mapper为单位划分,
当一个商品信息变化会将所有商品信息的缓存数据全部清空。
解决此类问题需要在业务层根据需求对数据有针对性缓存。
第三方缓存
ehcache
Memcached
redis
等等......
简介
基于Java,优秀的持久层框架
持久化
程序产生的数据首先都是在内存。
内存是不可靠的,他丫的一断电数据就没了。
那可靠的存储地方是哪里,硬盘、U盘、光盘等。
我们的程序在运行时说的持久化通常就是指将内存的数据存在硬盘。
硬盘用哪些地方能存?数据库文件、xml文件、
反正你将来能将数据读出来的文件都行。
反正你将来能将数据读出来的文件都行。
总结
将数据从瞬时态转化为持久态,长久保存。
就是把数据存在磁盘而不是内存。
就是把数据存在磁盘而不是内存。
持久层
业务是需要操作数据的
数据是在磁盘上的
具体业务调用具体的数据库操作,耦合度太高,复用性太差
将操作数据库的代码统一抽离出来,
自然就形成了介于业务层和数据库中间的独立的层。
自然就形成了介于业务层和数据库中间的独立的层。
持久层框架
操作数据库的框架
半自动化的ORM(Object Relational Mapping)框架
帮助我们简化对数据库的操作
优缺点
sql语句与代码分离,存放于xml配置文件中
优点:便于维护管理,不用在java代码中找这些语句
缺点: JDBC方式可以用打断点的方式调试,但是Mybatis不能,
需要通过log4j日志输出日志信息帮助调试,然后在配置文件中修改。
需要通过log4j日志输出日志信息帮助调试,然后在配置文件中修改。
用逻辑标签控制动态SQL的拼接
优点:用标签代替编写逻辑代码
缺点:拼接复杂SQL语句时,没有代码灵活,拼写比较复杂。
不要使用变通的手段来应对这种复杂的语句。
不要使用变通的手段来应对这种复杂的语句。
查询的结果集与java对象自动映射
优点:保证名称相同,配置好映射关系即可自动映射或者,
不配置映射关系,通过配置列名=字段名也可完成自动映射。
不配置映射关系,通过配置列名=字段名也可完成自动映射。
缺点:对开发人员所写的SQL依赖很强。
编写原生SQL
优点:接近JDBC,比较灵活。
缺点:对SQL语句依赖程度很高;并且属于半自动,
数据库移植比较麻烦,比如mysql数据库编程移植到
Oracle数据库,部分的sql语句需要调整。
数据库移植比较麻烦,比如mysql数据库编程移植到
Oracle数据库,部分的sql语句需要调整。
使用注解开发
select(查询)
insert(插入)
update(修改)
delete(删除)
总结
不推荐使用SQL过长的语句
短的SQL语句还是可以使用的
注
利用注解开发就不需要mapper.xml映射文件了
核心配置文件解读
什么是核心配置文件?
mybatis-config.xml 系统核心配置文件
核心配置文件主要配置mybatis一些基础组件和加载资源,
核心配置文件中的元素常常能影响mybatis的整个运行过程。
核心配置文件中的元素常常能影响mybatis的整个运行过程。
配置顺序
properties
元素
一个配置属性的元素
settings
设置
mybatis最为复杂的配置也是最重要的,
会改变mybatis运行时候的行为
会改变mybatis运行时候的行为
typeAliases
别名
在TypeAliasRegistry中可以看到mybatis提供了许多的系统别名
typeHandlers
类型处理器
比如在预处理语句中设置一个参数或者从结果集中获取一个参数时候,
都会用到类型处理器,
在 TypeHandlerRegistry 中定义了很多的类型处理器
都会用到类型处理器,
在 TypeHandlerRegistry 中定义了很多的类型处理器
objectFactory
对象工厂
myabtis 在构建一个结果返回的时候,
会使用一个 ObjectFactory 去构建pojo
【pojo:简单的Java对象,实际就是普通JavaBeans,
是为了避免和EJB混淆所创造的简称。】
会使用一个 ObjectFactory 去构建pojo
【pojo:简单的Java对象,实际就是普通JavaBeans,
是为了避免和EJB混淆所创造的简称。】
plugins
插件
environments
environment:环境变量
transactionManager:事务管理器
dataSource:数据源
databaseIdProvider:数据库厂商标识
mappers
映射器
注
配置顺序不能乱
environments元素
概述
environments可以为mybatis配置多环境运行,
将SQL映射到多个不同的数据库上,
必须指定其中一个为默认运行环境(通过default指定),
如果想切换环境修改default的值即可.
将SQL映射到多个不同的数据库上,
必须指定其中一个为默认运行环境(通过default指定),
如果想切换环境修改default的值即可.
图解
子节点
transactionManager - [ 事务管理器 ]
数据源(dataSource)
内建的数据源类型
第三方数据源
druid
hikari
dbcp
c3p0
等等....
mappers元素
概述
mappers的存在就是要对写好的mapper和xml进行统一管理
要不然系统怎么知道你写了哪些mapper
要不然系统怎么知道你写了哪些mapper
引入方式
MapperXML文件
Properties元素
资源目录下新建一个mybatis.properties
将文件导入properties 配置文件
日志
为什么需要日志?
在调试的时候能观察到sql语句的输出,
能查看中间过程,方便寻找错误。
能查看中间过程,方便寻找错误。
标准日志实现
图示
解析
STD:standard out:输出
STDOUT_LOGGING:标准输出日志
STDOUT_LOGGING:标准输出日志
组合log4j完成日志功能(扩展)
导入log4j的包
编写配置文件 log4j.properties
setting设置日志实现
测试
按正常程序执行就行
工具
数据关系的处理
手动维护
概述
自己维护,多写几个语句,使用java组装,
有时候使用mybatis维护关系反而复杂,不如自己维护。
有时候使用mybatis维护关系反而复杂,不如自己维护。
思路
先搜索部门
根据部门搜索员工
手动拼装
在多的一方维护关系
在一的一方维护关系
0 条评论
下一页