携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第十八天,点击查看活动详情 >>
10 多对一处理
多个学生,对应老师
对于这边而言,关联 多个学生,关联一个老师【多对一】
对于老师而言,集合 一个老师,有很多学生 【一对多】
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('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');
INSERT INTO `student` (`id`, `name`, `tid`) VALUES('6', '小哥', '1');
10.1 测试环境搭建
- 导入lombok
- 新建实体类 Teacher、Student
- 建立Mapper 接口
- 建立Mapper.xml文件
- 在核心配置文件中绑定注册我们的Mapper接口或者文件!!【方式很多 随意挑选】
- 测试查询成功与否
10.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-->
<collection property="teacher" column="tid" javaType="teacher" select="getTeacher"/>
</resultMap>
<select id="getTeacher" resultType="teacher">
select * from teacher where id = #{id}
</select>
10.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>
<!--结果封装,将查询出来的列封装到对象属性中-->
<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"></result>
</association>
</resultMap>
10.4 Mysql多对一查询方式:
- 子查询 (按照查询嵌套)
- 联表查询 (按照结果嵌套)
11 一对多处理
比如:一个老师有多个学生!
对于老师而言,就是一对多的关系!
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> student;
}
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>
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="getStudent" column="id"/>
</resultMap>
<select id="getStudent" resultType="Student">
select * from mybatis.student where tid=#{tid};
</select>
小结:
- 关联 - association 【多对一】
- 集合 - collection 【对多】
- JavaType & ofType
- JavaType 用来指定实体类中属性的类型
- ofType 用来指定映射到List或者集合中的pojo类型,泛型中的约束类型
注意点:
- 尽量保证SQL的可读性,尽量保证通俗易懂
- 注意一对多、多对一中,属性名和字段问题!!
- 如果问题不好排除,可以使用日志~ 建议Log4j 【其实默认的也够用了】
- 避免慢SQL
面试:
- Mysql 引擎
- InnoDB底层原理
- 引擎
- 索引优化!
@[toc]
12 动态SQL
什么是动态SQL:动态SQL就是指根据不同的条件生成不同的SQL语句
利用动态SQL这一特性可以摆脱这种痛苦。
动态SQL元素和JSTL或基于类似XML的文本处理器相似。在Mybatis之前的版本中,有很多元素需要花时间了解。Mybatis 3大大精简了元素种类,现在只需要学习原来的一半的元素便可以了。Mybatis采用功能强大的基于OGNL的表达式来淘汰其他大部分元素
- if
- choose (when,otherwise)
- trim (where, set)
- foreach
12.1 搭建环境
CREATE TABLE `blog`(
`id` VARCHAR(50) NOT NULL COMMENT '博客',
`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
- 创建一个基础工程
- 导包
- 编写配置文件
- 编写实体类
- 编写实体类对应的Mapper接口和Mapper.xml文件
12.2 IF
<!--parameterType 输入类型
resultType 返回结果集
-->
<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>
12.3 choose (when,otherwise)
<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>
12.4 trim (where, set)
<!-- where标签 会去除多余的 “AND” 或 “OR”,或 "where" -->
<select id="queryBlogIF" parameterType="map" resultType="blog">
select * from mybatis.blog
<where>
<if test="title != null">
and title = #{title}
</if>
<if test="author != null">
and author = #{author}
</if>
</where>
</select>
<!-- set标签 会去除多余的 " 逗号",或 "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>
所谓的动态SQL,本质还是SQL语句,只是我们可以在SQL层面,去执行一个逻辑代码
if where set choose when
12.5 SQL片段
有的时候,我们可能会将一些功能的部分抽取出来,方便复用
使用SQL标签抽取公共部分
<sql id="sql-if-title-author">
<if test="title != null">
title = #{title}
</if>
<if test="author != null">
and author = #{author}
</if>
</sql>
在需要使用的地方使用Include标签引用即可
<!--parameterType 输入类型
resultType 返回结果集
-->
<select id="queryBlogIF" parameterType="map" resultType="blog">
select * from mybatis.blog
<where>
<include refid="sql-if-title-author"/>
</where>
</select>
注意事项:
最好基于单表定义SQL片段!! sql标签不要存在where标签 因为他是动态的
12.6 Foreach
select * from user where 1=1 and
<foreach item="id" collection="ids" open="(" separator="or" close=")">
#{id}
</foreach>
(id=1 or id=2 or id=3)
相当于遍历一个数组
<!--
集合 select * from user where 1=1 and (id=1 or id=2 or id=3)
我们现在传递一个万能的map,这map可以存在一个集合!
collection:集合 item:集合里的数据
-->
<select id="queryBlogForeach" parameterType="map" resultType="blog">
select * from mybatis.blog
<where>
<foreach item="id" collection="ids" open="and (" separator="or" close=")">
id=#{id}
</foreach>
</where>
</select>
动态SQL就是拼接SQL语句,我们只要保证SQL的正确性,按照SQL的格式,去排列组合就可以了
建议:
现在Mybatis中写出完整的SQL,再对应的去修改成为我们的动态SQL实现通用即可