mybatis文档笔记

目录

这两个链接 基本上把本目录的所有知识点都包含进去了
mybatis高级查询具体操作

mybatis增删改查基本操作

Mybatis框架

1. jdbc回顾:

2. mybatis介绍

3. mybatis的整体架构

4. mybatis快速入门

5. 完整CRUD操作

6. 动态代理mapper实现类

7. mybatis-config 配置

8. Mapper.xml

9. 整理

10. 动态sql

11. 缓存

12. 高级查询

13. 分页插件

14. mybatis和spring整合

Mybatis框架

1.jdbc回顾:

mybatis文档笔记_第1张图片
jdbc的问题:
mybatis文档笔记_第2张图片

1、加载驱动问题:
每次执行都加载驱动
驱动名称,硬编码到java代码中,如果需要修改驱动。需要修改java文件
解决方案:将驱动名称放入到外部的配置文件
2、数据库的连接信息,硬编码到java代码中,解决方案:外部配置文件
3、设置参数的问题:
参数下标硬编码了。需要人为的去判断参数的位置。

4、遍历结果集:需要人工的判断字段名,以及个位置参数类型,不方便
是否可以:能够将结果集直接映射到一个pojo对象中
5、频繁的创建连接,关闭连接。导致资源浪费,影响性能,解决:连接池。

2.mybatis介绍

你会五大框架吗?

SSH spring struts2(webcontroller—[servlet]) hibernate (dao=jdbc—db)

SSM spring springmvc(webcontroller—[servlet] service[m] ) mybatis(dao=jdbc—db)

mybatis文档笔记_第3张图片
Cn.yanqi.bean domain entity pojo 实体类

在mybatis的包里面可以看到,ibatis的字样。

每一个框架都有一个核心配置文件,这个核心文件你必须会,不会这个框架就用不了

3.mybatis的整体架构

mybatis文档笔记_第4张图片

4.mybatis快速入门

编写第一个mybatis程序
创建数据表 tb_user

mybatis文档笔记_第5张图片

CREATE TABLE `tb_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_name` varchar(20) DEFAULT NULL,
  `sex` varchar(10) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
导入依赖

向工程的pom文件中,添加mybatis的依赖
mybatis文档笔记_第6张图片

向工程中,添加mybatis的依赖
在这里插入图片描述

编写全局配置文件

在工程的根目录src下面创建一个mybatis-config.xml 。这个名字不是固定的,可以随便起,
但也不能太随便,通常都叫mybatis-config.xml
注意:mybatis-config.xml 引入外部的jdbc.properties文件

mybatis文档笔记_第7张图片

外部的jdbc.properties文件

在src下创建
mybatis文档笔记_第8张图片

编写一个pojo实体类

提供getter,setter,toString方法
在这里插入图片描述
mybatis文档笔记_第9张图片

mapper.xml根据id查询用户信息
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200311065412420.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NTE1MTk2MA==,size_16,color_FFFFFF,t_70)

1、创建一个局部的mapper.xml(名字也可以随便写,但是不能太随便,位置可以放在项目里的任何位置,只需要你能加载到对应的mpper.xml即可)
在这里插入图片描述
通常我们就叫标签为一个statement对象或者叫mapped statement对象

mybatis文档笔记_第10张图片

构建SqlSessionFactory

可以通过官方文档里找路径如下:
在这里插入图片描述
打开index.html

mybatis文档笔记_第11张图片

其中Mybatis-config.XML文件的位置不是固定的,只要能找到xml文件就行,可以随便放
在这里插入图片描述
mybatis文档笔记_第12张图片

2、在全局的mybatis-config.xml 中去添加mapper.xml的配置
在这里插入图片描述

3、书写java代码,调用指定的statement,并且传递参数信息。获取返回值
mybatis文档笔记_第13张图片

mybatis文档笔记_第14张图片
测试打印查看是否查询到数据
在这里插入图片描述

注意:需要在mybatis-config.xml 中使用mapper 去引入外部的mapper.xml

添加日志支持

放在src下面
在这里插入图片描述

导入依赖

mybatis文档笔记_第15张图片

mybatis使用步骤总结

mybatis文档笔记_第16张图片

5.完整CRUD操作

创建UserDao接口

