大纲
Auto Mapping 单表实现(别名方式)
<resultMap>
实现单表配置
单个对象关联查询(N+1,外连接)
集合对象关联查询
注解开发
MyBatis 运行原理
准备:创建数据库
- 创建表、录入测试数据
-- 教师表
create table teacher(
id int(10) primary key auto_increment,
name varchar(20)
);
insert into teacher values(default,'鱼老师');
insert into teacher values(default,'绿老师');
insert into teacher values(default,'酸老师');
insert into teacher values(default,'魔老师');
-- 学生表:tid含有外键约束
create table student(
id int(10) primary key auto_increment,
name varchar(20),
age int(3),
tid int(10),
constraint fk_teacher foreign key (tid) REFERENCES teacher(id)
);
insert into student values(default,'学生1',25,1);
insert into student values(default,'学生2',28,1);
insert into student values(default,'学生3',24,3);
insert into student values(default,'学生4',24,3);
insert into student values(default,'学生5',26,2);
insert into student values(default,'学生6',25,2);
insert into student values(default,'学生7',28,4);
insert into student values(default,'学生8',21,4);
insert into student values(default,'学生9',21,1);
insert into student values(default,'学生10',22,1);
insert into student values(default,'学生11',27,1);
创建结果(学生表、教师表)
2. 模糊查询语法where 列 like '%内容%'
select * from student,teacher where student.name like '%学生%' and tid in (select id from teacher where name like '%鱼%') and tid=teacher.id;
查询结果:
课上笔记
使用JQuery
关于字符编码:tomcat默认使用iso-8859-1,网页中使用utf-8,所以会导致中文乱码。
在实际开发中,不要去修改tomcat的全局配置,会误伤到别人的项目。只能修改自己项目中的编码方式。如下:
一、MyBatis 实现多表查询
- Mybatis 实现多表查询方式
1.1 业务装配.对两个表编写单表查询语句,在业务(Service)把查询的两个结果进行关联.
1.2 使用Auto Mapping 特性,在实现两表联合查询时通过别名完成映射.
1.3 使用MyBatis 的<resultMap>
标签进行实现. - 多表查询时,类中包含另一个类的对象的分类
2.1 单个对象
2.2 集合对象.
二、resultMap 标签
<resultMap>
标签写在mapper.xml 中,由程序员控制SQL 查询结果与实体类的映射关系.
1.1 默认MyBatis 使用Auto Mapping 特性.- 使用
<resultMap>
标签时,<select>
标签不写 resultType 属性,而是使用 resultMap 属性引用<resultMap>
标签. - 使用resultMap 实现单表映射关系
3.1 数据库设计
3.2 实体类设计
public class Teacher{
private int id1;
private String name1;
}
3.3 mapper.xml 代码
<resultMap type="teacher" id="mymap">
<!-- 主键使用id 标签配置映射关系-->
<id column="id" property="id1" />
<!-- 其他列使用result 标签配置映射关系-->
<result column="name" property="name1"/>
</resultMap>
<select id="selAll" resultMap="mymap">
select * from teacher
</select>
4. 使用resultMap
实现关联单个对象(N+1 方式)
4.1 N+1 查询方式,先查询出某个表的全部信息,根据这个表的信息查询另一个表的信息.
4.2 与业务装配的区别:
4.3.1 在 service 里面写的代码,由 mybatis 完成装配
4.3 实现步骤:
4.3.1 在 Student 实现类中包含了一个Teacher 对象
public class Student {
private int id;
private String name;
private int age;
private int tid;
private Teacher teacher;
...
4.3.2 在TeacherMapper 中提供一个查询
<select id="selById" resultType="teacher" parameterType="int">
select * from teacher where id=#{0}
</select>
4.3.3 在StudentMapper 中
4.3.3.1 <association>
装配一个对象时使用
4.3.3.2 property: 对象在类中的属性名
4.3.3.3 select:通过哪个查询查询出这个对象的信息
4.3.3.4 column: 把当前表的哪个列的值做为参数传递给另一个查询
4.3.3.5 大前提使用N+1 方式.时如果列名和属性名相同可以不配置,使用Auto mapping 特性.但是mybatis 默认只会给列
专配一次
5. 使用resultMap 实现关联单个对象(联合查询方式)
5.1 只需要编写一个SQL,在StudentMapper 中添加下面效果
5.1.1 只要专配一个对象就用这个标签
5.1.2 此时把<association/>
小的<resultMap>
看待
5.1.3 javaType 属性:<association/>
专配完后返回一个什么类型的对象.取值是一个类(或类的别名)
<?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.bjsxt.mapper.StudentMapper">
<resultMap type="Student" id="stuMap">
<result column="tid" property="tid"/>
<!-- 如果关联一个对象 -->
<association property="teacher" select="com.bjsxt.mapper.TeacherMapper.selById" column="tid"></association>
</resultMap>
<select id="selAll" resultMap="stuMap">
select * from student
</select>
<resultMap type="Student" id="stuMap1">
<!-- column是数据库查询语句起的别名,property是javabean对象属性名称.id是主键,result是普通键 -->
<id column="sid" property="id"/>
<result column="sname" property="name"/>
<result column="age" property="age"/>
<result column="tid" property="tid"/>
<association property="teacher" javaType="Teacher" >
<id column="tid" property="id"/>
<result column="tname" property="name"/>
</association>
</resultMap>
<select id="selAll1" resultMap="stuMap1">
select s.id sid,s.name sname,age age,t.id tid,t.name tname FROM student s left outer join teacher t on s.tid=t.id
</select>
</mapper>
test.java
package com.bjsxt.test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import com.bjsxt.pojo.Student;
public class Test {
public static void main(String[] args) throws IOException {
InputStream is = Resources.getResourceAsStream("mybatis.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
SqlSession session = factory.openSession();
List<Student> list = session.selectList("com.bjsxt.mapper.StudentMapper.selAll");
System.out.println(list);
List<Student> list1 = session.selectList("com.bjsxt.mapper.StudentMapper.selAll1");
System.out.println(list1);
session.close();
System.out.println("程序执行结束");
}
}
- N+1 方式和联合查询方式对比
6.1 N+1:需求不确定时.
6.2 联合查询:需求中确定查询时两个表一定都查询. - N+1 名称由来
7.1 举例:学生中有3 条数据
7.2 需求:查询所有学生信息级授课老师信息
7.3 需要执行的SQL 命令
7.3.1 查询全部学生信息:select * from 学生
7.3.2 执行3 遍select * from 老师where id=学生的外键
7.4 使用多条SQl 命令查询两表数据时,如果希望把需要的数据都查询出来,需要执行N+1 条SQl 才能把所有数据库查询出来.
7.5 缺点:
7.5.1 效率低
7.6 优点:
7.6.1 如果有的时候不需要查询学生是同时查询老师.只需要执行一个select * from student;
7.7 适用场景: 有的时候需要查询学生同时查询老师,有的时候只需要查询学生.
7.8 如果解决N+1 查询带来的效率低的问题
7.8.1 默认带的前提: 每次都是两个都查询.
7.8.2 使用两表联合查询.
三.使用查询关联集合对象(N+1)
- 在Teacher 中添加
List<Student>
public class Teacher {
private int id;
private String name;
private List<Student> list;
- 在StudentMapper.xml 中添加通过 tid 查询
<select id="selByTid" parameterType="int" resultType="student">
select * from student where tid=#{0}
</select>
- 在TeacherMapper.xml 中添加查询全部
3.1<collection/>
当属性是集合类型时使用的标签.
<resultMap type="teacher" id="mymap">
<id column="id" property="id"/>
<result column="name" property="name"/>
<collection property="list" select="com.bjsxt.mapper.StudentMapper.selByTid" column="id"></collection>
</resultMap>
<select id="selAll" resultMap="mymap">
select * from teacher
</select>