Java框架 —— MyBatis
wptr33 2025-01-10 17:38 30 浏览
MyBatis
简介
?持久层框架,半自动映射,支持自定义SQL、高级映射、存储过程,免除了JDBC代码、参数设置、获取结果集的工
作,可以通过XML或注解方式配置、映射接口,以及实体类在数据库中的记录
Hibernate 和 Mybatis
- Hibernate
- 也是持久层框架,它是全自动映射,SQL编写量小,但是不够灵活,适合用于需求稳定的项目
- Mybatis
- 半自动映射,SQL编写量较大,比较灵活,适合需求变化频繁、快速迭代的项目
运行原理
?Mybatis的核心是一个全局配置文件 + 多个映射文件。MyBatis采用的是构建者模式,使用
SqlSessionFactoryBuilder的build()方法加载配置文件,生成SqlSessionFactory对象,
SqlSessionFactory采用的是工厂模式,使用openSession方法获取SqlSession对象,而SqlSession不像
JDBC一样可以直接操作数据库,它本身是一个接口,提供了操作数据库中数据的方法,通过调用执行器,来操作
mapperStatement对象执行SQL语句,返回结果
核心接口
SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession
代理模式规范
- 接口和映射文件必须同包同名
- 文件的命名空间(namespace)必须是全限定接口名
- 接口中的方法名必须和映射文件中SQL的 id 相同
- 接口中方法的参数只能有一个(除非使用@Param注解),参数类型必须与映射文件中parameterType保持一致
- 返回值类型必须和ResultMap或ResultType相同
配置文件
MyBatis配置文件中,标签的顺序是一定的,不可改变
- configuration(配置)
- properties(属性)
- setting(设置)
- typeAliases(类型别名)
- typeHandlers(类型处理器)
- pluging(插件)
- environment(环境)
- mapping(映射器)
CURD
?在Mybatis中,我们可以通过在配置文件中在<select>等标签内编写SQL语句,也可通过@Select等注解进行
<select id="selectItem" resultType="com.ry.pojo.Item">
select * from item where id = #{id}
</select>
编写
动态SQL
- <if>
- 条件查询,<if test="条件">
- <if test="categoryIdTwo != null and categoryIdTwo != ''"> and category_id_two = #{categoryIdTwo} </if>
- <choose>(when、otherwise)
- 类似于Java中的switch...case...,when作为条件判断,所有条件都不满足,则进入otherwise
- <select id="findActiveBlogLike" resultType="Blog"> SELECT * FROM BLOG WHERE state = ‘ACTIVE’ <choose> <when test="title != null"> AND title like #{title} </when> <when test="author != null and author.name != null"> AND author_name like #{author.name} </when> <otherwise> AND featured = 1 </otherwise> </choose> </select>
- <foreach>
- item:相当于var,index:索引(通常忽略)
- collection:输入参数不同,内容不同
- 参数为数组:输入 Array
- 参数为list:输入为 list
- 参数为map:输入为 key
- open:循环以...开始
- separate:以...进行分割
- close:以...结束
- <select id="selectPostIn" resultType="domain.blog.Post"> SELECT * FROM POST P WHERE ID in <foreach item="item" index="index" collection="list" open="(" separator="," close=")"> #{item} </foreach> </select>
- <trim>
- 可以代替<where>或者是<set>标签
- <trim prefix="WHERE" prefixOverrides="AND |OR "> ... </trim>
多表查询
?通过ResultMap进行封装
- 多对一:association
- javaType:声明该属性的自定义类型(全限定类名或别名)
- property:自定义类型中的属性名
- 一对多:collection
- ofType:集合中泛型的全限定类名或别名
- property:该类型的属性名
<resultMap id="ResultMapItem" type="com.ry.pojo.Item">
<association property="yiji" column="category_id_one"/>
<association property="erji" column="category_id_two"/>
<collection property="pls" column="id" ofType="com.ry.pojo.Comment"/>
</resultMap>
#{} 和 ${}的区别
- #{}就是占位符,相当于JDBC时期的?,会自动进行JDBC和Java类型的装换,将传入的数据当成一个字符串,会对传入的数据添加一对双引号,很大程度上防止了SQL注入问题
- ${}是字符串拼接,不进行类型之间的转换,一般在当动态的是字段,而不是值时使用
延迟加载
?在Mybatis中也叫懒加载,是指在进行表的关联查询时,不立即加载关联的对象,而是在真正用到关联对象的数
据时,才进行查询。这种机制有利于提高查询性能,避免不必要的查询,减少数据库的压力和内存的使用
延迟加载:默认不开启,需要进行手动设置
- 全局配置
- <settings> <!-- 启用延迟加载 --> <setting name="lazyLoadingEnabled" value="true"/> <!-- 只有当使用属性时,才加载对象的所有延迟加载属性 --> <setting name="aggressiveLazyLoading" value="false"/> </settings>
- 局部配置
- 在具体的映射文件中进行配置,例如在<association>或<collection>中指定fetchType
- <resultMap id="blogResultMap" type="Blog"> <association property="author" javaType="Author" select="selectAuthorById" fetchType="lazy"/> </resultMap> <select id="selectAuthorById" resultType="Author"> SELECT * FROM author WHERE id = #{id} </select>
日志处理
使用:导包(log4j-core、log4j-api) -> 编写配置文件
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
<setting name="logImpl" value="LOG4J"/>
</settings>
分页
- RowBounds
先将数据查询到内存中,在内存中进行分页处理(数据量大时,不建议使用)
- PageHelper
分页插件使用: 导包->在mybatis配置文件中进行配置->调用
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<property name="reasonable" value="true"/>
</plugin>
</plugins>
缓存
缓存:减少数据库的压力,提高数据库的性能。 实现原理:从数据库中将对象查询出来,使用后不进行销毁,而是存储在内存中,当再次需要获取该对象时,直接从内存中调用,减少数据库查询次数,提高性能
一级缓存
?Mybatis默认开启一级缓存,一级缓存的作用域是同一个SqlSession,在同一个SqlSession下,多次执行同一个SQL语句,第二次不进行查询,走缓存
缓存失效
- 当SqlSession调用close()方法,SqlSession对象关闭,直接会释放掉一级缓存PerpetualCache对象,一级缓存将不可用
- 如果SqlSession调用了clearCache()方法,会清空PerpetualCache对象中的数据,但是SqlSession仍然可用
- SqlSession执行了任何一个update、delete、insert操作,都会清空PerpetualCache中的数据,但SqlSession对象仍然可用
二级缓存
?二级缓存是SqlSessionFactory级别的,根据mapper的命名空间(namespace)划分,不同SqlSession多次调用同一mapper中的同一SQL语句,走缓存
使用
- 在配置文件中进行配置
<settings>
<setting name="cacheEnabled" value="true"/>
</setttings>
- 将所有实体类序列化(实现接口Serializable)
public class User implements Serializable
- 配置映射文件
<!--
表示此namespace使用二级缓存
cache标签的属性:
eviction="LRU" :清除策略,默认为LRU,移除最长时间不被使用的对象。
flushInterval="60000" :刷新间隔,以毫秒为单位的合理时间量
size="512" :引用数目
readOnly="true" :只读的缓存会给所有调用者返回缓存对象的相同实例
-->
<cache></cache>
<!--按照学号迭代查询-->
<!--
二级缓存
属性useCache="false",sql语句自己可以决定是否使用二级缓存
属性flushCache="false",sql语句自己可以决定是否刷新缓存,多用与新增,修改,删除语句
-->
<select id="findUser" resultType="User">
SELECT * FROM t_user WHERE id in
<foreach collection="list" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</select>
主键生成
解决在插入操作时,主键无法回显的问题
数据库支持主键自增
- 使用JDBC方式返回主键自增的值
- 这种方式只适用于支持主键自增的数据库
- <insert id="insertSysUser" useGeneratedKeys="true" keyProperty="id" > insert into sys_user(user_name,user_password,user_email,user_info,head_img,create_time) values ( #{userName}, #{userPassword}, default, #{userInfo}, #{headImg,jdbcType=BLOB}, #{createTime,jdbcType=TIMESTAMP} ); </insert>
?在以上代码中,我们将useGeneratedKeys属性设置为true, MyBatis会使用 JDBC 的getGeneratedKeys方法
来取出由数据库内部生成的主键;获得主键值后将其赋值给keyProperty属性配置的id属性(实体类中的属性)。当
需要设置多个属性时,使用逗号隔开,这种情况下通常还需要设置 keyColumn 属性按顺序指定数据库的列,这里
列的值会和 keyProperty 配置的属性一一对应。
- 使用selectKey返回主键的值
- 使用<selectKey>标签进行获取主键的值,这种方式不仅适用于不提供主键自增功能的数据库,也适用于提供主键自增功能的数据库
- selectKey 中的keyColumn、keyProperty和上面 useGeneratedKeys 的用法相同
- resultType用于设置返回值
- order属性的设置与数据库有关,MySql 中,order属性的值为 AFTER ,因为当前记录的主键值在 insert 语句执行后才能获取
- <insert id="insertSysUser"> insert into sys_user(user_name,user_password,user_email,user_info,head_img,create_time) values ( #{userName}, #{userPassword}, default, #{userInfo}, #{headImg,jdbcType=BLOB}, #{createTime,jdbcType=TIMESTAMP} ); <selectKey keyColumn="id" resultType="long" keyProperty="id" order="AFTER"> SELECT LAST_INSERT_ID () </selectKey> </insert>
数据库不支持主键自增
- 使用selectKey返回主键的值
- 在不支持主键自增的数据库中,如Orcal,order的值为 BEFORE,这是因为Orcal中需要先从序列获取值,然后将值作为主键插入到数据库中
注:selectKey元素放置的位置不会影响selectKey中的方法在insert前面或者后面执行的顺序,影响执行顺序的是order属性。
```
<insert id="insertSysUser">
<selectKey keyColumn="id" resultType="long" keyProperty="id" order="BEFORE">
SELECT UUID
</selectKey>
insert into sys_user(id,user_name,user_password,user_email,user_info,head_img,create_time)
values (
#{id},
#{userName},
#{userPassword},
default,
#{userInfo},
#{headImg,jdbcType=BLOB},
#{createTime,jdbcType=TIMESTAMP}
);
</insert>
```
XML 文件中的特殊字符
- 使用<![CDATE[" "]]>包裹
- 使用转义字符
- & 和??< 小于??> 大于
相关推荐
- MySQL进阶五之自动读写分离mysql-proxy
-
自动读写分离目前,大量现网用户的业务场景中存在读多写少、业务负载无法预测等情况,在有大量读请求的应用场景下,单个实例可能无法承受读取压力,甚至会对业务产生影响。为了实现读取能力的弹性扩展,分担数据库压...
- 3分钟短文 | Laravel SQL筛选两个日期之间的记录,怎么写?
-
引言今天说一个细分的需求,在模型中,或者使用laravel提供的EloquentORM功能,构造查询语句时,返回位于两个指定的日期之间的条目。应该怎么写?本文通过几个例子,为大家梳理一下。学习时...
- 一文由浅入深带你完全掌握MySQL的锁机制原理与应用
-
本文将跟大家聊聊InnoDB的锁。本文比较长,包括一条SQL是如何加锁的,一些加锁规则、如何分析和解决死锁问题等内容,建议耐心读完,肯定对大家有帮助的。为什么需要加锁呢?...
- 验证Mysql中联合索引的最左匹配原则
-
后端面试中一定是必问mysql的,在以往的面试中好几个面试官都反馈我Mysql基础不行,今天来着重复习一下自己的弱点知识。在Mysql调优中索引优化又是非常重要的方法,不管公司的大小只要后端项目中用到...
- MySQL索引解析(联合索引/最左前缀/覆盖索引/索引下推)
-
目录1.索引基础...
- 你会看 MySQL 的执行计划(EXPLAIN)吗?
-
SQL执行太慢怎么办?我们通常会使用EXPLAIN命令来查看SQL的执行计划,然后根据执行计划找出问题所在并进行优化。用法简介...
- MySQL 从入门到精通(四)之索引结构
-
索引概述索引(index),是帮助MySQL高效获取数据的数据结构(有序),在数据之外,数据库系统还维护者满足特定查询算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构...
- mysql总结——面试中最常问到的知识点
-
mysql作为开源数据库中的榜一大哥,一直是面试官们考察的重中之重。今天,我们来总结一下mysql的知识点,供大家复习参照,看完这些知识点,再加上一些边角细节,基本上能够应付大多mysql相关面试了(...
- mysql总结——面试中最常问到的知识点(2)
-
首先我们回顾一下上篇内容,主要复习了索引,事务,锁,以及SQL优化的工具。本篇文章接着写后面的内容。性能优化索引优化,SQL中索引的相关优化主要有以下几个方面:最好是全匹配。如果是联合索引的话,遵循最...
- MySQL基础全知全解!超详细无废话!轻松上手~
-
本期内容提醒:全篇2300+字,篇幅较长,可搭配饭菜一同“食”用,全篇无废话(除了这句),干货满满,可收藏供后期反复观看。注:MySQL中语法不区分大小写,本篇中...
- 深入剖析 MySQL 中的锁机制原理_mysql 锁详解
-
在互联网软件开发领域,MySQL作为一款广泛应用的关系型数据库管理系统,其锁机制在保障数据一致性和实现并发控制方面扮演着举足轻重的角色。对于互联网软件开发人员而言,深入理解MySQL的锁机制原理...
- Java 与 MySQL 性能优化:MySQL分区表设计与性能优化全解析
-
引言在数据库管理领域,随着数据量的不断增长,如何高效地管理和操作数据成为了一个关键问题。MySQL分区表作为一种有效的数据管理技术,能够将大型表划分为多个更小、更易管理的分区,从而提升数据库的性能和可...
- MySQL基础篇:DQL数据查询操作_mysql 查
-
一、基础查询DQL基础查询语法SELECT字段列表FROM表名列表WHERE条件列表GROUPBY分组字段列表HAVING分组后条件列表ORDERBY排序字段列表LIMIT...
- MySql:索引的基本使用_mysql索引的使用和原理
-
一、索引基础概念1.什么是索引?索引是数据库表的特殊数据结构(通常是B+树),用于...
- 一周热门
-
-
C# 13 和 .NET 9 全知道 :13 使用 ASP.NET Core 构建网站 (1)
-
程序员的开源月刊《HelloGitHub》第 71 期
-
详细介绍一下Redis的Watch机制,可以利用Watch机制来做什么?
-
假如有100W个用户抢一张票,除了负载均衡办法,怎么支持高并发?
-
Java面试必考问题:什么是乐观锁与悲观锁
-
如何将AI助手接入微信(打开ai手机助手)
-
redission YYDS spring boot redission 使用
-
SparkSQL——DataFrame的创建与使用
-
一文带你了解Redis与Memcached? redis与memcached的区别
-
如何利用Redis进行事务处理呢? 如何利用redis进行事务处理呢英文
-
- 最近发表
- 标签列表
-
- git pull (33)
- git fetch (35)
- mysql insert (35)
- mysql distinct (37)
- concat_ws (36)
- java continue (36)
- jenkins官网 (37)
- mysql 子查询 (37)
- python元组 (33)
- mybatis 分页 (35)
- vba split (37)
- redis watch (34)
- python list sort (37)
- nvarchar2 (34)
- mysql not null (36)
- hmset (35)
- python telnet (35)
- python readlines() 方法 (36)
- munmap (35)
- docker network create (35)
- redis 集合 (37)
- python sftp (37)
- setpriority (34)
- c语言 switch (34)
- git commit (34)