Mybatis实现多表查询的方式

2年前 (2022) 程序员胖胖胖虎阿
197 0 0

说到查询,就离不开结果映射(RusultMap),因为需要把查询的结果表,映射到实体类的属性上。mybatis提供了两种方式来实现:

第一种:SqlMapper.XML:

先实现动态代理,让Mybatis自动帮我们产生实现类,调取方法并返回结果。

<?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.apefruits.mapper.GoodsFruitsMapper">
</mapper>

实习动态代理有几个需要注意的点:

1.sqlMapper.xml文件要和接口名称一致,并存放在同一个包下

2.sqlMapper.xml种的namespace要指向接口的类路径;

3.SQL语句的id要和方法名相同

4.接口的入参类型要和sqlMapper.xml中parameterType的类型相同

5.接口的返回值类型要和sqlMapper.xml中定义的每个ResultType类型相同

在多表联查的情况下,由于返回结果存在别的表的字段,ResultType不能完全识别出属性,所以需要手动配置ResultMap,之后引用即可。

首先要分析表与表之间的关系:如学生和班级之间,一个学生对应一个班级  一个班级有多个学生,所以学生和班级就是一对一,班级和学生就是一对多。

为了阅读方便,省略了getset方法和构造器。

public class Banji {
	private int classid;
	private String classname;
	
	private List<Student> slist;//一对多
}
package com.ape.bean;

import java.util.Date;

public class Student {
private int sid;
private Date birthday;
private String sname;
private String ssex;
private int classid;
private Banji bj;//一对一
}

1对1的情况下:

<?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.ape.mapper.StudentMapper">
<resultMap type="Student" id="Stu_Cla_Map">
<result column="sid" property="sid"/>
<result column="birthday" property="birthday"/>
<result column="sname" property="sname"/>
<result column="ssex" property="ssex"/>
<result column="classid" property="classid"/>
<association property="bj">
<result column="classid" property="classid"/>
<result column="classname" property="classname"/>
</association>
</resultMap>
<select id="findStudentClass" resultMap="Stu_Cla_Map">
select * from student inner join class on student.classid=class.classid
</select>
</mapper>

多表联查时,所有属性必须全写,不写出来的结果映射不到对应属性上。

<resultMap>中 <association property="一对一属性名"> 然后下面的<result column="字段名"property="属性名">写对应一对一关系的另一张表的属性映射。

再看一对多的情况下:

<?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.ape.mapper.BanjiMapper">
<resultMap type="Banji" id="Cla_Stu_Map">
<result column="classid" property="classid"/>
<result column="classname" property="classname"/>

<collection property="slist"  ofType="Student">
<result column="sid" property="sid"/>
<result column="birthday" property="birthday"/>
<result column="sname" property="sname"/>
<result column="ssex" property="ssex"/>
<result column="classid" property="classid"/>
</collection>
</resultMap>
<select id="findBanjibyStudent" resultMap="Cla_Stu_Map">
select * from class inner join student on student.classid=class.classid
</select>
</mapper>

利用collection标签来设置一对多

<collection property="一对多的属性名"  ofType="集合内每个元素的类型">

后面再用<result column="字段名"property="属性名">写对应集合内原来类型关系的属性映射。

第二种方式就是:注解方式

需要注意的是注解中只有单表查询。

首先来说一对一:

@Result(column = "关联的字段",property = "需要映射的属性名" ,one=@One(select =“能得到属性对象的字符串"))

@Results(id = "S_C_Map" ,value = {
		//@Result(column = "sid",property = "sid"),
		//@Result(column = "birthday",property = "birthday"),
		//@Result(column = "sname",property = "sname"),
		//@Result(column = "ssex",property = "ssex"),
		@Result(column = "classid",property = "classid"),
		@Result(column = "classid",property = "bj",one = @One(select="com.ape.mapper.BanjiMapper.findAllBanji"))
})
@Select("select * from student")
List<Student> findStudentClass();
@Select("select * from class where classid=#{v}")
Banji findAllBanji(int classid);

 由于注解方式sql语句只能写单表查询,所以学生的属性和数据库对应的字段可以不写。但需要注意的是,班级id要写,因为我们通过One=@One(select="能得到属性对象的字符串")的把得到学生表离的classid传到班级那边的sql语句了,所以得到学生表里的classid是默认值,班级表里classid是正常的。所以上面必须再手动设置映射一下,得到的结果就是学生表里是正常的classid,班级表也是。

Mybatis实现多表查询的方式

结果如下:

Mybatis实现多表查询的方式

 

一对多和一对一的方式一样只是使用的注解不同:

 @Result(column = "关联的字段",property = "需要映射的属性名" ,@Many(select="通过字符反射得到的集合对象"))

@Results(value = {
@Result(column = "classid",property ="classid" ),
@Result(column = "classid",property ="slist" ,many = @Many(select = "com.ape.mapper.StudentMapper.findStudentbyclassid"))
})
@Select("select * from class ")
List<Banji> findBanjiandStudent();
@Select("select * from student where classid=#{v}")
List<Student> findStudentbyclassid(int classid);

结果如下:

Mybatis实现多表查询的方式

 

 在表关系中还存在多对多的关系:

再多表联查时,最好不要超过三层结构:比如:学生有课程,课程里有成绩

需要我们转换思维找到他们之间的中间表,利用中间表查询就可以得到我们想要的结果了:比如学生和课程。

一个学生有多门课,一门课有很多学生。

但是我们可以找到考试成绩。

从考试成绩来看,一门成绩对应一个课程和一个学生。

核心代码和结果如下:

创建联查映射关系

@Results({
	@Result(column = "sid",property = "sid"),
	@Result(column = "cid",property = "cid"),
	@Result(column = "sid",property = "stu",one = @One(select = "com.ape.mapper.StudentMapper.findStudentbysid")),
	@Result(column = "cid",property = "cou",one=@One(select="com.ape.mapper.CourseMapper.findCourseByCid"))
	
})
@Select("select * from sc")	
public List<Sc> findScAll();

 写出学生表和成绩表的联查

@Select("select * from student where sid=#{v}")
List<Student> findStudentbysid(int sid);

  写出课程表和成绩表的联查

@Select("select * from course where cid=#{v}")
public Course findCourseByCid(int cid);

Mybatis实现多表查询的方式

 得出结果:

Mybatis实现多表查询的方式 

 

版权声明:程序员胖胖胖虎阿 发表于 2022年9月18日 下午12:24。
转载请注明:Mybatis实现多表查询的方式 | 胖虎的工具箱-编程导航

相关文章

暂无评论

暂无评论...