Mybatis中實現了對數據庫中的數據進行封裝,那麼進行多表查詢時就會遇到查詢結果不只是一個對象的數據,有可能是多個對象的混合,可以使用<resultMap>
標籤進行映射
resultMap 標籤
在<select>
標籤中使用resultMap
可以完成與查詢結果進行映射
1.一對一關係association
一對一關係是指關係數據庫中兩個表之間的一種關係,該關係中第一個表中的單個行只可以與第二個表中的一個行相關,且第二個表中的一個行也只可以與第一個表中的一個行相關。
使用 resultMap
實現關聯單個對象,假設一位學生對應一個老師
多表聯查sql語句
實體類entity
Student.java
public class Student {
private String sname;
private String sid;
private Teacher teacher;
/*無參構造,有參構造,get/set方法,toString方法*/
}
Tips:在Student
類中有teacher
屬性,實現一對一關係
Teacher.java
public class Teacher {
private String tname;
private String id;
/*無參構造,有參構造,get/set方法,toString方法*/
}
Mapper映射
StudentMapper.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="Students">
<!-- 設計時儘量把屬性字段和數據庫字段設爲相同 -->
<!-- 查詢一條數據 -->
<select id="selectStudentById" parameterType="java.lang.String" resultMap="studentMap" >
SELECT
sid,
sname,
id,
tname
FROM
teacher t,
student s
WHERE
s.tid = t.id
AND s.sid = #{id}
</select>
<!-- 查詢多條數據 -->
<select id="selectStudents" resultMap="studentMap" >
SELECT
sid,
sname,
id,
tname
FROM
teacher t
INNER JOIN student s ON s.tid = t.id;
</select>
<resultMap type="Student" id="studentMap">
<!-- id 表示主鍵列 -->
<!-- property 對應java實體類中屬性名稱 -->
<!-- column 對應數據庫中列名 -->
<!-- association 表示一對一 -->
<id property="sid" column="sid" />
<result property="sname" column="sname" />
<!-- Teacher對象 -->
<association property="teacher" javaType="Teacher">
<id property="id" column="id" />
<result property="tname" column="tname" />
</association>
</resultMap>
</mapper>
測試
StudentTest.java
package com.zy.entity;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class StudentTest {
public static void main(String[] args) throws FileNotFoundException {
// 讀取配置文件
InputStream in = new FileInputStream("src/main/resources/mybatis.xml");
// 解析配置文件
SqlSessionFactory sf = new SqlSessionFactoryBuilder().build(in);
SqlSession session = sf.openSession();
Student s = session.selectOne("Students.selectStudentById", "1");
System.out.println("多表聯查返回一條數據:");
System.out.println(s);
List<Student> list = session.selectList("Students.selectStudents");
System.out.println("多表聯查返回多條數據-----list:");
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
}
}
2.一對多關係collection
一對多關係是關係數據庫中兩個表之間的一種關係,該關係中第一個表中的單個行可以與第二個表中的一個或多個行相關,但第二個表中的一個行只可以與第一個表中的一個行相關。
例如一個老師教授多個學生,那麼老師與學生的關係就是一對多
數據庫表還是teacher表與student表,數據不變
實體類entity
Teacher.java
public class Teacher {
private String tname;
private String id;
private List<Student> students;
/*無參構造,有參構造,get/set方法,toString方法*/
}
Tips:在Teacher實體類中多了一個List<Student>
學生集合屬性,來表示一個老師教授多個學生
Student.java
public class Student {
private String sname;
private String sid;
/*無參構造,有參構造,get/set方法,toString方法*/
}
Mapper映射
TeacherMapper.xml
這裏提供了兩種sql查詢方式,多表聯查和子查詢,查詢結果相同
<?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="Teachers">
<!-- 設計時儘量把屬性字段和數據庫字段設爲相同 -->
<!-- 多表聯查 -->
<select id="selectTeacherById" parameterType="java.lang.String"
resultMap="TeacherMap">
SELECT
id,
tname,
sid,
sname
FROM
teacher,
student
WHERE
teacher.id = student.tid and id = #{id}
</select>
<resultMap type="Teacher" id="TeacherMap">
<id property="id" column="id" />
<result property="tname" column="tname" />
<!-- ofType 關聯類型 -->
<!-- collection 一對多 -->
<collection property="students" ofType="Student">
<id property="sid" column="sid" />
<result property="sname" column="sname" />
</collection>
</resultMap>
<!-- 子查詢 -->
<select id="selectTeacherById1" parameterType="java.lang.String"
resultMap="TeacherMap1">
select * from teacher where id = #{id}
</select>
<resultMap type="Teacher" id="TeacherMap1">
<id property="id" column="id" />
<result property="tname" column="tname" />
<!-- ofType 關聯類型 -->
<!-- collection 一對多 -->
<collection property="students" ofType="Student"
column="id" select="selectStudent">
</collection>
</resultMap>
<select id="selectStudent" parameterType="java.lang.String"
resultType="Student">
select * from student where tid = #{id}
</select>
</mapper>
Tips:javaType
顧名思義就是表示這個屬性在java中所對應的類型,使用ofType
的原因是並沒有創建一個可以明確表示這個List<Student>
集合的類,也可以理解List<Student>
不能單純是一個Student
類型,使用ofType
表示屬性List<Student>
所關聯的java類是Student
類
測試
TeacherTest.java
package com.zy.entity;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class TeacherTest {
public static void main(String[] args) throws FileNotFoundException {
// 讀取配置文件
InputStream in = new FileInputStream("src/main/resources/mybatis.xml");
// 解析配置文件
SqlSessionFactory sf = new SqlSessionFactoryBuilder().build(in);
SqlSession session = sf.openSession();
System.out.println("多表聯查:");
Teacher t = session.selectOne("Teachers.selectTeacherById","1003");
System.out.println(t);
System.out.println("子查詢:");
Teacher t1 = session.selectOne("Teachers.selectTeacherById1","1003");
System.out.println(t1);
session.close();
}
}
3.多對多關係
多對多關係是關係數據庫中兩個表之間的一種關係, 該關係中第一個表中的一個行可以與第二個表中的一個或多個行相關。第二個表中的一個行也可以與第一個表中的一個或多個行相關。
Tips:要表示多對多關係,必須創建第三個表,該表通常稱爲聯接表,它將多對多關係劃分爲兩個一對多關係。將這兩個表的主鍵都插入到第三個表中,通過中間表將多對多拆分成兩個一對多
例如一個學生有多個老師,一個老師教授多個學生,那麼學生與老師的關係就是多對多
數據庫表在之前的基礎上稍作修改,加入第三張表stu_tea
實體類entity
Teacher.java
public class Teacher {
private String tname;
private String id;
private List<Student> students;
/*無參構造,有參構造,get/set方法,toString方法*/
}
Student.java
public class Student {
private String sname;
private String sid;
private String List<Teacher> teachers;
/*無參構造,有參構造,get/set方法,toString方法*/
}
Tips:爲表示多對多關係,在Student
類與Teacher
類中都加入了對應的List
集合
Mapper映射
StudentMapper.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="Students">
<!-- 設計時儘量把屬性字段和數據庫字段設爲相同 -->
<!-- 多表聯查 -->
<select id="selectStudentsById" parameterType="java.lang.String" resultMap="StudentMap">
SELECT
s.sid,
s.sname,
t.id,
t.tname
FROM
student_copy s,
teacher_copy t,
stu_tea st
WHERE
s.sid = st.sid
AND t.id = st.id
AND s.sid = #{id}
</select>
<resultMap type="Student" id="StudentMap">
<id property="sid" column="sid"/>
<result property="sname" column="sname"/>
<collection property="teachers" ofType="Teacher">
<id property="id" column="id"/>
<result property="tname" column="tname"/>
</collection>
</resultMap>
<!-- 子查詢 -->
<select id="selectStudentsById1" parameterType="java.lang.String" resultMap="StudentMap1">
select * from student_copy where sid = #{sid}
</select>
<resultMap type="Student" id="StudentMap1">
<id property="sid" column="sid"/>
<result property="sname" column="sname"/>
<collection property="teachers" column="sid" ofType="Teacher" select="selectTeachers"></collection>
</resultMap>
<select id="selectTeachers" parameterType="java.lang.String" resultType="Teacher">
SELECT
teacher_copy.id,
teacher_copy.tname
FROM
teacher_copy,
stu_tea
WHERE
stu_tea.id = teacher_copy.id
AND stu_tea.sid = #{sid}
</select>
</mapper>
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="Teachers">
<!-- 設計時儘量把屬性字段和數據庫字段設爲相同 -->
<!-- 多表聯查 -->
<select id="selectTeachersById" parameterType="java.lang.String" resultMap="TeacherMap">
SELECT
s.sid,
s.sname,
t.id,
t.tname
FROM
student_copy s,
teacher_copy t,
stu_tea st
WHERE
s.sid = st.sid
AND t.id = st.id
AND t.id = #{id}
</select>
<resultMap type="Teacher" id="TeacherMap">
<id property="id" column="id"/>
<result property="tname" column="tname"/>
<collection property="students" ofType="Student">
<id property="sid" column="sid"/>
<result property="sname" column="sname"/>
</collection>
</resultMap>
<!-- 子查詢 -->
<select id="selectTeachersById1" parameterType="java.lang.String" resultMap="TeacherMap1">
select * from teacher_copy where id = #{id}
</select>
<resultMap type="Teacher" id="TeacherMap1">
<id property="id" column="id"/>
<result property="tname" column="tname"/>
<collection property="students" ofType="Student" column="id" select="selectStudents"></collection>
</resultMap>
<select id="selectStudents" resultType="Student" parameterType="java.lang.String">
SELECT
student_copy.sid,
student_copy.sname
FROM
student_copy,
stu_tea
WHERE
stu_tea.sid = student_copy.sid
AND stu_tea.id = #{id}
</select>
</mapper>
Tips:將多對多拆分成兩個一對多,即有兩個mapper
映射,通過Student
查詢Teacher
,通過Teacher
查詢Student
,雙向的一對多查詢實現多對多關係
測試
StudentTest.java
package com.zy.entity;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class StudentTest {
public static void main(String[] args) throws FileNotFoundException {
// 讀取配置文件
InputStream in = new FileInputStream("src/main/resources/mybatis.xml");
// 解析配置文件
SqlSessionFactory sf = new SqlSessionFactoryBuilder().build(in);
SqlSession session = sf.openSession();
Student s = session.selectOne("Students.selectStudentsById","1");
System.out.println("多表聯查:");
System.out.println(s);
Student s1 = session.selectOne("Students.selectStudentsById1","1");
System.out.println("子查詢:");
System.out.println(s1);
session.close();
}
}
TeacherTest.java
package com.zy.entity;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class TeacherTest {
public static void main(String[] args) throws FileNotFoundException {
// 讀取配置文件
InputStream in = new FileInputStream("src/main/resources/mybatis.xml");
// 解析配置文件
SqlSessionFactory sf = new SqlSessionFactoryBuilder().build(in);
SqlSession session = sf.openSession();
Teacher t = session.selectOne("Teachers.selectTeachersById","1003");
System.out.println("多表聯查:");
System.out.println(t);
Teacher t1 = session.selectOne("Teachers.selectTeachersById1","1003");
System.out.println("子查詢:");
System.out.println(t1);
session.close();
}
}
Tips:爲了實現多對多關係,在Student
類與Teacher
類中都加入了對應的List
類型,導致查詢結果中出現null