在这里插入图片描述

	public interface UserDao {	
/**
 * 根据id查询用户信息
	 * @param id
	 * @return
*/
    public User queryUserById(int id);	
	/**
	 * 查询所有用户信息
	 * @return
	 */
	public List<User> queryAllUser();
	/**
	 * 根据id删除用户信息
	 * @param id
	 */
	public void deleteUserById(int id);
	/**
	 * 添加用户信息
	 * @param user
	 */
	public void addUser(User user);
	/**
	 * 修改用户信息
	 * @param user
	 */
	public void updateUser(User user);
    
}
创建UserDaoImpl实现类
public class UserDaoImpl implements UserDao{
	//需要sqlSession的来操作
	private SqlSession sqlSession;
	//临时解决方案,利用构造方法传入
	public UserDaoImpl(SqlSession sqlSession){
		this.sqlSession = sqlSession;
	}
	//根据id来查询用户
	@Override
	public User queryUserById(int id) {
		return sqlSession.selectOne("user.queryUserById", id);
	}
	//查询所有
	@Override
	public List<User> queryAllUser() {
		return sqlSession.selectList("user.queryAllUser");
	}
	//删除用户
	@Override
	public void deleteUserById(int id) {
		sqlSession.delete("user.deleteUserById", id);
	}
	//添加用户
	@Override
	public void addUser(User user) {
		sqlSession.insert("user.addUser", user);
	}
   //修改用户
	@Override
	public void updateUser(User user) {
		sqlSession.update("user.updateUser", user);
	}
}
编写User对应的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">
  
<mapper namespace="user">
	  <!-- 根据id来查询 -->
	  <select id="queryUserById" resultType="cn.yanqi.mybaits.pojo.User">
	    select * from t_user where id = #{id}
	  </select>
	  
	  <!-- 查询所有 -->
	  <select id="queryAllUser" resultType="cn.yanqi.mybaits.pojo.User">
	     select * from t_user
	  </select>
	  
	  <!-- 根据id来删除用户      没有结果集的映射的java对象-->
	  <delete id="deleteUserById">
	     delete from t_user where id = #{id}
	  </delete>
	  
	  <!-- 添加用户 -->
	  <insert id="addUser">
	  		INSERT INTO t_user 
	  			(id,
	  		    name,
	  		    sex)
			VALUES(
				NULL,
				#{name},
			    #{sex}
			)
	  </insert>
	  
	   <!-- 修改用户   #{name} pojo类属性一样-->
	  <update id="updateUser">
	 	UPDATE t_user
			SET
			 name = #{name},
			 sex = #{sex}
			WHERE
				id = #{id}
	 </update>
   </mapper>

在mybatis-config.xml里面引入UserMapper.xml
mybatis文档笔记_第17张图片

编写测试用例—操作

mybatis文档笔记_第18张图片
用Junit Test Case 来测试

mybatis文档笔记_第19张图片

mybatis文档笔记_第20张图片
mybatis文档笔记_第21张图片

编写测试用例
public class UserDaoTest {
	//new 一个userDao对象
	private UserDao userDao;
	private SqlSession sqlSession;//定义成全局的对象
	
	@Before//执行test方法之前执行
	public void setUp() throws Exception {
		
		String resource ="mybatis-config.xml";
		//读取xml配置文件
		InputStream is = Resources.getResourceAsStream(resource);
		//构建SqlSessionFactory
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is); 
		//打开SqlSession,得到sqlSession可以进行curd的操作
		sqlSession = sqlSessionFactory.openSession();
		//userDao = new UserDaoImpl(sqlSession);
		//获取mapper的动态代理实现类
		userDao = sqlSession.getMapper(UserDao.class);
	}
	//根据id查询
	@Test
	public void testQueryUserById() {
		//调用userDao方法
		User user = userDao.queryUserById(1);
		System.out.println(user);
	}
	//查询所有
	@Test
	public void testQueryAllUser() {
		//调用userDao方法
		List<User> users = userDao.queryAllUser();
		//遍历输出
		for(User user : users){
			System.out.println(user);
		}
	}
	//根据id来删除
	@Test
	public void testDeleteUserById() {
		userDao.deleteUserById(6);
		sqlSession.commit();//必须开启事务
	}
	//添加user
	@Test
	public void testAddUser() {
		User user = new User();
		user.setName("yanqi");
		user.setSex("boy");
		userDao.addUser(user);
		sqlSession.commit();//不开启事务是写入不到数据库里去的
	}
	//修改用户
	@Test
	public void testUpdateUser() {
//		1、先去查询
		User user = userDao.queryUserById(1);
		user.setName("yanqi");
		userDao.updateUser(user);
//		提交事务
		sqlSession.commit();
	}
}
数据库字段名和实体类属性名不一致的问题

