MyBatis联合查询
1、联合查询简介
- 级联关系是一个数据库实体的概念,有 3 种级联关系,分别是一对一级联、一对多级联以及多对多级联。级联的优点是获取关联数据十分方便,但是级联过多会增加数据库系统的复杂度,同时降低系统的性能。 MyBatis提供了方便的一对一和多对多查询,而多对多查询可以由两个一对多查询组成。
2、级联属性查询数据
①使用级联属性查询数据之前,需要在mysql建立好所需的表,现在在mysql的User数据库里新建Student表(学生表)和Grade表(班级表),且逻辑是一个班级有多个学生,而一个学生只属于一个班级。
②根据https://perfectcode.top/2020/12/24/%E6%90%AD%E5%BB%BAMyBatis/#more新建一个MyBatis项目,并创建好数据库表对应的bean。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38public class Student {
private int sId;
private String sName;
private Grade grade;
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 Grade getGrade() {
return grade;
}
public void setGrade(Grade grade) {
this.grade = grade;
}
public String toString() {
return "Student{" +
"sId=" + sId +
", sName='" + sName + '\'' +
", grade=" + grade +
'}';
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38public class Grade {
private int gId;
private String gName;
private List<Student> students;
public int getgId() {
return gId;
}
public void setgId(int gId) {
this.gId = gId;
}
public String getgName() {
return gName;
}
public void setgName(String gName) {
this.gName = gName;
}
public List<Student> getStudents() {
return students;
}
public void setStudents(List<Student> students) {
this.students = students;
}
public String toString() {
return "Grade{" +
"gId=" + gId +
", gName='" + gName + '\'' +
", students=" + students +
'}';
}
}③新建StudentDao和StudentMapper.xml配置好查询语句,假设要根据学生id查找其所在班级信息:
1
2
3
4public interface StudentDao {
Student getStudentById(Integer sId);
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<mapper namespace="com.example.dao.StudentDao">
<resultMap id="myResultMap" type="com.example.bean.Student">
<id property="sId" column="s_id"/>
<result property="sName" column="s_name"/>
<result property="grade.gId" column="g_id"/>
<result property="grade.gName" column="g_name"/>
</resultMap>
<select id="getStudentById" resultMap="myResultMap">
select s.s_id, s.s_name, g.g_id, g.g_name
from student s
join grade g on g.g_id = s.g_id
where s.s_id = #{sId}
</select>
</mapper>④测试级联属性查询数据。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20public class MybatisTest {
public static void main(String[] args) throws IOException {
//1.根据全局配置文件创建一个sqlSessionFactory
//SqlSessionFactory是SqlSession工厂,负责创建SqlSession对象
//SqlSession:sql会话(代表和数据库的一次会话)
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2.获取和数据库的一次会话:getConnection()
SqlSession sqlSession = sqlSessionFactory.openSession();
//3.使用SqlSession操作数据库,先获取到dao接口实现
StudentDao mapper = sqlSession.getMapper(StudentDao.class);
//4.调用方法
Student studentById = mapper.getStudentById(1);
System.out.println(studentById);
}
}执行结果成功查询到id为1的学生的信息。
3、使用association查询数据
在 MyBatis 中可以通过
元素的子元素 处理一对一级联查询。在 元素中通常使用以下属性。 property:指定映射到实体类的对象属性。
column:指定表中对应的字段(即查询返回的列名)。
javaType:指定映射到实体对象属性的类型。
select:指定引入嵌套查询的子 SQL 语句,该属性用于关联映射中的嵌套查询。
①将上面用级联属性查询例子改成用
来进行一对一查询,此时的StudentMapper.xml内容如下,其它不变: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<mapper namespace="com.example.dao.StudentDao">
<resultMap id="myResultMap" type="com.example.bean.Student">
<id property="sId" column="s_id"/>
<result property="sName" column="s_name"/>
<association property="grade" javaType="com.example.bean.Grade">
<id property="gId" column="g_id"/>
<result property="gName" column="g_name"/>
</association>
</resultMap>
<select id="getStudentById" resultMap="myResultMap">
select s.s_id, s.s_name, g.g_id, g.g_name
from student s
join grade g on g.g_id = s.g_id
where s.s_id = #{sId}
</select>
</mapper>②测试后发现打印出同样的结果:
如果使用
的select属性,则将StudentMapper.xml改为: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<mapper namespace="com.example.dao.StudentDao">
<resultMap id="myResultMap" type="com.example.bean.Student">
<id property="sId" column="s_id"/>
<result property="sName" column="s_name"/>
<association property="grade" select="com.example.dao.GradeDao.getGradeByIdSimple"
column="g_id">
</association>
</resultMap>
<select id="getStudentById" resultMap="myResultMap">
select * from student where s_id = #{sId}
</select>
</mapper>同时需要新建GradeDao和GradeMapper.xml,内容分别如下:
1
2
3public interface GradeDao {
Grade getGradeByIdSimple(Integer gId);
}1
2
3
4
5
6
7
8
9
<mapper namespace="com.example.dao.GradeDao">
<select id="getGradeByIdSimple" resultType="com.example.bean.Grade">
select * from grade where g_id = #{gId}
</select>
</mapper>测试结果也一样:
4、使用collection查询数据
在 MyBatis 中可以通过
元素的子元素 处理一对多级联查询。 ①假设需要根据班级id查询所有的学生信息,此时需要用到
来进行一对多查询。此时的GradeDao和GradeMapper.xml内容如下: 1
2
3
4public interface GradeDao {
Grade getGradeById(Integer gId);
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<mapper namespace="com.example.dao.GradeDao">
<resultMap id="myResultMap" type="com.example.bean.Grade">
<id property="gId" column="g_id"/>
<result property="gName" column="g_name"/>
<collection property="students" ofType="com.example.bean.Student">
<id property="sId" column="s_id"/>
<result property="sName" column="s_name"/>
</collection>
</resultMap>
<select id="getGradeById" resultMap="myResultMap">
select g.g_id, g.g_name, s.s_id, s.s_name
from grade g
join student s on s.g_id = g.g_id
where g.g_id = #{gId}
</select>
</mapper>②测试类及测试结果如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20public class MybatisTest {
public static void main(String[] args) throws IOException {
//1.根据全局配置文件创建一个sqlSessionFactory
//SqlSessionFactory是SqlSession工厂,负责创建SqlSession对象
//SqlSession:sql会话(代表和数据库的一次会话)
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2.获取和数据库的一次会话:getConnection()
SqlSession sqlSession = sqlSessionFactory.openSession();
//3.使用SqlSession操作数据库,先获取到dao接口实现
GradeDao mapper = sqlSession.getMapper(GradeDao.class);
//4.调用方法
Grade gradeById = mapper.getGradeById(1);
System.out.println(gradeById);
}
}如果也是用select属性,则将GradeMapper.xml改为:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<mapper namespace="com.example.dao.GradeDao">
<resultMap id="myResultMap" type="com.example.bean.Grade">
<id property="gId" column="g_id"/>
<result property="gName" column="g_name"/>
<collection property="students" select="com.example.dao.StudentDao.getStudentsByGradeId"
column="g_id">
</collection>
</resultMap>
<select id="getGradeById" resultMap="myResultMap">
select * from grade where g_id = #{gId};
</select>
</mapper>同时StudentDao和StudentMapper.xml内容分别如下:
1
2
3public interface StudentDao {
List<Student> getStudentsByGradeId(Integer gId);
}1
2
3
4
5
6
7
8
9
<mapper namespace="com.example.dao.StudentDao">
<select id="getStudentsByGradeId" resultType="com.example.bean.Student">
select * from student where g_id = #{gId}
</select>
</mapper>测试结果为: