Java框架 —— MyBatis
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[" "]]>包裹使用转义字符
& 和 < 小于 > 大于
Java框架 —— MyBatis的更多相关文章
- java框架-Mybatis
一.Mybatis介绍 mybatis是一个持久层的框架,是对JDBC操作数据库的封装,使开发者只需要关注业务本身,不需要花费精力去处理加载驱动.创建数据库连接对象.创建statement语句对象.参 ...
- java框架---->mybatis的使用(一)
这里我们记录一些mybatis的一些常用知识和项目中遇到的问题总结.快乐人生的三个必要元素是,有要做的事.热爱的事及盼望的事. mybatis的一些知识 一.mybatis插入返回主键值 插入的jav ...
- Java框架-MyBatis三剑客之MyBatis Generator(mybatis-generator MBG插件)详解
生成器设计思路: 连接数据库 -> 获取表结构 -> 生成文件 1 下载与安装 官网文档入口 最方便的 maven 插件使用方式 贴至pom 文件 2 新建配置文件 填充配置信息(官网示例 ...
- 详解Java的MyBatis框架中SQL语句映射部分的编写
这篇文章主要介绍了Java的MyBatis框架中SQL语句映射部分的编写,文中分为resultMap和增删查改实现两个部分来讲解,需要的朋友可以参考下 1.resultMap SQL 映射XML 文件 ...
- 【JAVA框架】Hibernate 与Mybatis 区别
Hibernate Mybatis 简介 区别 与联系 欢迎提出见解及转载. 1 简单简介 1.1 Hibernate 框架 Hibernate是一个开放源代码的对象关 ...
- 转 分享我在阿里工作十年接触过Java框架设计模式
转 原文: 分享我在阿里工作十年接触过Java框架设计模式 一.前言 说起来设计模式,大家应该都耳熟能详,设计模式代表了软件设计的最佳实践,是经过不断总结提炼出来的代码设计经验的分类总结,这些模式或者 ...
- 杂项-Java:MyBatis
ylbtech-杂项-Java:MyBatis 1.返回顶部 1. MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundatio ...
- Java自学路线图之Java框架自学
Java自学路线图的框架分为两个阶段,第一阶段的Java框架包含六个内容:MyBatis,Spring,SpringMVC,Maven高级,Git,Dubbo. 在Java自学过程中掌握框架的使用,对 ...
- 程序员必须掌握的Java 框架,小白学会之后15k不是问题
Spring 的核心特性是什么?Spring 优点? Spring 的核心是控制反转(IoC)和面向切面(AOP) Spring 优点: 程序员必须掌握的Java 框架,学会之后50k不是问题 (1) ...
- 一个C#开发编写Java框架的心路历程
前言 这一篇絮絮叨叨,逻辑不太清晰的编写Java框架的的一个过程,主要描述我作为一个java初学者,在编写Java框架时的一些心得感悟. 因为我是C#的开发者,所以,在编写Java框架时,或多或少会带 ...
随机推荐
- [OI] Kruskal 重构树
算法介绍 Kruskal 重构树用于快速判断节点的连通性. 考虑到,假如两个节点是联通的,则他们之间总会有一条边被选入最小生成树内,因此他们在最小生成树内也是联通的. 也就是说,我们可以通过求最小生成 ...
- トヨタ自動車プログラミングコンテスト2024#7(ABC 362)
非常好名次,使我的 \(1\) 旋转 四发罚时应该是这次比赛最唐的东西了,没有就进前一千了 A.Buy a Pen 特判秒了,懒得打三种 ans=,所以就把不能选的那个赋值成无穷大了 #include ...
- Spring技术书的代码资源下载
我是清华社编辑,这些资源获得作者授权,免费提供给读者个人学习使用.禁止任何形式的商用. 二维码用微信扫,按提示填写你的邮箱,转到电脑上打开邮箱下载.清华国企网盘,比较快速.安全.放心下载. 百度网盘链 ...
- LeetCode 1438. Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit (绝对差不超过限制的最长连续子数组)
给你一个整数数组 nums ,和一个表示限制的整数 limit,请你返回最长连续子数组的长度,该子数组中的任意两个元素之间的绝对差必须小于或者等于 limit . 如果不存在满足条件的子数组,则返回 ...
- 41.key发生变化,dom还会复用吗
会复用但是可能会产生没有必要的真实DOM更新 ,会降低渲染效率 :比如使用 index 作为 key 值 :
- 使用nacos上传配置文件报错
1.使用nacos导入配置文件报错:未读取到合法数据,请检查导入的数据文件. 对比在naocs server中导出的文件,发现是少了一级目录.需要创建一个文件夹,名称为组的名称.因为在nacos上传文 ...
- vue 强制刷新
页面传的数值动态改变,接口接受的参数也就动态更改,但接收的数据有时候不会及时改变,通过this.$forceUpdate()页面强制刷新来解决这个问题.
- Python-提高-1
阅读目录 1.GIL(全局解释器锁) 2.深拷贝.浅拷贝 3.私有化 4.import导入模块 5.再议 封装.继承.多态 一.GIL(全局解释器锁) GIL面试题如下 描述Python GIL的概念 ...
- 微信H5分享外部链接,缩略图不显示
可关注微信公众号酒酒酒酒查看原文: 前言:最近做了一款推广茶的APP软件,展厅.产品需要分享功能:从APP内分享到H5网页:微信内打开H5网页,点击微信内右上角三个点,可再次分享: 注意:大多数情况下 ...
- Tony Bai · Go语言第一课 _个人笔记 04|初窥门径:一个Go程序的结构是怎样的?
Tony Bai · Go语言第一课 _个人笔记 04|初窥门径:一个Go程序的结构是怎样的? 1.配置国内的Go模块的镜像 配置国内镜像代理(使用阿里云镜像) go env -w GOPROXY=h ...