〇、附
1、自定义一个工具类,用于获取sqlSession
package com.hbw.util;
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 java.io.IOException;
import java.io.InputStream;
public class SqlSessionUtil {
//读取核心配置文件
static InputStream inputStream;
//构建SqlSessionFactory
static SqlSessionFactory sqlSessionFactory;
static{
try {
inputStream = Resources.getResourceAsStream("mybatiesConfig.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession();
}
}
Ⅰ、一对一
一对一使用,association标签property bean中属性名称;javaType返回值类型。
表关系:一个学生一辆自行车。不要设置外键,不好维护。
学生表
学生实体类Student.java
package com.hbw.bean;
import java.io.Serializable;
public class Student implements Serializable {
private int sid;
private String sname;
private int sage;
private String ssex;
private String semail;
private Bicycle bicycle;
public int getSid() {
return sid;
}
public void setSid(int sid) {
this.sid = sid;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public int getSage() {
return sage;
}
public void setSage(int sage) {
this.sage = sage;
}
public String getSsex() {
return ssex;
}
public void setSsex(String ssex) {
this.ssex = ssex;
}
public String getSemail() {
return semail;
}
public void setSemail(String semail) {
this.semail = semail;
}
public Bicycle getBicycle() {
return bicycle;
}
public void setBicycle(Bicycle bicycle) {
this.bicycle = bicycle;
}
@Override
public String toString() {
return "Student{" +
"sid=" + sid +
", sname='" + sname + '\'' +
", sage=" + sage +
", ssex='" + ssex + '\'' +
", semail='" + semail + '\'' +
", bicycle=" + bicycle +
'}';
}
}
自行车表
自行车实体类Bicycle.java
package com.hbw.bean;
import java.io.Serializable;
public class Bicycle implements Serializable {
private int bid;
private String bname;
private double bprice;
public int getBid() {
return bid;
}
public void setBid(int bid) {
this.bid = bid;
}
public String getBname() {
return bname;
}
public void setBname(String bname) {
this.bname = bname;
}
public double getBprice() {
return bprice;
}
public void setBprice(double bprice) {
this.bprice = bprice;
}
@Override
public String toString() {
return "Bicycle{" +
"bid=" + bid +
", bname='" + bname + '\'' +
", bprice=" + bprice +
'}';
}
}
一、嵌套结果集(连接查询)
因为是连接查询,所以sql语句比较复杂,但是步骤较少。数据库学得好的推荐这类
原理:左外连接查询学生信息和自行车信息,通过共同字段sid联系起来。
这里,展示全部代码信息,后面的其他方式中,直接补充新增加的内容。
1、dao层接口StudentDao.java
package com.hbw.dao;
import com.hbw.bean.Student;
public interface StudentDao {
/**
* 通过学生id查询学生信息和学生的自行车的信息,,嵌套结果集
*/
public Student getStudentBicycleByid(int sid);
}
2、映射文件StudentMapperDao.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="com.hbw.dao.StudentDao">
<!--通过学生id查询学生信息和学生用于的自行车的信息,,嵌套结果集-->
<resultMap id="studentBicycle" type="student">
<id column="sid" property="sid"></id>
<result column="sname" property="sname"></result>
<result column="sage" property="sage"></result>
<result column="ssex" property="ssex"></result>
<result column="semail" property="semail"></result>
<!--一对一使用,association标签-->
<!--property bean中属性名称;javaType返回值类型-->
<association property="bicycle" javaType="bicycle">
<id column="bid" property="bid"></id>
<result column="bname" property="bname"></result>
<result column="bprice" property="bprice"></result>
</association>
</resultMap>
<select id="getStudentBicycleByid" resultMap="studentBicycle">
SELECT s.sid,s.sname,s.sage,s.ssex,s.semail,b.bid,b.bname,b.bprice
FROM student s LEFT JOIN bicycle b ON s.sid=b.sid
WHERE s.sid=#{sid};
</select>
</mapper>
3、测试StudentUtil.java
import com.hbw.bean.Student;
import com.hbw.dao.StudentDao;
import com.hbw.util.SqlSessionUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class StudentUtil {
private SqlSession sqlSession;
private StudentDao sd;
@Before
public void before(){
sqlSession = SqlSessionUtil.getSqlSession();
sd = sqlSession.getMapper(StudentDao.class);
}
@After
public void after(){
sqlSession.commit();
sqlSession.close();
}
/**
* 测试一对一关系,嵌套结果集
*/
@Test
public void test2(){
Student stu = sd.getStudentBicycleByid(17);
System.out.println(stu);
}
}
4、结果
Student{sid=17, sname=‘张三’, sage=17, ssex=‘男’, semail=‘110@qq.com’, bicycle=Bicycle{bid=1, bname=‘FRW 辐轮王’, bprice=1200.0}}
二、嵌套查询(子查询)
因为是多次查询,所以比较繁杂,但是sql语句简单。
原理:第一次查询学生信息,再通过学生id查询自行车信息
1、在StudentDao.java中新增内容
/**
* 通过学生id查询学生信息和学生的自行车的信息,,嵌套查询
*/
public Student getStudentBicycleByid2(int sid);
2、在StudentMapperDao.xml中新增内容
<!--通过学生id查询学生信息和学生用于的自行车的信息,嵌套查询-->
<resultMap id="studentBicycle2" type="student">
<id column="sid" property="sid"></id>
<result column="sname" property="sname"></result>
<result column="sage" property="sage"></result>
<result column="ssex" property="ssex"></result>
<result column="semail" property="semail"></result>
<!--一对一使用,association标签-->
<!--property bean中属性名称;column第二次查询的入参;select再次查询-->
<association property="bicycle" column="sid" select="com.hbw.dao.BicycleDao.getBicycleById"></association>
</resultMap>
<select id="getStudentBicycleByid2" resultMap="studentBicycle2">
select sid,sname,sage,ssex,semail from student where sid=#{sid}
</select>
3、新建BicycleMapper.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="com.hbw.dao.BicycleDao">
<select id="getBicycleById" resultType="bicycle">
select bid,bname,bprice from bicycle where sid=#{sid}
</select>
</mapper>
4、在StudentUtil.java中新增内容
/**
* 测试一对一关系,嵌套查询
*/
@Test
public void test3(){
Student stu = sd.getStudentBicycleByid2(17);
System.out.println(stu);
}
5、结果
Ⅱ、一对多
collection标签关联一对多关系表查询;oftype属性指定集合中自定义的类(查询的多条数据封装在集合中的类型)
表关系:一个学生有多位任课老师
老师表
老师表实体类Teacher.java
package com.hbw.bean;
import java.io.Serializable;
public class Teacher implements Serializable {
private int tid;
private String tname;
private double twages;
public int getTid() {
return tid;
}
public void setTid(int tid) {
this.tid = tid;
}
public String getTname() {
return tname;
}
public void setTname(String tname) {
this.tname = tname;
}
public double getTwages() {
return twages;
}
public void setTwages(double twages) {
this.twages = twages;
}
@Override
public String toString() {
return "Teacher{" +
"tid=" + tid +
", tname='" + tname + '\'' +
", twages=" + twages +
'}';
}
}
修改学生表Student.java
一、嵌套结果集
1、在StudentDao.java中新增内容
/*一对多通过学生id查询学生信息,还有他的任课老师的信息,嵌套结果集*/
public Student getStudentTeacherById(int sid);
2、在StudentMapperDao.xml中新增内容
<!--一对多通过学生id查询学生信息,还有他的任课老师的信息,嵌套结果集-->
<resultMap id="studentTeacher" type="student">
<id column="sid" property="sid"></id>
<result column="sname" property="sname"></result>
<result column="sage" property="sage"></result>
<result column="ssex" property="ssex"></result>
<result column="semail" property="semail"></result>
<!--collection是对应一对多关系的标签;property:Student实体类中的属性名;ofType:返回值类型(主配置文件去了别名)-->
<collection property="teacherList" ofType="teacher">
<id column="tid" property="tid"></id>
<result column="tname" property="tname"></result>
<result column="twages" property="twages"></result>
</collection>
</resultMap>
<select id="getStudentTeacherById" resultMap="studentTeacher">
SELECT s.sid,s.sname,s.sage,s.ssex,s.semail,t.tid,t.tname,t.twages
FROM student s LEFT JOIN teacher t ON s.sid=t.sid
WHERE s.sid=#{sid};
</select>
3、在StudentUtil.java中新增内容
/*通过学生id获取学生信息,并获取他的任课老师,嵌套结果集*/
@Test
public void test4(){
Student stu = sd.getStudentTeacherById(17);
System.out.println(stu);
}
4、结果
二、嵌套查询
1、在StudentDao.java中新增内容
/*一对多通过学生id查询学生信息,还有他的任课老师的信息,嵌套查询*/
public Student getStudentTeacherById2(int sid);
2、在StudentMapperDao.xml中新增内容
<!--一对多通过学生id查询学生信息,还有他的任课老师的信息,嵌套结果集-->
<resultMap id="studentTeacher2" type="student">
<id column="sid" property="sid"></id>
<result column="sname" property="sname"></result>
<result column="sage" property="sage"></result>
<result column="ssex" property="ssex"></result>
<result column="semail" property="semail"></result>
<!--collection是对应一对多关系的标签;property:Student实体类中的属性名;ofType:返回值类型(主配置文件去了别名)-->
<collection property="teacherList" column="sid" select="com.hbw.dao.TeacherDao.getTeacherById"></collection>
</resultMap>
<select id="getStudentTeacherById2" resultMap="studentTeacher2">
SELECT sid,sname,sage,ssex,semail FROM student WHERE sid=#{sid};
</select>
3、新建TeacherMapper.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="com.hbw.dao.TeacherDao">
<!--一对多,通过sid'查到tacher的信息-->
<select id="getTeacherById" resultType="teacher">
select tid,tname,twages from teacher where sid=#{sid}
</select>
</mapper>
4、在StudentUtil.java中新增内容
/*通过学生id获取学生信息,并获取他的任课老师,嵌套查询*/
@Test
public void test5(){
Student stu = sd.getStudentTeacherById2(17);
System.out.println(stu);
}
5、结果
Ⅲ、多对多
表关系:一个学生多位老师,每位老师多门课程,中间用课程表来连接
课程种类表course
课程表timeable
比如,一号老师(张老师)教1、2、3号课程(语数外)
课程表实体类Course
package com.hbw.bean;
import java.io.Serializable;
public class Course implements Serializable {
private int cid;
private String cname;
public int getCid() {
return cid;
}
public void setCid(int cid) {
this.cid = cid;
}
public String getCname() {
return cname;
}
public void setCname(String cname) {
this.cname = cname;
}
@Override
public String toString() {
return "Course{" +
"cid=" + cid +
", cname='" + cname + '\'' +
'}';
}
}
修改实体类Teacher.java
一、嵌套结果集
1、在StudentDao.java中新增内容
/*多对多通过学生id查找学生信息、老师信息,再通过老师的tid查找老师的课程,嵌套结果集*/
public Student getStudentTeacherCourseById(int sid);
2、在StudentMapperDao.xml中新增内容
<!--多对多通过学生id查找学生信息、老师信息,再通过老师的tid查找老师的课程,嵌套结果集-->
<resultMap id="studentTeacherCourse" type="student">
<id column="sid" property="sid"></id>
<result column="sname" property="sname"></result>
<result column="sage" property="sage"></result>
<result column="ssex" property="ssex"></result>
<result column="semail" property="semail"></result>
<!--collection多对多关系也使用这个标签(单向看其实也就是一对多的关系),property实体类中属性名;ofType返回值类型-->
<collection property="teacherList" ofType="teacher">
<id column="tid" property="tid"></id>
<result column="tname" property="tname"></result>
<result column="twages" property="twages"></result>
<collection property="courseList" ofType="course">
<id column="cid" property="cid"></id>
<result column="cname" property="cname"></result>
</collection>
</collection>
</resultMap>
<select id="getStudentTeacherCourseById" resultMap="studentTeacherCourse">
SELECT s.sid,s.sname,s.sage,s.ssex,s.semail,t.tid,t.tname,t.twages,c.cid,c.cname
FROM student s LEFT JOIN teacher t ON s.sid=t.sid
LEFT JOIN timetable tt ON t.tid=tt.tid
LEFT JOIN course c ON tt.cid=c.cid
WHERE s.sid=#{sid};
</select>
3、在StudentUtil.java中新增内容
/*多对多,嵌套查询*/
@Test
public void test6(){
Student stu = sd.getStudentTeacherCourseById(17);
System.out.println(stu);
}
4、结果
17号张三同学的任课老师有张老师、李老师、王老师;
张老师教了语数外;
李老师教了体育;
王老师教了物理
二、嵌套查询
1、在StudentDao.java新增内容
/*多对多通过学生id查找学生信息、老师信息,再通过老师的tid查找老师的课程,嵌套查询*/
public Student getStudentTeacherCourseById2(int sid);
2、在StudentMapperDao.xml新增内容
第一次查询
<!--多对多通过学生id查找学生信息、老师信息,再通过老师的tid查找老师的课程,嵌套查询-->
<resultMap id="studentTeacherCourse2" type="student">
<id column="sid" property="sid"></id>
<result column="sname" property="sname"></result>
<result column="sage" property="sage"></result>
<result column="ssex" property="ssex"></result>
<result column="semail" property="semail"></result>
<!--collection多对多关系也使用这个标签(单向看其实也就是一对多的关系),property实体类中属性名;ofType返回值类型-->
<collection property="teacherList" column="sid" select="com.hbw.dao.TeacherDao.getTeacherByIds"></collection>
</resultMap>
<select id="getStudentTeacherCourseById2" resultMap="studentTeacherCourse2">
SELECT s.sid,s.sname,s.sage,s.ssex,s.semail FROM student s WHERE s.sid=#{sid};
</select>
3、在TeacherMapper.xml新增内容
第二次查询
<!--多对多,通过sid'查到tacher的信息-->
<resultMap id="teachers" type="teacher">
<id column="tid" property="tid"></id>
<result column="tname" property="tname"></result>
<result column="twages" property="twages"></result>
<collection property="courseList" column="tid" select="com.hbw.dao.Course.getCourseById"></collection>
</resultMap>
<select id="getTeacherByIds" resultMap="teachers">
select tid,tname,twages from teacher where sid=#{sid}
</select>
4、新建CourseMapper.xml
第三次查询。使用tid,通过中间表timetable查询课程信息
<?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.hbw.dao.Course">
<select id="getCourseById" resultType="course">
SELECT c.cid,c.cname
FROM course c LEFT JOIN timetable tt ON c.cid=tt.cid
WHERE tid=#{tid};
</select>
</mapper>
5、在StudentUtil.java中新增内容
/*多对多,嵌套查询*/
@Test
public void test7(){
Student stu = sd.getStudentTeacherCourseById2(17);
System.out.println(stu);
}
6、结果
总结 0
1、嵌套结果集与嵌套查询
嵌套结果集:连接查询,sql语句复杂,步骤少
嵌套查询操作:多次查询,sql语句简单,步骤多
2、一对一
1)嵌套结果集。
使用association标签,其中property属性表示bean中成员名称;javaType属性表示返回值类型(一般是实体类全类名,这里批量取别名了)
<association property="bicycle" javaType="bicycle">
<id column="bid" property="bid"></id>
<result column="bname" property="bname"></result>
<result column="bprice" property="bprice"></result>
</association>
2)嵌套查询
使用association标签,其中property属性表示bean中成员名称;column属性表示再次查询的入参;select再次查询的路径
<association property="bicycle" column="sid" select="com.hbw.dao.BicycleDao.getBicycleById"></association>
3、一对多、多对多(单向看也是一对多)
1)嵌套结果集
使用collection标签,其中property属性表示实体类中的成员变量名(一般都是集合);ofType属性表示返回值类型(一般是实体类全限定名称,这里批量取别名了)
<collection property="teacherList" ofType="teacher">
<id column="tid" property="tid"></id>
<result column="tname" property="tname"></result>
<result column="twages" property="twages"></result>
</collection>
2)嵌套查询
使用collection标签,其中property属性表示实体类中的成员变量名(一般都是集合);column表示再次查询的入参;select表示再次查询的路径
<collection property="teacherList" column="sid" select="com.hbw.dao.TeacherDao.getTeacherById"></collection>
4、查询多表时,返回值类型只能使用ResultMap
5、注意:每新增一个映射配置文件,都需要在主配置文件的mappers(映射器)中添加mapper映射路径
<!--resource就是主程序配置文件夹Resources-->
<mappers>
<mapper resource="AMapper.xml"/>
<mapper resource="BMapper.xml"/>
</mappers>
疑惑
dao层接口如何找到mapper配置文件中对应的查询语句
👉Mybatis(上)——简介、入门案例、主配置文件、映射配置文件、基于接口操作数据库、模糊查询、参数传递、执行原理
👉mybatis(下)——<![CDATA[…]]>、动态sql语句详解、懒加载、缓存、逆向工程、纯注解操作数据库