前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java学习笔记-全栈-web开发-15-MyBatis

Java学习笔记-全栈-web开发-15-MyBatis

作者头像
devi
发布2021-08-18 15:43:36
1.4K0
发布2021-08-18 15:43:36
举报
文章被收录于专栏:搬砖记录

1. 简介

MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis,实质上Mybatis对ibatis进行一些改进

MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。

对jdbc的封装框架有哪些:Hibernate,dbutils,jdbcTemplate[spring],mybatis

原理: Mybatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatemnt、CallableStatement)配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。

1.1 原生JDBC 缺点

在这里插入图片描述
在这里插入图片描述

以上是普通jdbc数据库操作,缺点

  • 数据库连接频繁开启和关闭,会严重影响数据库的性能。
  • 代码中存在硬编码,分别是数据库部分的硬编码和SQL执行部分的硬编码。

1.2 MyBatis框架核心

  • 1、mybatis配置文件,包括Mybatis全局配置文件和Mybatis映射文件,其中全局配置文件配置了数据源、事务等信息;映射文件配置了SQL执行相关的信息。
  • 2、mybatis通过读取配置文件信息(全局配置文件和映射文件),构造出SqlSessionFactory,即会话工厂。
  • 3、通过SqlSessionFactory,可以创建SqlSession即会话。Mybatis是通过SqlSession来操作数据库的
  • 4、SqlSession本身不能直接操作数据库,它是通过底层的Executor执行器接口来操作数据库的。Executor接口有两个实现类,一个是普通执行器,一个是缓存执行器(默认)。
  • 5、Executor执行器要处理的SQL信息是封装到一个底层对象MappedStatement中。该对象包括:SQL语句、输入参数映射信息、输出结果集映射信息。其中输入参数和输出结果的映射类型包括HashMap集合对象、POJO对象类型。

1.3 开发步骤

  • 1、创建model类
  • 2、创建全局配置文件SqlMapConfig.xml;
  • 3、编写映射文件;
  • 4、加载映射文件,在SqlMapConfig.xml中进行加载;
  • 5、编写测试程序,即编写Java代码,连接并操作数据库。 过程:
    • a)读取配置文件;
    • b)通过SqlSessionFactoryBuilder创建SqlSessionFactory会话工厂。
    • c)通过SqlSessionFactory创建SqlSession。
    • d)调用SqlSession的操作数据库方法。
    • e)关闭SqlSession。

1.3.1 创建model类

在这里插入图片描述
在这里插入图片描述

1.3.2 创建全局配置文件

SqlMapConfig.xml

代码语言:javascript
复制
<?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>
<!-- 配置mybatis的环境信息 -->
<environments default="development">
	<environment id="development">
		<!-- 配置JDBC事务控制,由mybatis进行管理 -->
		<transactionManager type="JDBC"></transactionManager>
		<!-- 配置数据源,采用dbcp连接池 -->
		<dataSource type="POOLED">
			<property name="driver" value="com.mysql.jdbc.Driver"/>
			<property name="url" value="jdbc:mysql://localhost:3306/study?serverTimezone=UTC"/>
			<property name="username" value="root"/>
			<property name="password" value="123456"/>
		</dataSource>
	</environment>
</environments>
</configuration>

1.3.3 编写映射文件

在classpath下,创建sqlmap文件夹,在其下创建User.xml映射文件

代码语言:javascript
复制
<?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:命名空间,它的作用就是对SQL进行分类化管理,可以理解为SQL隔离
	注意:使用mapper代理开发时,namespace有特殊且重要的作用
 -->