查询数据的时候,查不到userName的信息,原因:数据库的字段名是user_name
POJO中的属性名字是userName
两端不一致,造成mybatis无法填充对应的字段信息。修改方法:在sql语句中使用别名
解决方案1:在sql语句中使用别名(麻烦)
Select * , user_name as username from t_user;

在这里插入图片描述
解决方案2: 参考后面的resultMap –mapper具体的配置的时候
解决方案3:参考驼峰匹配 — mybatis-config.xml 的时候

mybatis中dao层的命名规则

在mybatis中dao层的接口的名字不在使用***Dao 而是修改成***Mapper
例如:把UserDao,修改成UserMapper。 UserDao(Mapper)

思考CURD的dao中的问题

接口->实现类->mapper.xml

思考:能否只写UserDao接口,不书写实现类UserDaoImp,只编写Mapper.xml即可

6.动态代理mapper实现类

使用动态代理的目标是可以不用书写实现类,只需要书写接口和mapper.xml即可完成crud的操作

如果不想写实现类(UserDaoImpl ) ,只写接口UserDao ---- 就可以使用动态代理
因为在dao(mapper)的实现类中对sqlsession的使用方式很类似。mybatis提供了接口的动态代理

名称空间

mapper.xml 根标签的 namespace 属性
如果希望使用mybatis通过的动态代理的接口,就需要namespace 中的值,和需要对应的Mapper(dao)接口的全路径一直

mybatis文档笔记_第22张图片
mybatis文档笔记_第23张图片

通过sqlSession.getMapper(接口类.class)

mybatis文档笔记_第24张图片

使用动态代理总结

mybatis文档笔记_第25张图片

出现错误

mybatis文档笔记_第26张图片

错误原因:mapper接口的全路径和对应mapper.xml的名称空间不一致造成。

7.mybatis-config 配置

mapUnderscoreToCamelCase用法:

开启驼峰匹配:从经典数据库的命名规则user_name,到经典java命名规则的映射userName
java命名规则:驼峰书写, 大小写区分两个单词的界限。举例: userName;
数据库经典命名规则:两个单词之间,使用下划线分割。举例:user_name

开启驼峰匹配:相当于去掉数据库名字中的下划线,然后在与java中的属性名进行对应。

数据库中的user_name 和java属性中的 userName 是一样的
在mybatis-config.xml中:

mybatis文档笔记_第27张图片

typeAliases(常用)

给类起一个别名
mybatis文档笔记_第28张图片
缺点:需要为每一个类都去定义一个类型别名。书写麻烦。

typeAliases的使用2—使用扫描包

在这里插入图片描述
mybatis文档笔记_第29张图片
mybatis文档笔记_第30张图片

typeHandlers(类型处理器)

mybatis文档笔记_第31张图片

mybatis文档笔记_第32张图片

environments(环境)

在这里插入图片描述
预发布环境;
mybatis文档笔记_第33张图片
可以指定数据源
在这里插入图片描述

mappers----映射器

作用:将mapper.xml 文件配置到mybatis-config.xml的环境中。
mybatis文档笔记_第34张图片

使用mapper接口路径:

这里所谓的mapper接口路径。实际上就是dao的接口路径。在mybatis中,通常把dao的包叫做mapper
类名,也叫做mapper

1、定义一个接口
2、在接口所在的包中定义mapper.xml
3、在mybatis-config.xml 中通过class路径,引入mapper。要求mapper.xml 中的名称空间是类的接口的全路径
在这里插入图片描述
mybatis文档笔记_第35张图片

问题:
1、mapper.xml 和 java文件没有分离。spring整合之后解决。
2、需要一个一个的去加载mapper

使用mapper接口扫描包(常用)

