mybatis想來大家不陌生吧,但是不知道大家對mybatis中的一對多瞭解嗎?
老生常談的話題,學生-老師關係:一個老師對應多個學生。首先建表t_student、t_teacher表(沒有用外鍵,之前一直以爲一對多、一對一必須要外鍵呢,然而並不需要,哈哈哈)
表對應的實體類關係t_student對應Student.class、t_teacher對應Teacher.class
package org.myself.pojo;
import java.io.Serializable;
/**
* Created by zhao_xinhu
* On 2018/8/30
* 學生實體類
*/
public class Student implements Serializable{
private String studentId;
private String studentName;
private Byte studentAge;
private Boolean studentSex;
public String getStudentId() {
return studentId;
}
public void setStudentId(String studentId) {
this.studentId = studentId;
}
public String getStudentName() {
return studentName;
}
public void setStudentName(String studentName) {
this.studentName = studentName;
}
public Byte getStudentAge() {
return studentAge;
}
public void setStudentAge(Byte studentAge) {
this.studentAge = studentAge;
}
public Boolean getStudentSex() {
return studentSex;
}
public void setStudentSex(Boolean studentSex) {
this.studentSex = studentSex;
}
public Student() {
}
public Student(String studentId, String studentName, Byte studentAge, Boolean studentSex) {
this.studentId = studentId;
this.studentName = studentName;
this.studentAge = studentAge;
this.studentSex = studentSex;
}
}
package org.myself.pojo;
import java.io.Serializable;
/**
* Created by zhao_xinhu
* On 2018/8/30
* 對應老師表
*/
public class Teacher implements Serializable {
private String teacherId;
private String teacherName;
private Boolean teacherSex;
private Byte teacherAge;
public String getTeacherId() {
return teacherId;
}
public void setTeacherId(String teacherId) {
this.teacherId = teacherId;
}
public String getTeacherName() {
return teacherName;
}
public void setTeacherName(String teacherName) {
this.teacherName = teacherName;
}
public Boolean getTeacherSex() {
return teacherSex;
}
public void setTeacherSex(Boolean teacherSex) {
this.teacherSex = teacherSex;
}
public Byte getTeacherAge() {
return teacherAge;
}
public void setTeacherAge(Byte teacherAge) {
this.teacherAge = teacherAge;
}
public Teacher() {
}
public Teacher(String teacherId, String teacherName, Boolean teacherSex, Byte teacherAge) {
this.teacherId = teacherId;
this.teacherName = teacherName;
this.teacherSex = teacherSex;
this.teacherAge = teacherAge;
}
}
有人發現我的實體類中沒有對應的關係(我習慣表單獨對應實體類),如果需要老師對應學生的我一般單獨封裝成下面這樣(純屬自己習慣):
package org.myself.object;
import org.myself.pojo.Student;
import org.myself.pojo.Teacher;
import java.io.Serializable;
import java.util.List;
/**
* Created by zhao_xinhu
* On 2018/8/30
* 老師(包含老師對應的多個學生)信息表
*/
public class TeacherStudentObj extends Teacher implements Serializable {
private List<Student> students;
public List<Student> getStudents() {
return students;
}
public void setStudents(List<Student> students) {
this.students = students;
}
}
只要是需要一對多關係的,就用單獨封裝的實體類,如果不需要一對多的,就用原始的pojo類。
下面是dao接口(隨便寫的兩個測試方法)
package org.myself.dao;
import org.apache.ibatis.annotations.Param;
import org.myself.object.TeacherStudentObj;
/**
* Created by zhao_xinhu
* On 2018/8/30
*/
public interface StudentDao {
//1)一對多
TeacherStudentObj getTeacherStudentObjByTeacherId(@Param(value = "teacherId") String teacherId);
//2)一對多
TeacherStudentObj getTeacherStudentById(@Param(value = "teacherId") String teacherId);
}
mapper纔是重點
1. 一對多不用select的方式:
<?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="org.myself.dao.StudentDao">
<resultMap id="teacherStudent" type="org.myself.object.TeacherStudentObj">
<id column="teacherId" property="teacherId" javaType="java.lang.String"></id>
<result column="teacherName" property="teacherName" javaType="java.lang.String"></result>
<result column="teacherSex" property="teacherSex" javaType="java.lang.Boolean"></result>
<result column="teacherAge" property="teacherAge" javaType="java.lang.Byte"></result>
<!-- 一對多collection中一定要用ofType -->
<collection property="students" ofType="org.myself.pojo.Student">
<id column="studentId" property="studentId" javaType="java.lang.String"></id>
<result column="studentName" property="studentName" javaType="java.lang.String"></result>
<result column="studentAge" property="studentAge" javaType="java.lang.Byte"></result>
<result column="studentSex" property="studentSex" javaType="java.lang.Boolean"></result>
</collection>
</resultMap>
<sql id="student">
${tableName}.student_id AS studentId,
${tableName}.student_name AS studentName,
${tableName}.student_age AS studentAge,
${tableName}.student_sex AS studentSex
</sql>
<sql id="teacher">
${tableName}.teacher_id AS teacherId,
${tableName}.teacher_name AS teacherName,
${tableName}.teacher_sex AS teacherSex,
${tableName}.teacher_age AS teacherAge
</sql>
<select id="getTeacherStudentObjByTeacherId" resultMap="teacherStudent">
SELECT <include refid="student"><property name="tableName" value="ts"></property></include>,
<include refid="teacher"><property name="tableName" value="tt"></property></include>
FROM t_student ts JOIN t_teacher tt
ON tt.teacher_id = #{teacherId} AND ts.teacher_id = tt.teacher_id
</select>
</mapper>
上面需要注意的地方就是collection中一定要用ofType,如果是association用javaType,至於ofType和javaType的區別自行百度,還有一個地方需要注意的,column和property的指向問題,property指的是實體類中的屬性名稱(這個毫無疑問),但是column有人搞不清楚,反正我總是搞暈,在這再聲明一遍,也使自己加深印象吧。column指的是你查詢之後的映射名稱(拿上你的sql去數據庫中執行一遍看看你查詢結果上顯示的字段沒錯就是他,並不是你表中的字段名)
我mapper文件的sql語句:
SELECT <include refid="student"><property name="tableName" value="ts"></property></include>,
<include refid="teacher"><property name="tableName" value="tt"></property></include>
FROM t_student ts JOIN t_teacher tt
ON tt.teacher_id = #{teacherId} AND ts.teacher_id = tt.teacher_id
拿上上面的sql語句,去數據庫執行之後的結果:
沒錯就是紅色標記中的名稱。
最後執行測試正常:
2. 一對多用select的方式:
mapper文件:
<?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="org.myself.dao.StudentDao">
<sql id="student2">
${tableName}.student_id,
${tableName}.student_name,
${tableName}.student_age,
${tableName}.student_sex
</sql>
<sql id="teacher2">
${tableName}.teacher_id,
${tableName}.teacher_name,
${tableName}.teacher_sex,
${tableName}.teacher_age
</sql>
<resultMap id="teacherStudent2" type="org.myself.object.TeacherStudentObj">
<id column="teacher_id" property="teacherId" javaType="java.lang.String"></id>
<result column="teacher_name" property="teacherName" javaType="java.lang.String"></result>
<result column="teacher_sex" property="teacherSex" javaType="java.lang.Boolean"></result>
<result column="teacher_age" property="teacherAge" javaType="java.lang.Byte"></result>
<collection property="students" column="teacher_id" select="getStudentByTeacherId" ofType="org.myself.pojo.Student">
</collection>
</resultMap>
<select id="getStudentByTeacherId" resultType="org.myself.pojo.Student">
SELECT <include refid="student2"><property name="tableName" value="ts"></property></include>
FROM t_student ts
WHERE ts.teacher_id = #{teacherId}
</select>
<select id="getTeacherStudentById" resultMap="teacherStudent2">
SELECT <include refid="teacher2"><property name="tableName" value="tt"></property></include>
FROM t_teacher tt
WHERE tt.teacher_id = #{teacherId}
</select>
</mapper>
大家有看到column不一樣了嗎?如果是這種column寫法的是因爲查詢沒有起別名,還是那句話(拿上你的sql去數據庫中執行一下,看看是什麼這個column填什麼就對了)。有人說collection中的column字段呢?一樣的,你查詢出來對應的是什麼就是什麼,你可以換成別的試試(這樣你是查不到student的,因爲你換成別的字段是沒有值的,所以關聯查詢也查不到數據)