<mapper namespace="test">
	<!-- 
		[id]:statement的id,要求在命名空间内唯一  
		[parameterType]:入参的java类型
		[resultType]:查询出的单条结果集对应的java类型
		[#{}]: 表示一个占位符?
		[#{id}]:表示该占位符待接收参数的名称为id。注意:如果参数为简单类型时,#{}里面的参数名称可以是任意定义
	 -->
	<select id="findUserById" parameterType="int" resultType="com.shunxu.model.User">
		SELECT * FROM USER WHERE id = #{id}
	</select>
</mapper>

1.3.4 加载映射文件

在SqlMapConfig.xml中加载User.xml

代码语言:javascript
复制
<mappers>
	<mapper resource="sqlmap/User.xml"/>
</mappers>

1.3.5 编写测试程序

在这里插入图片描述
在这里插入图片描述

以上测试代码是mybatis单独使用的方法,但实际上会同spring一起使用,对象的操作都会交给bean,比上述代码简单很多。

2. 常用查询(语法重点)

2.1 模糊查询

代码语言:javascript
复制
<!-- 
		[${}]:表示拼接SQL字符串
	 	[${value}]:表示要拼接的是简单类型参数。
		 注意:
		1、如果参数为简单类型时,${}里面的参数名称必须为value 
		2、${}会引起SQL注入,一般情况下不推荐使用。但是有些场景必须使用${},比如order by ${colname}
	-->
	<select id="findUserByName" parameterType="String" resultType="com.shunxu.model.User">
		SELECT * FROM USER WHERE username like '%${value}%'
	</select>
在这里插入图片描述
在这里插入图片描述

2.2 增

代码语言:javascript
复制
<insert id="insertUser" parameterType="com.shunxu.model.User">
	INSERT INTO USER (username,sex,birthday,address)
	VALUES(#{username},#{sex},#{birthday},#{address})
</insert>

如果主键的值是mysql自增,则此处不需要给ID赋值

在这里插入图片描述
在这里插入图片描述

2.3 删

代码语言:javascript
复制
<delete id="deleteUser" parameterType="int">
	DELETE FROM USER WHERE id=#{id}
</delete>
在这里插入图片描述
在这里插入图片描述

2.4 改

代码语言:javascript
复制
<update id="updateUser" parameterType="com.shunxu.model.User">
	UPDATE USER SET username=#{username},sex=#{sex} WHERE id=#{id}
</update>
在这里插入图片描述
在这里插入图片描述

2.5 获得自增主键

通过sql函数获得:SELECT LAST_INSERT_ID()

代码语言:javascript
复制
<insert id="insertUser" parameterType="com.gyf.domain.User">
		<!-- 
			[selectKey标签]:通过select查询来生成主键
			[keyProperty]:指定存放生成主键的属性
			[resultType]:生成主键所对应的Java类型
			[order]:指定该查询主键SQL语句的执行顺序,相对于insert语句
			[last_insert_id]:MySQL的函数,要配合insert语句一起使用 -->
		<selectKey keyProperty="id" resultType="int" order="AFTER">
			SELECT LAST_INSERT_ID()
		</selectKey>
		<!-- 如果主键的值是通过MySQL自增机制生成的,那么我们此处不需要再显示的给ID赋值 -->
		INSERT INTO USER (username,sex,birthday,address) 
		VALUES(#{username},#{sex},#{birthday},#{address})
</insert>

2.6 获得自增UUID

代码语言:javascript
复制
<insert id="insertUser" parameterType="com.gyf.domain.User">
		<selectKey keyProperty="id" resultType="String" order="BEFORE">
			SELECT UUID()
		</selectKey>
		INSERT INTO USER (username,sex,birthday,address) 
		VALUES(#{username},#{sex},#{birthday},#{address})
</insert>

2.7 语法小结

parameterType和resultType

  • parameterType指定输入参数的java类型,可以填写别名或Java类的全限定名。 resultType指定输出结果的java类型,可以填写别名或Java类的全限定名。

#{}和${}

  • #{}:相当于预处理中的占位符?。 #{}里面的参数表示接收java输入参数的名称。 #{}可以接受HashMap、POJO类型的参数。 当接受简单类型的参数时,#{}里面可以是value,也可以是其他。 #{}可以防止SQL注入。
  • {}:相当于拼接SQL串,对传入的值不做任何解释的原样输出。 {}会引起SQL注入,所以要谨慎使用。 {}可以接受HashMap、POJO类型的参数。 当接受简单类型的参数时,{}里面只能是value。

selectOne和selectList

  • selectOne:只能查询0或1条记录,大于1条记录的话,会报错:
  • selectList:可以查询0或N条记录

3. Dao层 —— mapper(核心)

Mapper代理的开发方式,程序员只需要编写mapper接口(相当于dao接口)即可。

Mybatis会自动的为mapper接口生成动态代理实现类。

不过要实现mapper代理的开发方式,需要遵循一些开发规范

3.1 开发规范

  • 1.mapper接口的全限定名要和mapper映射文件的namespace的值相同。
  • 2.mapper接口的方法名称要和mapper映射文件中的statement的id相同;
  • 3.mapper接口的方法参数只能有一个,且类型要和mapper映射文件中statement的parameterType的值保持一致。
  • 4.mapper接口的返回值类型要和mapper映射文件中statement的resultType值或resultMap中的type值保持一致;

3.2 测试

3.2.1 编写mapper接口以及对应的配置文件

在这里插入图片描述
在这里插入图片描述

3.2.2 添加配置映射

在这里插入图片描述
在这里插入图片描述

3.2.3 测试

在这里插入图片描述
在这里插入图片描述

3.3 全局配置setting(了解)

在这里插入图片描述
在这里插入图片描述

可配置属性:

在这里插入图片描述
在这里插入图片描述

3.4 别名 typeAliases

别名是使用是为了在映射文件中,更方便的去指定参数和结果集的类型,不再用写很长的一段全限定名。

3.4.1 mybatis内置别名

在这里插入图片描述
在这里插入图片描述

3.4.2 自定义别名

在这里插入图片描述
在这里插入图片描述

3.5 mapper注册

代码语言:javascript
复制
<mapper resource=’’/>
使用相对于类路径的资源
如:<mapper resource="sqlmap/User.xml" />

-----------------------------------------
<mapper class=’’/>
使用mapper接口的全限定名
如:<mapper class="cn.shunxu.mybatis.mapper.UserMapper"/>
注意:此种方法要求mapper接口和mapper映射文件要名称相同,且放到同一个目录下;
-----------------------------------------
<package name=’’/>(推荐)
注册指定包下的所有映射文件
如:<package name="cn.shunxu.mybatis.mapper"/>

注意:此种方法要求mapper接口和mapper映射文件要名称相同,且放到同一个目录下;

3.6 注解开发

可以将xml文件删除,所有的sql语句都在mapper接口方法中写

在这里插入图片描述
在这里插入图片描述

4. 映射文件(重点)

4.1 输入映射ParameterType

指定输入参数的java类型,可以使用别名或者类的全限定名。它可以接收简单类型,POJO对象、HashMap。

4.1.1 简单类型

基本类型

在这里插入图片描述
在这里插入图片描述

传递POJO对象

在这里插入图片描述
在这里插入图片描述

4.1.2 传递POJO包装对象

开发中通过pojo传递查询条件 ,查询条件是综合的查询条件,不仅包括用户查询条件还包括其它的查询条件(比如将用户购买商品信息也作为查询条件),这时可以使用包装对象传递输入参数

例如: 综合查询用户信息,需要传入查询条件复杂,比如(用户信息、订单信息、商品信息)。

  1. 定义POJO包装类
在这里插入图片描述
在这里插入图片描述
  1. 修改UserMapper.java
在这里插入图片描述
在这里插入图片描述
  1. 修改UserMapper.xml
在这里插入图片描述
在这里插入图片描述
  1. 测试
在这里插入图片描述
在这里插入图片描述

4.1.3 传递Map对象

  1. mapper
在这里插入图片描述
在这里插入图片描述
  1. xml
在这里插入图片描述
在这里插入图片描述
  1. 测试
在这里插入图片描述
在这里插入图片描述

4.2 输出映射 resultType/resultMap

输出映射与输出映射的用法基本一致,因此这里针对resultType和resultMap各举一个典型例子

4.2.1 resultType

resultType

  • 使用resultType进行结果映射时,查询的列名和映射的pojo属性名完全一致,该列才能映射成功。
  • 如果查询的列名和映射的pojo属性名全部不一致,则不会创建pojo对象;
  • 如果查询的列名和映射的pojo属性名有一个一致,就会创建pojo对象

输出POJO列表

  1. mapper
在这里插入图片描述
在这里插入图片描述
  1. xml
在这里插入图片描述
在这里插入图片描述

4.2.2 resultMap

如果查询出来的列名和属性名不一致(即数据库字段与model字段不一致),通过定义一个resultMap将列名和pojo属性名之间作一个映射关系。

  • 1、定义resultMap
  • 2、使用resultMap作为statement的输出映射类型
  1. mapper
在这里插入图片描述
在这里插入图片描述
  1. xml
在这里插入图片描述
在这里插入图片描述
  1. 测试
在这里插入图片描述
在这里插入图片描述

4.3 映射用法总结

  • 输出单个pojo对象和pojo列表时,mapper映射文件中的resultType的类型是一样的,mapper接口的方法返回值不同。
  • 同样的mapper映射文件,返回单个对象和对象列表时,mapper接口在生成动态代理的时候,会根据返回值的类型,决定调用selectOne方法还是selectList方法。

5. 高级查询语法

5.1 if和where

if标签:作为判断入参来使用的,如果符合条件,则把if标签体内的SQL拼接上。(test中的参数是property而不是column,且所有特殊字符都需要转义,逻辑运算符也得转义,因此建议使用英文逻辑运算符

注意:

  • 用if进行判断是否为空时,不仅要判断null,也要判断空字符串‘’;
  • 查询时,多个if并联的时候,比如当第一个if不满足时,拼接结果就会多一个"and"导致出错,使用where标签,会去掉条件中的第一个and符号。
  • 同理,update用多个if实现多个set时,也会有逗号可能多余的情况。因此用set标签替代手动的set,能够去掉最后一个多余的逗号
在这里插入图片描述
在这里插入图片描述

5.2 SQL片段

将某一段查询语句单独抽出来,然后通过引用的方式实现“到处使用”

在这里插入图片描述
在这里插入图片描述

5.3 for-each

例子:查询指定id用户 java

在这里插入图片描述
在这里插入图片描述

xml

在这里插入图片描述
在这里插入图片描述

还可以加上index属性,当为list指索引,当为map指key。 测试

在这里插入图片描述
在这里插入图片描述

或者直接传入id集合

在这里插入图片描述
在这里插入图片描述

此外,foreach常用于批量保存

在这里插入图片描述
在这里插入图片描述

for-each本质上是拼接sql字符串,因此,凡是可遍历生成的字符串,都可以用foreach,比如连接url设置allowMultiQueries=true,可以通过for-each发起多个sql语句

5.4 choose(分支查询)

需求:如果带了id,就用id查询,如果带了username,就用username查;二选其一。choose相当于带了bread的switch-case(因此是按顺序进入when)

代码语言:javascript
复制
<select id="getByIdOrUsername" resultType="xx.User">
	select * from user
	<where>
		<choose>
			<when test="id!=null">
				id=#{id}
			</when>
			<when test="userName!=null">
				username like #{userName}
			</when>
			<otherwise>
			<!--其他情况查所有-->
				1=1 
			</otherwise>
		</choose>		
	</where>
</select>

6. 关联查询

显然,mybatis是以一个model为基本单位,当查询涉及到多个model时,就需要关联查询

数据库信息如下:

在这里插入图片描述
在这里插入图片描述

user和orders:

  • User 与orders:一个用户可以创建多个订单,一对多
  • Orders 与 user:多个订单只由一个用户创建,多对一

orders和orderdetail:

  • Orders 与 orderdetail:一个订单包括多个订单明细,因为一个订单可以购买多个商品,每个商品的购买信息在orderdetail记录,一对多
  • orderdetail 与orders:多个订单明细包括在一个订单中, 多对一

orderdetail和items:

  • Orderdetail 与 items:多个订单明细只对应一个商品信息,多对一
  • Items 与 orderdetail:一个商品可以包括在多个订单明细 ,一对多

6.1 一对一

需求: 根据商品ID查找订单,包括用户名和地址

SQL语句:

代码语言:javascript
复制
#查找某个定单id的信息,包括用户名字和地址
SELECT o.*,u.username,u.address FROM orders o,user u
WHERE o.user_id = u.id AND o.id = 3

6.1.1 resultType实现

复杂查询时,单表对应的po类已不能满足输出结果集的映射。所以要根据需求建立一个扩展类来作为resultType的类型。

  1. 写一个订单扩展类
在这里插入图片描述
在这里插入图片描述
  1. 声明订单接口
在这里插入图片描述
在这里插入图片描述
  1. 声明订单配置文件
在这里插入图片描述
在这里插入图片描述
  1. 加载映射文件
在这里插入图片描述
在这里插入图片描述
  1. 测试
在这里插入图片描述
在这里插入图片描述

6.1.2 resultMap实现

掌握association用法

  1. OrdersMapper.java
在这里插入图片描述
在这里插入图片描述
  1. OrdersMapper.xml
在这里插入图片描述
在这里插入图片描述
  1. 测试
在这里插入图片描述
在这里插入图片描述

小结

  • resultType:使用resultType实现较为简单,如果pojo中没有包括查询出来的列名,需要增加列名对应的属性,即可完成映射。如果没有查询结果的特殊要求建议使用resultType。
  • resultMap:需要单独定义resultMap,实现有点麻烦,如果对查询结果有特殊的要求,使用resultMap可以完成将关联查询映射pojo的对象属性中。
  • resultMap可以实现延迟加载,resultType无法实现延迟加载。

6.2 一对多

掌握collection用法

需求:根据订单ID查找订单信息、用户信息和订单明细

SQL

代码语言:javascript
复制
Select
			orders.id,
			orders.user_id,
			orders.number,
			orders.createtime,
			orders.note,
			user.username,
			user.address,
			orderdetail.id detail_id,
			orderdetail.items_id,
			orderdetail.items_num
		from 
			orders,user,orderdetail
		where 
			orders.user_id = user.id 
			and orders.id = orderdetail.orders_id
  			and orders.id = #{?};
代码语言:javascript
复制
SELECT 
	o.*,
	u.username,
	u.address,
	od.id detail_id,
  od.items_id,
  od.items_num
FROM 
	orders o,
	user u,
	orderdetail od
WHERE 
	o.user_id = u.id 
  AND o.id = od.orders_id
	AND o.id = 3
  1. 在Orders中指定订单明细
在这里插入图片描述
在这里插入图片描述
  1. Mapper
在这里插入图片描述
在这里插入图片描述
  1. OrderMapper.xml
在这里插入图片描述
在这里插入图片描述
  1. 测试
在这里插入图片描述
在这里插入图片描述

小结

  • mybatis使用resultMap的collection对关联查询的多条记录映射到一个list集合属性中。

使用resultType实现:

  • 需要对结果集进行二次处理。将订单明细映射到orders中的orderdetails中,需要自己处理,使用双重循环遍历,去掉重复记录,将订单明细放在orderdetails中。

6.3 多对多

需求:查询用户信息及用户购买的商品信息,要求将关联信息映射到主pojo的pojo属性中

在这里插入图片描述
在这里插入图片描述

SQL

代码语言:javascript
复制
SELECT 
  u.id,
	u.username,
	u.address,
	o.id order_id,
  o.number,
	o.createtime,
  o.note,
	od.id detail_id,
  od.items_id,
  od.items_num,
  it.name,
  it.price,
  it.detail
FROM 
	user u,
	orders o,
	orderdetail od,
  items it
WHERE 
	o.user_id = u.id 
  AND o.id = od.orders_id
  AND od.items_id = it.id;

思路:

  • 将用户信息映射到user中。
  • 在user类中添加订单列表属性List<Orders> orderslist,将用户创建的订单映射到orderslist
  • 在Orders中添加订单明细列表属性List<Orderdetail> detailList,将订单的明细映射到detailList
  • 在Orderdetail中添加Items属性,将订单明细所对应的商品映射到Items
  1. UserMapper
在这里插入图片描述
在这里插入图片描述
  1. User/Orders/Orderdetail.java
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
  1. UserMapper.xml
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
  1. 测试
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

6.4 总结

  • 一对一:模型里面写模型(association)
  • 一对多:模型里面写集合(collection)
  • resultType:将查询结果按照sql列名pojo属性名一致性映射到pojo中。
  • resultMap:使用association和collection完成一对一和一对多高级映射(对结果有特殊的映射要求)。
  • association:将关联查询信息映射到一个pojo对象中。
  • collection:将关联查询信息映射到一个list集合中。

7. 懒加载

懒加载又叫延时加载,也叫按需加载。也就是说先加载主信息,需要的时候,再去加载信息。 在mybatis中,resultMap标签 的association标签和collection标签具有懒加载的功能。

Usermapper.xml

在这里插入图片描述
在这里插入图片描述

OrdersMapper.xml

在这里插入图片描述
在这里插入图片描述

开启懒加载

在这里插入图片描述
在这里插入图片描述

测试

在这里插入图片描述
在这里插入图片描述

8. 查询缓存

请记住:缓存只针对“查询”操作,其他操作会清除\更新缓存。

Mybatis的缓存,包括一级缓存和二级缓存,一级缓存是默认使用的。二级缓存需要手动开启。

一级缓存指的就是sqlsession,同一个sqlSession的同一条查询语句结果会被缓存。

在sqlsession中有一个数据区域,是map结构,这个区域就是一级缓存区域。

一级缓存中的key是由sql语句、条件、statement等信息组成一个唯一值。一级缓存中的value,就是查询出的结果对象

二级缓存指的就是同一个namespace下的mapper,二级缓存中,也有一个map结构,这个区域就是一级缓存区域。

在这里插入图片描述
在这里插入图片描述

8.1 一级缓存

原理:

在这里插入图片描述
在这里插入图片描述

由于一级缓存是sqlSession级别的,在spring中,也可理解为是一个事务级别的,只有在一个事务中的相同查询,一级缓存才有效。

8.2 二级缓存

不同的namespace缓存放不同的map。

原理:

在这里插入图片描述
在这里插入图片描述

二级缓存需要手动开启:

  1. 全局开启
在这里插入图片描述
在这里插入图片描述
  1. mapper开启二级缓存
在这里插入图片描述
在这里插入图片描述

缓存是一种保存操作,对象会被序列化到本地,因此,所有对象都必须实现serializable接口

指定某个方法禁用二级缓存:

在这里插入图片描述
在这里插入图片描述

刷新缓存:

在这里插入图片描述
在这里插入图片描述

注意,二级缓存实际放的是一级缓存,因此,只有当一级缓存的sqlSession关闭后,二级缓存才有数据。

8.2.1 二级缓存应用场景:

应用需求:对于访问响应速度要求高,但是实时性不高的查询,可以采用二级缓存技术。

注意:在使用二级缓存的时候,要设置一下刷新间隔(cache标签中有一个flashInterval属性)来定时刷新二级缓存,这个刷新间隔根据具体需求来设置,比如设置30分钟、60分钟等,单位为毫秒。

局限性 Mybatis二级缓存对细粒度的数据,缓存实现不好。

应用场景: 对商品信息进行缓存,由于商品信息查询访问量大,但是要求用户每次查询都是最新的商品信息,此时如果使用二级缓存,就无法实现当一个商品发生变化只刷新该商品的缓存信息而不刷新其他商品缓存信息,因为二级缓存是mapper级别的,当一个商品的信息发送更新,所有的商品信息缓存数据都会清空。

解决此类问题,需要在业务层根据需要对数据有针对性的缓存。 比如可以对经常变化的 数据操作单独放到另一个namespace的mapper中。

mybatis本身的缓存实现不太好,因此本节没有详细解释用法,仅仅是罗列概念。 在springboot中将学习更好的缓存框架。

8.2.2 缓存框架

mybatis的缓存只是“意思意思”,实际上不会真的用。一般使用第三方缓存框架

  • 如果是单个应用或者对缓存访问要求很高的应用,用ehcache。
  • 如果是大型系统,存在缓存共享、分布式部署、缓存内容很大的,建议用redis。

9. MyBatisPlus

mybatisplus是对mybatis的封装操作,能够实现更加强大的功能 mybatisplus官网

具体的使用可以查看官网(中文),我会在springboot中将会介绍它的入门使用。

推荐一个不错的学习博文 链接

10. 重点笔记(核心)

mybatis映射文件:

  • resultMap,自定义结果集
  • sql,抽取可重用语句块
  • insert、update、delete、select
    • values中的#{}填写的值,直接使用传入的pojo等封装对象的属性
    • 允许增删改直接定义包装类型的返回值
    • 如果是非pojo等封装对象,mybatis会将其封装为map,默认的key是param1~paramN,因此,最好在接口的方法传参中加上@param(“key名”)指定sql语句中的参数
    • 如果不是pojo对象,且不经常使用,则可以将其封装为map,因为mybatis底层本身就是使用map
    • 对于经常使用的多参数模型,创建专用的TO即可
    • 如果传入的是collection或list,虽然也是封装为map,但是map的key指定为collection和list,比如访问数组的第一个值:list[0]
    • 如果返回的是集合,resultType依旧写集合中元素的类型
    • 想要返回Map<主键,Javabean>,则resultType填Javabean,mapper接口方法上加上@MapKey(“主键字段名”)
  • parameterType,传入的参数类型,可以省略
  • cache,命名空间的二级缓存配置
  • cache-ref,其他命名空间缓存配置的引用
  • parameterMap,已废弃,老式的参数映射

#和$的区别:

  • #通过占位符的形式与sql拼接,能防止sql注入
  • 用在原生sql语句不允许使用占位符的时候(非参数的地方),如: 分表:select * from {year}_salary;分组:select * from user order by {orderName}
  • #能够规定参数的一些规则

resultMap详解:

基本用法:如果查询出来的列名和Javabean属性名不一致,可以通过resultMap将列名将Javabean属性名之间作一个映射关系。

高级用法():实现关联查询

11. 运行原理(重要)

架构图

在这里插入图片描述
在这里插入图片描述

11.1 基础点

底层执行步骤:

  • 所有的mybatis应用都围绕着SqlSessionFactory,因此框架的第一步就是构建SqlSessionFactory
  • 从SqlSessionFactory中拿到sqlSession对象,sqlSession能够通过唯一标识执行已经映射的sql语句(Mapped sql),执行完毕需要关闭。
  • 唯一标识:Mapped sql的id,且包含namespace。
  • Mapped sql:就是包含sql语句的xxMapper.xml,需要将其注册到全局配置文件的Mappers中才能生效。

接口式执行步骤:

  • 配置Mapper接口,写上所需方法。
  • 配置Mapper.xml
  • 通过mapper全类名地址=namespace,将Mapper接口和Mapper.xml实现文件绑定
  • 通过mapper中方法名=xml中sql方法的id,将sql语句和接口方法绑定
  • 创建SqlSessionFactory,获取sqlSession对象,通过sqlSession获取Mapper接口的代理对象,然后用其调用方法,最后关闭sqlSession对象。

非线程安全的对象(如sqlSession),不允许将其作为类属性作为类共享属性,而应该在调用处,每次获取新的对象,否则会出现竞争。

Mapper接口没有实现类,但是mybatis为其生成了代理对象。

mybatis通过TypeHandlers实现Java和mysql对象的转换。

mybatis四大对象:

  • Executor:MyBatis的执行器,用于执行增删改查操作
  • ParameterHandler:处理SQL的参数对象
  • ResultSetHandler:处理SQL的返回结果集
  • StatementHandler:数据库的处理对象,用于执行SQL语句

11.2 解析源码从HelloWorld开始

1. 获取SqlSessionFactory对象

在这里插入图片描述
在这里插入图片描述

2. 获取sqlSession对象

在这里插入图片描述
在这里插入图片描述

在这步,拿到了四大对象之一的executor(第七步很重要,利用了插件包装executor)

3. 获取Mapper接口的代理对象(MapperProxy)

在这里插入图片描述
在这里插入图片描述

4. 执行增删改查方法

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

总结

代码语言:javascript
复制
 * 	1、根据配置文件(全局,sql映射)初始化出Configuration对象
 * 	2、创建一个DefaultSqlSession对象,
 * 		他里面包含Configuration以及
 * 		Executor(根据全局配置文件中的defaultExecutorType创建出对应的Executor)
 *  3、DefaultSqlSession.getMapper():拿到Mapper接口对应的MapperProxy;
 *  4、MapperProxy里面有(DefaultSqlSession);
 *  5、执行增删改查方法:
 *  		1)、调用DefaultSqlSession的增删改查(Executor);
 *  		2)、会创建一个StatementHandler对象。
 *  			(同时也会创建出ParameterHandler和ResultSetHandler)
 *  		3)、调用StatementHandler预编译参数以及设置参数值;
 *  			使用ParameterHandler来给sql设置参数
 *  		4)、调用StatementHandler的增删改查方法;
 *  		5)、ResultSetHandler封装结果
 *  注意:
 *  	四大对象每个创建的时候都有一个interceptorChain.pluginAll(parameterHandler);

如下图所示:

在这里插入图片描述
在这里插入图片描述

11.3 插件机制

MyBatis在四大对象的创建过程中,都会有插件进行介入。

插件可以利用动态代理机制一层层的包装目标对象,而实现在目标对象执行目标方法之前进行拦截的效果。

MyBatis 允许在已映射语句执行过程中的某一点进行拦截调用。 默认情况下,MyBatis 允许使用插件来拦截的方法调用包括:

  • Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
  • ParameterHandler (getParameterObject, setParameters)
  • ResultSetHandler (handleResultSets, handleOutputParameters)
  • StatementHandler (prepare, parameterize, batch, update, query)
在这里插入图片描述
在这里插入图片描述
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019/12/26 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 简介
    • 1.1 原生JDBC 缺点
      • 1.2 MyBatis框架核心
        • 1.3 开发步骤
          • 1.3.1 创建model类
          • 1.3.2 创建全局配置文件
          • 1.3.3 编写映射文件
          • 1.3.4 加载映射文件
          • 1.3.5 编写测试程序
      • 2. 常用查询(语法重点)
        • 2.1 模糊查询
          • 2.2 增
            • 2.3 删
              • 2.4 改
                • 2.5 获得自增主键
                  • 2.6 获得自增UUID
                    • 2.7 语法小结
                    • 3. Dao层 —— mapper(核心)
                      • 3.1 开发规范
                        • 3.2 测试
                          • 3.2.1 编写mapper接口以及对应的配置文件
                          • 3.2.2 添加配置映射
                          • 3.2.3 测试
                        • 3.3 全局配置setting(了解)
                          • 3.4 别名 typeAliases
                            • 3.4.1 mybatis内置别名
                            • 3.4.2 自定义别名
                          • 3.5 mapper注册
                            • 3.6 注解开发
                            • 4. 映射文件(重点)
                              • 4.1 输入映射ParameterType
                                • 4.1.1 简单类型
                                • 4.1.2 传递POJO包装对象
                                • 4.1.3 传递Map对象
                              • 4.2 输出映射 resultType/resultMap
                                • 4.2.1 resultType
                                  • 4.2.2 resultMap
                                • 4.3 映射用法总结
                                • 5. 高级查询语法
                                  • 5.1 if和where
                                    • 5.2 SQL片段
                                      • 5.3 for-each
                                        • 5.4 choose(分支查询)
                                        • 6. 关联查询
                                          • 6.1 一对一
                                            • 6.1.1 resultType实现
                                            • 6.1.2 resultMap实现
                                            • 小结
                                          • 6.2 一对多
                                            • 小结
                                          • 6.3 多对多
                                            • 6.4 总结
                                            • 7. 懒加载
                                            • 8. 查询缓存
                                              • 8.1 一级缓存
                                                • 8.2 二级缓存
                                                  • 8.2.1 二级缓存应用场景:
                                                  • 8.2.2 缓存框架
                                              • 9. MyBatisPlus
                                              • 10. 重点笔记(核心)
                                              • 11. 运行原理(重要)
                                                • 架构图
                                                  • 11.1 基础点
                                                    • 11.2 解析源码从HelloWorld开始
                                                      • 1. 获取SqlSessionFactory对象
                                                      • 2. 获取sqlSession对象
                                                      • 3. 获取Mapper接口的代理对象(MapperProxy)
                                                      • 4. 执行增删改查方法
                                                      • 总结
                                                    • 11.3 插件机制
                                                    相关产品与服务
                                                    云数据库 SQL Server
                                                    腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
                                                    领券
                                                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档