mybatis文档笔记_第36张图片
扫描的是包
在这里插入图片描述
缺点:
1、如果包的路径有很多?2、mapper.xml和mapper.java没有分离。
2、在spring整合的时候可以解决这个问题

整理mybatis-config中的内容

2settings:开启驼峰匹配。
从数据库的经典命名规则到java经典命名规则的映射; 把数据库中的下划线去顶在和java中的内容进行映射。

 <settings>
  	<setting name="mapUnderscoreToCamelCase" value="true" />
  </settings>

3、typealiases:类型别名。 为一些java对象,去起一个简写的名字,减少mapper.xml中的 代码书写量。

	<typeAliases>
  	 	<package name="cn.yanqi.mybatis.pojo"/>
</typeAliases>

4、环境:数据库的连接信息
5、mappers:关联外部的mapper.xml文件的
把外部的mapper.xml加载到mybatis中

扫描包的方式:

<mappers>
     <!--
          扫描指定包下面的所有的接口
     	 要求:
     	 1、要求mapper.xml文件的名字和mapper接口的名字,一致
     	 2、要求mapper.xml文件 和 mapper接口类在一个目录下
       -->
     <package name="cn.yanqi.mybatis.mapper"/>
<mapper resource="cn/yanqi/mybatis/resources/mapper.xml"/>
<mapper class="cn.yanqi.mybatis.mapper.UserMapper"/>
  </mappers>

8.Mapper.xml

mybatis文档笔记_第37张图片

CURD操作
select

select – 书写查询sql语句

id属性:当前名称空间下的statement的唯一标识。必须。要求id和mapper接口中的方法的名字一致。
Select 标签中 resultType:将结果集映射为java的对象类型必须要有(和 resultMap 二选一)

parameterType:传入参数类型。可以省略,会自判断传入的是什么类型

要求:查询当前有多少人
mybatis文档笔记_第38张图片
接口方法
mybatis文档笔记_第39张图片

测试
mybatis文档笔记_第40张图片

insert

insert 的几个属性说明:
id属性:当前名称空间下的statement的唯一标识(必须属性);
parameterType:传入的参数类型,可以省略。
标签内部:具体的sql语句。insert语句
使用#{} 去替换一个变量。

怎么知道我们添加时是否添加成功怎么办?
UserMapper.java 接口中把返回类型直接写成Integer返回类型,其他的不用动

在这里插入图片描述测试类中给一个integer 返回值就行了
mybatis文档笔记_第41张图片
添加成功后返回1
mybatis文档笔记_第42张图片
在这里插入图片描述

获取自增的id的值

可以拿到数据库的自增长的id值

在这里插入图片描述
mybatis文档笔记_第43张图片
测试:
User.getId();就可以直接拿到自增的id
mybatis文档笔记_第44张图片
测试结果:
在这里插入图片描述

Update

update 的几个属性说明:
id属性:当前名称空间下的statement的唯一标识(必须属性);
parameterType:传入的参数类型,可以省略。
标签内部:具体的sql语句。
使用#{} 去替换一个变量。

在这里插入图片描述

补充:

mybatis文档笔记_第45张图片

delete

delete 的几个属性说明:
id属性:当前名称空间下的statement的唯一标识(必须属性);
parameterType:传入的参数类型,可以省略。
标签内部:具体的sql语句。
使用#{} 去替换一个变量。

#{ 只是表示占位可以随便写 } 相当于 ?

在这里插入图片描述

${}的用法----传入参数的。接受参数。

#{} ?只能出现where中 ,当作一个变量 ,如要sql语句中要在实体对象中取出数据 ,那么where 后的#{}不能随便写
数 据 : 是 进 行 字 符 串 拼 接 。 如 果 使 用 {} 数据:是进行字符串拼接。 如果使用 使{} 去取出参数信息,则需要在方法的参数列表上加上一个注释@param 表示参数的名字
#{} 只是表示占位,与参数的名字无关。如果用#{}去传入下例中的一个表名的话,是传不进去的

sql语句动态生成的时候,使用${};
sql语句中某个参数进行占位的时候#{}

mapper.xml中的内容:
新写一个接口的方法

mybatis文档笔记_第46张图片
mapper接口的内容:

mybatis文档笔记_第47张图片
测试:
mybatis文档笔记_第48张图片

parameterType传入参数-了解

