Mybatis关于复杂的SQL查询的处理&Mybatis的缓存机制
Posted a碟
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mybatis关于复杂的SQL查询的处理&Mybatis的缓存机制相关的知识,希望对你有一定的参考价值。
目录
1、多对一处理
多对一:
- 多个学生,对应一个老师
- 对于学生这边而言, 关联 … 多个学生,关联一个老师 【多对一】
- 对于老师而言, 集合 , 一个老师,有很多学生 【一对多】
SQL:
CREATE TABLE `teacher` (
`id` INT(10) NOT NULL,
`name` VARCHAR(30) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8
INSERT INTO teacher(`id`, `name`) VALUES (1, '秦老师');
CREATE TABLE `student` (
`id` INT(10) NOT NULL,
`name` VARCHAR(30) DEFAULT NULL,
`tid` INT(10) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fktid` (`tid`),
CONSTRAINT `fktid` FOREIGN KEY (`tid`) REFERENCES `teacher` (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('1', '小明', '1');
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('2', '小红', '1');
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('3', '小张', '1');
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('4', '小李', '1');
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('5', '小王', '1');
1.1、测试环境搭建
- 导入lombok
- 新建实体类 Teacher,Student
- 建立Mapper接口
- 建立Mapper.XML文件
- 在核心配置文件中绑定注册我们的Mapper接口或者文件!【方式很多,随心选】
- 测试查询是否能够成功!
1.2、按照查询嵌套处理
<!--
思路:
1. 查询所有的学生信息
2. 根据查询出来的学生的tid,寻找对应的老师! 子查询
-->
<select id="getStudent" resultMap="StudentTeacher">
select * from student
</select>
<resultMap id="StudentTeacher" type="Student">
<result property="id" column="id"/>
<result property="name" column="name"/>
<!--复杂的属性,我们需要单独处理 对象: association 集合: collection -->
<association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>
</resultMap>
<select id="getTeacher" resultType="Teacher">
select * from teacher where id = #id
</select>
1.3、按照结果嵌套处理
<!--按照结果嵌套处理-->
<select id="getStudent2" resultMap="StudentTeacher2">
select s.id sid,s.name sname,t.name tname
from student s,teacher t
where s.tid = t.id;
</select>
<!-- 这样的结果集映射,可以处理结果中,将teacher对象的属性name赋值为查询结果中的tname-->
<resultMap id="StudentTeacher2" type="Student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<association property="teacher" javaType="Teacher">
<result property="name" column="tname"/>
</association>
</resultMap>
回顾mysql 多对一查询方式:
- 子查询
- 联表查询
2、一对多处理
比如:一个老师拥有多个学生!
对于老师而言,就是一对多的关系!
2.1、环境搭建
- 环境搭建,和刚才一样
实体类
@Data
public class Student
private int id;
private String name;
private int tid;
@Data
public class Teacher
private int id;
private String name;
//一个老师拥有多个学生
private List<Student> students;
2.2、按照结果嵌套处理
<!--按结果嵌套查询-->
<select id="getTeacher" resultMap="TeacherStudent">
select s.id sid, s.name sname, t.name tname,t.id tid
from student s,teacher t
where s.tid = t.id and t.id = #tid
</select>
<resultMap id="TeacherStudent" type="Teacher">
<result property="id" column="tid"/>
<result property="name" column="tname"/>
<!--复杂的属性,我们需要单独处理 对象: association 集合: collection
javaType="" 指定属性的类型!
集合中的泛型信息,我们使用ofType获取
-->
<collection property="students" ofType="Student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<result property="tid" column="tid"/>
</collection>
</resultMap>
2.3、按照查询嵌套处理
<select id="getTeacher2" resultMap="TeacherStudent2">
select * from mybatis.teacher where id = #tid
</select>
<resultMap id="TeacherStudent2" type="Teacher">
<collection property="students" javaType="ArrayList" ofType="Student" select="getStudentByTeacherId" column="id"/>
</resultMap>
<select id="getStudentByTeacherId" resultType="Student">
select * from mybatis.student where tid = #tid
</select>
2.4、小结
- 关联 - association 【多对一】
- 集合 - collection 【一对多】
- javaType & ofType
- JavaType 用来指定实体类中属性的类型
- ofType 用来指定映射到List或者集合中的 pojo类型,泛型中的约束类型!
注意点:
- 保证SQL的可读性,尽量保证通俗易懂
- 注意一对多和多对一中,属性名和字段的问题!
- 如果问题不好排查错误,可以使用日志 , 建议使用 Log4j
慢SQL 1s 1000s
面试高频
- Mysql引擎
- InnoDB底层原理
- 索引
- 索引优化!
3、动态 SQL
什么是动态SQL:动态SQL就是指根据不同的条件生成不同的SQL语句
利用动态 SQL 这一特性可以彻底摆脱这种痛苦。
动态 SQL 元素和 JSTL 或基于类似 XML 的文本处理器相似。在 MyBatis 之前的版本中,有很多元素需要花时间了解。MyBatis 3 大大精简了元素种类,现在只需学习原来一半的元素便可。MyBatis 采用功能强大的基于 OGNL 的表达式来淘汰其它大部分元素。
if
choose (when, otherwise)
trim (where, set)
foreach
3.1、搭建环境
CREATE TABLE `blog` (
`id` varchar(50) NOT NULL COMMENT '博客id',
`title` varchar(100) NOT NULL COMMENT '博客标题',
`author` varchar(30) NOT NULL COMMENT '博客作者',
`create_time` datetime NOT NULL COMMENT '创建时间',
`views` int(30) NOT NULL COMMENT '浏览量'
) ENGINE=InnoDB DEFAULT CHARSET=utf8
补充:因为MySQL中所有的字母都是大写,我们命名为xxx_xxx,驼峰命名映射可以将其映射到经典的java属性名XxxXxx
创建一个基础工程
-
导包
-
编写配置文件
-
编写实体类
@Data public class Blog private int id; private String title; private String author; private Date createTime; private int views;
-
编写实体类对应Mapper接口 和 Mapper.XML文件
package com.adie.dao;
import com.adie.pojo.Blog;
public interface BlogMapper
// 插入数据
int addBlog(Blog blog);
<?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="com.adie.dao.BlogMapper">
<insert id="addBlog" parameterType="blog">
insert into blog(id,title,author,create_time,views)
values (#id,#title,#author,#createTime,#views)
</insert>
</mapper>
3.2、IF
<select id="queryBlogIF" parameterType="map" resultType="blog">
select * from mybatis.blog where 1=1
<if test="title != null">
and title = #title
</if>
<if test="author != null">
and author = #author
</if>
</select>
没有给参数时
只有title参数时
有title和author参数时
可以看到我们在写SQL语句的时候写了一句1=1,为什么需要这一句呢,因为如果不写这句话,只写where,如果后面没有匹配的条件,sql将变成select * from blog where。这样的语句是不对的。或者如果只匹配第二个条件,那么SQL变成 select * from blog where and authot=""。这样的SQL也是不对的。
那么如何解决这个问题,可以不写1=1呢,Mybatis提供了这样一个解决办法
更改xml后
<select id="queryBlogIF" parameterType="map" resultType="blog">
select * from blog
<where>
<if test="title!=null">
and title=#title
</if>
<if test="author!=null">
and author=#author
</if>
</where>
</select>
3.3、choose (when, otherwise)
只选择其中一个条件,和switch类似
<select id="queryBlogChoose" parameterType="map" resultType="blog">
select * from mybatis.blog
<where>
<choose>
<when test="title != null">
title = #title
</when>
<when test="author != null">
and author = #author
</when>
<otherwise>
and views = #views
</otherwise>
</choose>
</where>
</select>
只带otherwise上的条件时
可以看到存在一个条件时,我们没有走otherwise
先进入了第一个when,每次只选择SQL语句中写好的最近的那个存在的条件
3.4、trim (where,set)
where在if中提过了
select * from mybatis.blog
<where>
<if test="title != null">
title = #title
</if>
<if test="author != null">
and author = #author
</if>
</where>
set和之前说的where用法类似,在update中,我们如果需要修改多个字段,每个字段之间我们会使用“,”隔开。那么在xml中写了if判断需要修改哪个字段,我们并不能确定什么时候需要逗号隔开,所以set就是来处理这个问题的。
<update id="updateBlog" parameterType="map">
update mybatis.blog
<set>
<if test="title != null">
title = #title,
</if>
<if test="author != null">
author = #author
</if>
</set>
where id = #id
</update>
更改title和author两个字段
只更改author字段
自定义前缀后缀trime。图片中的前缀后缀是指整个字段里面的最前面/最后面
所谓的动态SQL,本质还是SQL语句 , 只是我们可以在SQL层面,去执行一个逻辑代码
if
where , set , choose ,when
3.5、SQL片段
有的时候,我们可能会将一些功能的部分抽取出来,方便复用!
-
使用SQL标签抽取公共的部分
<sql id="if-title-author"> <if test="title != null"> title = #title </if> <if test="author != null"> and author = #author </if> </sql>
-
在需要使用的地方使用Include标签引用即可
<select id="queryBlogIF" parameterType="map" resultType="blog"> select * from mybatis.blog <where> <include refid="if-title-author"></include> </where> </select>
注意事项:
- 最好基于单表来定义SQL片段!
- 不要存在where标签
3.6、Foreach
select * Mybatis的动态sql的处理