定义传入参数的类型:

如果 没 有 指 定 参 数 名 , 使 用 {} 没有指定参数名 ,使用 使{value} 表示传递过来的参数。
如果接口中书写的@Param(“TableName”) 就输入 ${TableName}
在这里插入图片描述

mybatis文档笔记_第49张图片

可以在方法的参数列表列表上 @param(“参数名”)

mybatis文档笔记_第50张图片

1、如果使用$去传递参数的时候,使用@Param 把参数指定一个名字
2、如果传入多个参数的时候,使用@Param,一定需要使用为每一个参数都去指定名字

parameterType传入多个参数

如果接口代码这样书写:
mapper.xml
传递多个参数的时候出现如下错误:
mybatis文档笔记_第51张图片
对于传入多个参数的时候,#{} 需要使用参数名的方式去获取数据。
java代码:
mybatis文档笔记_第52张图片

解决方案1 不推存使用:
在mapper.xml中使用 0,1这样的序号去,0表示第一个参数,1表示第二个参数。(从0开始数)

mybatis文档笔记_第53张图片
mybatis文档笔记_第54张图片
或者 用param1 param2 这个时就是从1开始:
在这里插入图片描述

解决方案2:
在java代码中加入param注解
测试
mybatis文档笔记_第55张图片

通过@param(“ 数据名”) 取出 # { 数据名 }

mybatis文档笔记_第56张图片

mybatis文档笔记_第57张图片
mapper.xml
mybatis文档笔记_第58张图片
接口:
在这里插入图片描述

面试题:#{}与${}的区别

mybatis文档笔记_第59张图片

${} statement对象
#{} Preparedstatement对象

${} 方式:

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

1、KaTeX parse error: Expected 'EOF', got '#' at position 7: 字符串拼接,#̲ 参数站位相当于jdbc中的?…不能够防止sql注入,#可以防止sql注入的
3、KaTeX parse error: Expected 'EOF', got '#' at position 17: …以替换sql语句任何一个内容,#̲只能替换参数 4、如果操作字符串,需要在sql中使用单引号。 #不需要(不需要判断数据类型,会自动转换)($要考虑参类型 ,#不用考虑参数类型)

简单来说#{} 解析的是占位符?可以防止SQL注入, 比如打印出来的语句 select * from table where id= ? 然而${} 作为字符串拼接来用,则是不能防止SQL注入打印出来的语句 select * from table where id=2 实实在在的参数 (sql注入:通过字符串拼接达到串改sql语句的目地)

8.5.1: $不能够防止sql注入,#可以防止sql注入的

mybatis文档笔记_第60张图片

以下案例演示的要判断数据类型

案例:根据姓名进行模糊查询

定义一个接口的方法

在这里插入图片描述
使用#
在这里插入图片描述
测试:

mybatis文档笔记_第61张图片
使用 $

接口定义方法
在这里插入图片描述
mapper定义
在这里插入图片描述
测试:
mybatis文档笔记_第62张图片
结果
在这里插入图片描述

【补充】

mybatis文档笔记_第63张图片

什么时候使用 $ ,

$可以代替所有#
如果传入的数据,不是sql中的字段的时候,就不能够使用#.

通常使用#。
选择获取参数的时候,首要选择的# 的方式(1、可以防止sql注入,2、可以不用考虑数据类型,简化书写,3、sql是参数的话的sql,预编译的sql,速度会块一些)
当#用不了的时候,去选择 例 如 , s q l 需 要 改 变 是 表 名 的 情 况 , 就 可 使 用 例如 ,sql需要改变是表名的情况,就可使用 sql使的方式。

总结:能用# 就不选择$

ResultMap

mybatis文档笔记_第64张图片
mybatis文档笔记_第65张图片

resultMap的自动映射

mybatis文档笔记_第66张图片

sql片段

作用:把重复的sql语句抽出来来放到sql标签中,然后通来引入
mybatis文档笔记_第67张图片

用法1

在一个mapper.xml 中使用 去定义sql片段,然后在需要的位置使用 引入
mybatis文档笔记_第68张图片
mybatis文档笔记_第69张图片
用法2
将所有的公用的SQL片段集中定义到一个Mapper.xml文件中,其他Mapper.xml文件如需引入mybatis-config.xml,通过命名空间.id即可。

sqlMapper.xml
mybatis文档笔记_第70张图片
在全局的mybatis-config.xml里面引入sqlMapper.xml
在这里插入图片描述

引入公共的sql.xml
在这里插入图片描述

9.整理

mybatis文档笔记_第71张图片

10.动态sql

if
进行判断。

需求1:查询男性用户,如果输入了姓名,进行模糊查找,如果不输入就按男性用户来查询。

定义接口

mybatis文档笔记_第72张图片

编写mapper和测试类

使用# {}的方式

mybatis文档笔记_第73张图片

mybatis文档笔记_第74张图片

1:使用 的 方 式 进 行 取 出 数 据 , 要 求 在 s q l 语 句 中 ‘ {}的方式进行取出数据,要求在sql语句中 ‘% sql{}%’
2: 使用#{} 去取出数据,要求在传递参数的时候,就把% 进行拼接到参数上。%张%

choose,when,otherwise

choose,when,otherwise 相当于java中的 if, else if的逻辑

查询男性用户,如果输入了姓名则按照姓名模糊查找,否则如果输入了年龄则按照年龄查找。

定义接口

mybatis文档笔记_第75张图片

编写mapper.xml

如果其中的一个when 成立,则后的都不执行,如果所有when的都不成立,那么就执行otherwise
也就是谁在前面谁优先
mybatis文档笔记_第76张图片

测试

mybatis文档笔记_第77张图片

where 和set

作用:完成WHERE和SET关键字,并且处理SQL语句的中语法错误。
Select * from t_user where …
Update from t_user set name = …

练习:查询所有用户,如果输入了姓名按照姓名进行模糊查询,如果输入年龄,按照年龄进行查询。

定义接口

mybatis文档笔记_第78张图片

编写mapper.xml

Where标签 代替了 where这个关键字 , 并且会把多余的and去掉

在这里插入图片描述

测试

mybatis文档笔记_第79张图片
结果:把多余的and 去掉
mybatis文档笔记_第80张图片
Set 和 where的用户类似(自已测试)

set的使用

Set标签 相当于 sql中 set 关键字
需求:如果名字信息不是null,则修改名字, 如果age信息不是null,同时也修改age
mybatis文档笔记_第81张图片
会自动去掉错的 ,(逗号)
mybatis文档笔记_第82张图片
mybatis文档笔记_第83张图片

foreach

练习:按照多个id查询用户信息
Select * from t_user where id in(1,2,3)

定义接口

mybatis文档笔记_第84张图片

编写mapper.xml

Collection:要遍历的集合, item:接受遍历集合的值in( 1,2,3)

mybatis文档笔记_第85张图片

测试

mybatis文档笔记_第86张图片

Trim

trim介绍

trim元素的主要功能是可以在自己包含的内容前加上某些前缀,也可以在其后加上某写后缀,与之对应的属性是prefix和suffix;
可以把包含内容的首部某些内容覆盖,即忽略,也可以把尾部的某些内容覆盖,对应的属性是prefixOverrides和suffixOver

案例1
select * from user 
  <trim prefix="WHERE" prefixOverrides="AND |OR">
    <if test="name != null and name.length()>0"> AND name=#{name}</if>
    <if test="gender != null and gender.length()>0"> AND gender=#{gender}</if>
</trim>

假如说name和gender的值都不为null的话,打印的SQL为:
select * from user where name = ‘xx’ and gender = ‘xx’

where后不存在and,这是因为prefixOverrides="AND |OR"代表去掉第一个and或者是or。

案例2
update user
  <trim prefix="set" suffixOverrides="," suffix=" where id = #{id} ">
    <if test="name != null and name.length()>0"> name=#{name} , </if>
    <if test="gender != null and gender.length()>0"> gender=#{gender} ,  </if>
</trim>

假如说name和gender的值都不为null的话,打印的SQL为:
update user set name=‘xx’ , gender=‘xx’ where id=‘x’

11.缓存

一级缓存

mybatis文档笔记_第87张图片

在mybatis中,一级缓存默认是开启的,并且一直无法关闭(我们没法去管理一级缓存)

测试一级缓存

1、测试代码

mybatis文档笔记_第88张图片
2、日志输出

在这里插入图片描述

一级缓存满足条件:
1、同一个session中
2、相同的SQL和参数

使用sqlsession.clearCache()强制查询不缓存。

mybatis文档笔记_第89张图片

2、日志输出:

mybatis文档笔记_第90张图片

执行update,delete,insert 语句的时候,清空缓存 刷新缓存

执行update,delete,insert 语句的时候 都会清空缓存 然后刷新

mybatis文档笔记_第91张图片
mybatis文档笔记_第92张图片

二级缓存

mybatis 的二级缓存的作用域是一个mapper的namespace ,同一个namespace中查询sql可以从缓存中命中。
二级缓存是跨session

开启二级缓存

需要在mapper.xml 中加入如下:
在这里插入图片描述

测试二级缓存

java代码:
在这里插入图片描述
跨session来测试

mybatis文档笔记_第93张图片
需要把这个对象进行序列化

mybatis文档笔记_第94张图片

日志输出:
因为开启了二级缓存,第二次会去二级缓存中去命中,所有不会再发送sql语句

mybatis文档笔记_第95张图片

关闭二级缓存

mybatis文档笔记_第96张图片
mybatis文档笔记_第97张图片
在全局的mybatis-config.xml 中去关闭二级缓存

mybatis文档笔记_第98张图片
【扩展知识】
mybatis文档笔记_第99张图片

12.高级查询

案例说明

mybatis文档笔记_第100张图片
mybatis文档笔记_第101张图片

需求

mybatis文档笔记_第102张图片

一对一查询

查询订单,并且查询出下单人的信息

sql语句分析:
我们以定单为主,不管它有没有对应上这用户都要把订单查询出来

SELECT
		*
	FROM
		tb_order
	LEFT JOIN tb_user ON tb_order.user_id = tb_user.id
	where 
      tb_order.order_number =20140921001

在这里插入图片描述

一对一查询实现1(了解)

在这里插入图片描述
mybatis文档笔记_第103张图片

思考:查询订单,并且查询出下单人的信息同要把两个信息放在一块去

核心思想:扩展Order对象,来映射结果集。(把两个信息放到一块去)
第三个实体类,即用户信息也有订单信息
OrderUser.java

mybatis文档笔记_第104张图片

接口定义:
OrderMapper 返回第三个实体类

在这里插入图片描述
OrderMapper.xml中的定义

	<!-- 查询订单,并且查询出下单人的信息 -->
	<select id="queryOrderUserByNumber" resultType="OrderUser">
		SELECT
			*
		FROM
			tb_order
		LEFT JOIN tb_user ON tb_order.user_id = tb_user.id
		where tb_order.order_number = #{orderNumber}
   </select>

测试类
在这里插入图片描述
mybatis文档笔记_第105张图片

一对一查询实现2

核心思想:面向对象的思想,在Order对象中添加User对象。 用这个
mybatis文档笔记_第106张图片

接口方法: 返回的对象是Order
mybatis文档笔记_第107张图片

使用resultType不能完成自动映射,所以需要手动完成结果集的映射,需要使用resultMap实现。
其中user里面的id 和order里面的id 一样。哪个id是属于谁了
mybatis文档笔记_第108张图片
测试

mybatis文档笔记_第109张图片
测试结果:
在这里插入图片描述
在这里插入图片描述

一对多查询

一对多查询:查询订单,查询出下单人信息并且查询出订单详情。
一个定单可以有多个定单详情
mybatis文档笔记_第110张图片

sql:

select *
			,o.id as order_id
			,u.id as user_id
			,d.id as detail_id 
  from 
			tb_order as o
			LEFT JOIN tb_user as u on o.user_id = u.id 
			LEFT JOIN tb_orderdetail as d on d.order_id = o.id
	where 
			o.order_number = '20140921003'; 

定义接口
接口定义:

mybatis文档笔记_第111张图片

Order类:
提供getter,setter 方法

mybatis文档笔记_第112张图片

编写mapper

mybatis文档笔记_第113张图片
测试用例
用debug测试

mybatis文档笔记_第114张图片

多对多查询

定单和商品表 是多对多的对应关系
多对多查询:查询订单,查询出下单人信息并且查询出订单详情中的商品数据。

Sql分析

  SELECT
			*,
			o.id as order_id,
			u.id as user_id,
			d.id as detail_id
		FROM
			tb_order as o 
		LEFT JOIN tb_user as u ON o.user_id = u.id
		left join tb_orderdetail as d on  d.id = o.id
		left join tb_item as i on i.id = d.item_id
		where 
		o.order_number = #{OrderNumber};

定义接口
java对象的实现:

mybatis文档笔记_第115张图片
接口:
返回order对象,里面包含了用户,订单详情,商品
mybatis文档笔记_第116张图片
编写mapper.xml
这里面就不用给itema_id起别名,因为在订单详情表中的名字就是item_id
mybatis文档笔记_第117张图片
编写测试用例

在这里插入图片描述

resultMap的继承

mybatis文档笔记_第118张图片

高级查询整理

resutlType无法帮助我们自动的去完成映射,所以只有使用resultMap手动的进行映射
type 结果集对应的数据类型 id 唯一标识,被引用的时候,进行指定






13.分页插件

实现通用分页组件

mybatis文档笔记_第119张图片

Mybatis的plugin实现原理

mybatis文档笔记_第120张图片

使用PageHelper实现分页

mybatis文档笔记_第121张图片

导入依赖

<dependency>
			<groupId>com.github.pagehelper</groupId>
			<artifactId>pagehelper</artifactId>
			<version>3.7.5</version>
		</dependency>
		<dependency>
			<groupId>com.github.jsqlparser</groupId>
			<artifactId>jsqlparser</artifactId>
			<version>0.9.1</version>
	</dependency>

mybatis文档笔记_第122张图片

配置插件

这个拦截器插件放在配置环境的上面

mybatis文档笔记_第123张图片

在执行查询时设置分页参数

在这里插入图片描述

在这里插入图片描述

可以通过Pageinfo获取分页的信息
Pageinfo.getpages :总页数

mybatis文档笔记_第124张图片

14.mybatis和spring整合

导入依赖

mybatis文档笔记_第125张图片
共22个jar包
mybatis文档笔记_第126张图片

配置spring文件

1、创建spring的配置文件applicationContext.xml

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
	http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
	http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">

配置资源文件替换器
applicationContext.xml

<!-- 使用spring自带的占位符替换功能 -->
	<bean
		class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<!-- 配置资源文件 -->
		<property name="locations">
			<list>
				<value>classpath:jdbc.properties</value>
			</list>
		</property>
	</bean>

jdbc.properties

driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/springdata
username=root
password=root

配置连接池:
applicationContext.xml

<!-- 配置连接池 -->
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
		destroy-method="close">
		<property name="driverClass" value="${c3p0.driverClass}"></property>
		<property name="jdbcUrl" value="${c3p0.url}"></property>
		<property name="user" value="${c3p0.user}"></property>
		<property name="password" value="${c3p0.password}"></property>
	</bean>

配置SqlSessionFactory

<!-- 配置SqlSessionFactory -->
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<!--引入mybatis的总配置  -->
		<property name="configLocation" value="classpath:mybatis-config.xml"></property>
	</bean>

配置mapper

<!-- 配置mapper -->
	<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
 		<!-- 配置mapper接口  (这种方式太麻烦)-->
		<property name="mapperInterface" value="cn.yanqi.mybatis.mapper.UserMapper" />
		<property name="sqlSessionFactory" ref="sqlSessionFactory" />
	</bean>

使用1

配置mapper接口扫描器

<!-- 配置mybatis mapper接口扫描器 -->
	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 如果配置多个mapper的路径,可以使用,多个包使用逗号分割即可:					value="cn.yanqi.mybatis.mapper,cn.yanqi.mybatis.mapper" -->
		<property name="basePackage" value="cn.yanqi.mybatis.mapper" />
	</bean>

在Spring配置文件中指定别名包

mybatis文档笔记_第127张图片

Mapper.xml和java代码分离

mybatis文档笔记_第128张图片

全部配置

mybatis文档笔记_第129张图片

测试整合是否通过:

mybatis文档笔记_第130张图片

mapper整合servcie

servcie方法:

mybatis文档笔记_第131张图片

测试:

mybatis文档笔记_第132张图片

你可能感兴趣的:(mybatis,mybatis笔记,mybatis文档,mybatis增删改查,mybatis高级查询,mybatis项目)