MyBatis多表關聯(lián)查詢的實現(xiàn)示例
一對多查詢
一對多關聯(lián)查詢是指在查詢一方對象的時候,同時將其所關聯(lián)的多方對象也都查詢出來。下面以班級 Classes 與學生 Student 間的一對多關系為例進行演示。一個班級有多個學生,一個學生只屬于一個班級。數(shù)據(jù)庫 student 表里面有個字段 classno 是外鍵,對應主鍵表 Class 的主鍵 cid。
項目案例:查詢班級號為 1801 的班級,同時遍歷該班級的所有的學生信息
實現(xiàn)步驟:
【1】在 MySQL 中創(chuàng)建數(shù)據(jù)庫 studentdb,創(chuàng)建表 student 和classes,并添加若干測試用的數(shù)據(jù)記錄,SQL 語句如下:
CREATE DATABASE studentdb; USE studentdb ; DROP TABLE IF EXISTS student ; CREATE TABLE student ( id INT(11) NOT NULL, studentname VARCHAR(20) DEFAULT NULL, gender CHAR(2) DEFAULT NULL, age INT(11) DEFAULT NULL, classno VARCHAR(10), PRIMARY KEY ( id ) ) INSERT INTO student ( id , studentname , gender , age , classno ) VALUES (1,'張飛','男',18,'201801'),(2,'李白','男',20,'201801'),(3,'張無忌','男',19,'201801'),(4,'趙敏','女',17,'201801'); CREATE TABLE classes ( cid VARCHAR (30), cname VARCHAR (60) ); INSERT INTO classes (cid, cname) VALUES('201801','計算機軟件1班'); INSERT INTO classes (cid, cname) VALUES('201802','計算機軟件2班');
【2】創(chuàng)建實體類 Classes 和 Student 類
Student 類如下:
package cn.kgc.my01.entity; import lombok.Data; @Data public class Student { private String sid; private String sname; private String sex; private Integer age; //添加額外屬性:所在班級 private Classes classes; public String show(){ return "學生編號:"+getSid()+",學生姓名:"+getSname()+",學生性別:"+getSex()+",學生年齡:"+getAge(); } }
Classes 類如下:
package cn.kgc.my01.entity; import lombok.Data; import java.util.List; @Data public class Classes { private String cid; private String cname; //添加額外屬性 private List<Student> students; public String show(){ return "班級編號:"+getCid()+",班級名稱:"+getCname()+",班級學生:"; } }
【3】創(chuàng)建 ClassesMapper.java 接口,并添加 findClassesById 方法
package cn.kgc.my01.mapper; import cn.kgc.my01.entity.Classes; public interface ClassesMapper { Classes findClassesById(String id); }
【4】創(chuàng)建 ClassesMapper.xml 映射文件,有以下兩種方式:
方式一:多表連接查詢方式
這種方式只用到1條 SQL 語句,代碼如下所示:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "https://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="cn.kgc.my01.mapper.ClassesMapper"> <!--方式一:多表連接查詢方式,只用到 1條SQL語句--> <resultMap id="classResultMap" type="classes"> <id property="cid" column="cid"/> <result property="cname" column="cname"/> <!--關聯(lián)屬性的映射關系--> <collection property="students" ofType="Student"> <id property="sid" column="id"/> <result property="sname" column="studentname"/> <result property="sex" column="gender"/> <result property="age" column="age"/> </collection> </resultMap> <select id="findClassesById" resultMap="classResultMap"> select cid,cname,id,studentname,gender,age from classes,student where classes.cid=student.classno and classes.cid=#{cid} </select> </mapper>
注意: 在 <resultMap/> 中,如果字段名與屬性名相同時,可以在 <resultMap/> 中添加 autoMapping=“true” 來開啟自動映射。
另外,在 “一方” 的映射文件中使用 <collection/> 標簽體現(xiàn)出兩個實體對象間的關聯(lián)關系。其兩個屬性的解釋如下:
- property:指定關聯(lián)屬性,即 Class 類中的集合屬性 students。
- ofType:集合屬性的泛型類型,即 Student。
方式二:多表單獨查詢方式
多表連接查詢方式是將多張表進行連接,連為一張表后進行查詢。其查詢的本質(zhì)是一張表。而多表單獨查詢方式是多張表各自查詢各自的相關內(nèi)容,需要多張表的聯(lián)合數(shù)據(jù),再將主表的查詢結果聯(lián)合其它表的查詢結果,封裝為一個對象。
多個查詢是可以跨越多個映射文件的,即是可以跨越多個namespace 的。在使用其它 namespace 的查詢時,添加上其所在的 namespace 即可。這種方式要用到2條 SQL 語句,代碼如下所示:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "https://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="cn.kgc.my01.mapper.ClassesMapper"> <!--方式二:多表單獨查詢方式,也就是分步查詢--> <resultMap id="classResultMap2" type="classes"> <id property="cid" column="cid"/> <result property="cname" column="cname"/> <!--關聯(lián)屬性的映射關系--> <collection property="students" ofType="Student"> <id property="sid" column="id"/> <result property="sname" column="studentname"/> <result property="sex" column="gender"/> <result property="age" column="age"/> </collection> </resultMap> <!-- 以下注釋部分屬于方式二: 多表單獨查詢方式 --> <resultMap id="studentResultMap" type="student"> <id property="sid" column="id" /> <result property="sname" column="studentname" /> <result property="sex" column="gender" /> <result property="age" column="age" /> </resultMap> <resultMap id="classesResultMap" type="classes"> <id property="cid" column="cid" /> <result property="cname" column="cname" /> <!-- 關聯(lián)屬性的映射關系 --> <!-- 集合的數(shù)據(jù)來自指定的select查詢,該select查詢的動態(tài)參數(shù)來自column指定的字段值 --> <collection property="students" ofType="Student" select="selectStudentsByClasses" column="cid"/> </resultMap> <!-- 多表單獨查詢,查多方的表 --> <select id="selectStudentsByClasses" resultMap="studentResultMap"> select * from student where calssno=#{cid} </select> <!-- 多表單獨查詢,查一方的表 --> <select id="findClassesById" parameterType="String" resultMap="classesResultMap"> select cid,cname from classes where cid=#{cid} </select> </mapper>
【5】創(chuàng)建 ClassesMapperTest 測試類,并添加如下方法:
package cn.kgc.my01.mapper; import cn.kgc.my01.entity.Classes; import cn.kgc.my01.entity.Student; import junit.framework.TestCase; 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 org.junit.Before; import org.junit.Test; import java.io.IOException; import java.io.InputStream; import java.util.List; public class ClassesMapperTest{ SqlSessionFactory factory=null; @Before public void init(){ try { System.out.println("########"); InputStream resourceAsStream = Resources.getResourceAsStream("config/mybatis-config.xml"); factory = new SqlSessionFactoryBuilder().build(resourceAsStream); } catch (IOException e) { e.printStackTrace(); } } @Test public void testFindClassesById() { SqlSession sqlSession = factory.openSession(true); ClassesMapper mapper = sqlSession.getMapper(ClassesMapper.class); Classes classesById = mapper.findClassesById("201801"); System.out.println(classesById.show()); List<Student> students = classesById.getStudents(); for (Student student : students) { System.out.println(student.show()); } } }
方式一:多表連接查詢方式測試結果:
DEBUG [main] - ==> Preparing: select cid,cname,id,studentname,gender,age from classes,student where classes.cid=student.classno and classes.cid=? DEBUG [main] - ==> Parameters: 201801(String) DEBUG [main] - <== Total: 4 班級編號:201801,班級名稱:計算機軟件1班,班級學生: 學生編號:1,學生姓名:張飛,學生性別:男,學生年齡:18 學生編號:2,學生姓名:李白,學生性別:男,學生年齡:20 學生編號:3,學生姓名:張無忌,學生性別:男,學生年齡:19 學生編號:4,學生姓名:趙敏,學生性別:女,學生年齡:17
可以發(fā)現(xiàn),只有一條 SQL 語句,并且是多表聯(lián)查。
方式二:多表單獨查詢方式測試結果:
2023-02-15 10:56:49,965 [main] DEBUG DEBUG [main] - ==> Preparing: select cid,cname from classes where cid=? DEBUG [main] - ==> Parameters: 201801(String) DEBUG [main] - ====> Preparing: select * from student where classno=? DEBUG [main] - ====> Parameters: 201801(String) DEBUG [main] - <==== Total: 4 DEBUG [main] - <== Total: 1 班級編號:201801,班級名稱:計算機軟件1班,班級學生: 學生編號:1,學生姓名:張飛,學生性別:男,學生年齡:18 學生編號:2,學生姓名:李白,學生性別:男,學生年齡:20 學生編號:3,學生姓名:張無忌,學生性別:男,學生年齡:19 學生編號:4,學生姓名:趙敏,學生性別:女,學生年齡:17
可以發(fā)現(xiàn),其 SQL 語句是兩條,即各查各的,共用同一個參數(shù)。第 1 條先查一方的表,第 2 條再查多方的表。
多對一查詢
多對一關聯(lián)查詢是指在查詢多方對象的時候,同時將其所關聯(lián)的一方對象也查詢出來。
由于在查詢多方對象時也是一個一個查詢,所以多對一關聯(lián)查詢,其實就是一對一關聯(lián)查詢。即一對一關聯(lián)查詢的實現(xiàn)方式與多對一的實現(xiàn)方式是相同的。 配置多對一關聯(lián)的重點在于“多方”的映射文件要有 <association> 屬性關聯(lián)“一方”。
項目案例: 查詢學號為1的學生,同時獲取他所在班級的完整信息
實現(xiàn)步驟:
【1】創(chuàng)建 StudentMapper.java 接口,并添加方法 searchStudentsById(int id) 如下:
package cn.kgc.my01.mapper; import cn.kgc.my01.entity.Student; public interface StudentMapper { public Student searchStudentsById(int id); }
【2】創(chuàng)建 StudentMapper.xml 映射文件,有以下兩種方式:
方式一:多表聯(lián)合查詢。
<!-- 多表聯(lián)合查詢 --> <resultMap id="studentResultMapper" type="student"> <id property="sid" column="id" /> <result property="sname" column="studentname" /> <result property="sex" column="gender" /> <result property="age" column="age" /> <!-- 關聯(lián)屬性 --> <association property="classes" javaType="classes"> <id property="cid" column="cid" /> <result property="cname" column="cname" /> </association> </resultMap> <!-- 多表連接查詢 --> <select id="searchStudentsById" parameterType="int" resultMap="studentResultMapper"> select cid,cname,id,studentname,gender,age from classes,student where classes.cid=student.classno and student.id=#{id} </select>
方式二:多表單獨查詢。
<!-- 以下注釋的是方式二:多表單獨查詢 --> <resultMap id="studentResultMap2" type="student"> <id property="sid" column="id" /> <result property="sname" column="studentname" /> <result property="sex" column="gender" /> <result property="age" column="age" /> <!-- 關聯(lián)屬性 --> <association property="classes" javaType="classes" select="findClassesById" column="classno"/> </resultMap> <select id="searchStudentsById" resultMap="studentResultMap2"> select id,studentname,gender,age,classno from student where id=#{id} </select> <select id="findClassesById" parameterType="String" resultType="classes"> select cid,cname from classes where cid=#{cid} </select>
【3】創(chuàng)建 StudentMapperTest 測試類,并添加如下方法:
package cn.kgc.my01.mapper; import cn.kgc.my01.entity.Classes; import cn.kgc.my01.entity.Student; import junit.framework.TestCase; 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 org.junit.Before; import org.junit.Test; import java.io.IOException; import java.io.InputStream; public class StudentMapperTest { SqlSessionFactory factory=null; @Before public void init(){ try { InputStream resourceAsStream = Resources.getResourceAsStream("config/mybatis-config.xml"); factory = new SqlSessionFactoryBuilder().build(resourceAsStream); } catch (IOException e) { e.printStackTrace(); } } @Test public void testSearchStudentsById() { SqlSession sqlSession = factory.openSession(true); StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); Student student = mapper.searchStudentsById(1); System.out.println(student.show()); System.out.println("所在班級:"); Classes classes=student.getClasses(); System.out.println(classes.toString()); } }
方式一:多表聯(lián)合查詢方式測試結果:
DEBUG [main] - ==> Preparing: select cid,cname,id,studentname,gender,age from classes,student where classes.cid=student.classno and student.id=? DEBUG [main] - ==> Parameters: 1(Integer) DEBUG [main] - <== Total: 1 學生編號:1,學生姓名:張飛,學生性別:男,學生年齡:18 所在班級: Classes(cid=201801, cname=計算機軟件1班, students=null)
可以發(fā)現(xiàn),它發(fā)出的 SQL 語句是多表查詢。
方式一:多表單獨查詢方式測試結果:
DEBUG [main] - ==> Preparing: select id,studentname,gender,age,classno from student where id=? DEBUG [main] - ==> Parameters: 1(Integer) DEBUG [main] - ====> Preparing: select cid,cname from classes where cid=? DEBUG [main] - ====> Parameters: 201801(String) DEBUG [main] - <==== Total: 1 DEBUG [main] - <== Total: 1 學生編號:1,學生姓名:張飛,學生性別:男,學生年齡:18 所在班級: Classes(cid=201801, cname=計算機軟件1班, students=null)
可以發(fā)現(xiàn),它發(fā)出的 SQL 語句是兩條,即各查各的,共用同一個參數(shù)。
自連接查詢
自連接的查詢可以用一對多來處理,也可以用多對一來處理。例如,員工表,每個員工都有一個上司,但上司同時也是員工表的一條記錄,這種情況可用自連接查詢出每個員工對應的上司信息,也可以查出每個上司有哪些下屬員工。
使用多對一的方式實現(xiàn)自連接
項目案例:查詢員工的信息及對應的上司信息。
思路分析: 可將員工當做多方,上司當做一方。
實現(xiàn)步驟:
【1】修改數(shù)據(jù)庫。
添加一個表 employee 并插入測試數(shù)據(jù),具體如下:
create table employee ( empid double , empname varchar (60), job varchar (60), leader double ); insert into employee (empid, empname, job, leader) values('1','jack','clerk','3'); insert into employee (empid, empname, job, leader) values('2','mike','salesman','3'); insert into employee (empid, empname, job, leader) values('3','john','manager','4'); insert into employee (empid, empname, job, leader) values('4','smith','president',NULL); insert into employee (empid, empname, job, leader) values('5','rose','salesman','3');
【2】創(chuàng)建實體類 Employee,代碼如下:
package cn.kgc.my01.entity; public class Employee { private int empid; private String empname; private String job; private Employee leader; public int getEmpid() { return empid; } public void setEmpid(int empid) { this.empid = empid; } public String getEmpname() { return empname; } public void setEmpname(String empname) { this.empname = empname; } public String getJob() { return job; } public void setJob(String job) { this.job = job; } public Employee getLeader() { return leader; } public void setLeader(Employee leader) { this.leader = leader; } public String toString(){ return "員工編號:"+getEmpid()+",員工姓名:"+getEmpname()+",員工職位:"+getJob(); } }
可以發(fā)現(xiàn),里面存在著嵌套,Employee 里面的一個屬性 leader 本身就是 Employee 類型。
【3】創(chuàng)建 EmployeeMapper.java 接口,添加 findEmployeeAndLeaderById 方法如下:
package cn.kgc.my01.mapper; import cn.kgc.my01.entity.Employee; public interface EmployeeMapper { Employee findEmployeeAndLeaderById(int id); }
【4】創(chuàng)建 EmployeeMapper.xml 映射文件,代碼如下:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "https://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="cn.kgc.my01.mapper.EmployeeMapper"> <resultMap id="empResultMap" type="employee"> <id property="empid" column="empid" /> <result property="empname" column="empname" /> <result property="job" column="job" /> <association property="leader" javaType="Employee" select="findEmployeeAndLeaderById" column="leader"/> </resultMap> <select id="findEmployeeAndLeaderById" parameterType="int" resultMap="empResultMap"> select * from employee where empid=#{empid} </select> </mapper>
【5】創(chuàng)建 EmployeeMapperTest.java 測試類
package cn.kgc.my01.mapper; import cn.kgc.my01.entity.Classes; import cn.kgc.my01.entity.Employee; import cn.kgc.my01.entity.Student; import junit.framework.TestCase; 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 org.junit.Before; import org.junit.Test; import java.io.IOException; import java.io.InputStream; import java.util.Scanner; public class EmployeeMapperTest { SqlSessionFactory factory=null; @Before public void init(){ try { InputStream resourceAsStream = Resources.getResourceAsStream("config/mybatis-config.xml"); factory = new SqlSessionFactoryBuilder().build(resourceAsStream); } catch (IOException e) { e.printStackTrace(); } } @Test public void testFindEmployeeAndLeaderById() { SqlSession sqlSession = factory.openSession(true); EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class); Employee employee=mapper.findEmployeeAndLeaderById(1); Employee leader=employee.getLeader(); System.out.println(employee.toString()); System.out.println("他的上司是:"+leader.toString()); //System.out.println("他的上司的上司是:"+leader.getLeader().toString()); } }
測試結果: 查詢員工
DEBUG [main] - ==> Preparing: select * from employee where empid=? DEBUG [main] - ==> Parameters: 1(Integer) DEBUG [main] - ====> Preparing: select * from employee where empid=? DEBUG [main] - ====> Parameters: 3(Integer) DEBUG [main] - ======> Preparing: select * from employee where empid=? DEBUG [main] - ======> Parameters: 4(Integer) DEBUG [main] - <====== Total: 1 DEBUG [main] - <==== Total: 1 DEBUG [main] - <== Total: 1 員工編號:1,員工姓名:jack,員工職位:clerk 他的上司是:員工編號:3,員工姓名:john,員工職位:manager
從上面的 SQL 語句中發(fā)現(xiàn),出現(xiàn)了 3 條 SQL 語句,這個查詢存在嵌套,先查員工1,然后查他的直接上司3,再查上司的上司4。這種情況不影響什么,甚至可以實現(xiàn)直接輸出上司的上司,但要注意輸出語句不要出現(xiàn)地柜,即輸出語句不要出現(xiàn)輸出上司。
要同時查上司的上司,只需要在上面的測試類中多加一條語句:
System.out.println("他的上司的上司是:"+leader.getLeader().toString());
使用一對多的方式實現(xiàn)自連接
項目案例:查詢某位領導及其直接下屬員工。
思路分析: 可用一對多的方式來實現(xiàn),員工(領導)當作一方,員工(下屬)當作多方。
實現(xiàn)步驟:
【1】修改實體類 Employee,代碼如下:
package cn.kgc.my01.entity; import java.util.List; public class Employee { private int empid; private String empname; private String job; //員工的上司 private Employee leader; //員工的下屬 private List<Employee> employees; public List<Employee> getEmployees() { return employees; } public void setEmployees(List<Employee> employees) { this.employees = employees; } public int getEmpid() { return empid; } public void setEmpid(int empid) { this.empid = empid; } public String getEmpname() { return empname; } public void setEmpname(String empname) { this.empname = empname; } public String getJob() { return job; } public void setJob(String job) { this.job = job; } public Employee getLeader() { return leader; } public void setLeader(Employee leader) { this.leader = leader; } public String toString(){ return "員工編號:"+getEmpid()+",員工姓名:"+getEmpname()+",員工職位:"+getJob(); } }
【2】在 EmployeeMapper.java 接口中,添加 findLeaderAndEmployeesById 方法如下:
Employee findLeaderAndEmployeesById(int id);
【3】在 EmployeeMapper.xml 映射文件中,添加 findEmployeeAndLeaderById 的映射方法內(nèi)容如下:
<!-- 一對多的方式實現(xiàn)自連接 --> <resultMap id="empResultMap2" type="employee"> <id property="empid" column="empid" /> <result property="empname" column="empname" /> <result property="job" column="job" /> <!-- 關聯(lián)屬性的映射關系 集合的數(shù)據(jù)來自指定的select查詢,該select查詢的動態(tài)參數(shù)來自column指定的字段值 --> <collection property="employees" ofType="employee" select="selectEmployeesByLeader" column="empid"/> </resultMap> <select id="selectEmployeesByLeader" resultType="employee"> select * from employee where leader=#{empid} </select> <select id="findLeaderAndEmployeesById" parameterType="int" resultMap="empResultMap2"> select * from employee where empid=#{empid} </select>
【4】在 EmployeeMapperTest.java 測試類中,添加如下內(nèi)容:
@Test public void testTestFindLeaderAndEmployeesById() { SqlSession sqlSession = factory.openSession(true); EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class); Employee leader=mapper.findLeaderAndEmployeesById(4); List<Employee> employees = leader.getEmployees(); System.out.println(leader.toString()); System.out.println("他的直接下屬有:"); for (Employee employee : employees) { System.out.println(employee.toString()); } }
測試結果: 查詢經(jīng)理
DEBUG [main] - ==> Preparing: select * from employee where empid=? DEBUG [main] - ==> Parameters: 4(Integer) DEBUG [main] - ====> Preparing: select * from employee where leader=? DEBUG [main] - ====> Parameters: 4.0(Double) DEBUG [main] - <==== Total: 1 DEBUG [main] - <== Total: 1 員工編號:4,員工姓名:smith,員工職位:president 他的直接下屬有: 員工編號:3,員工姓名:john,員工職位:manager
多對多查詢
原理: 多對多可以分拆成兩個一對多來處理,需要一個中間表,各自與中間表實現(xiàn)一對多的關系。
項目案例:一個學生可以選人修多門課程,一門課程可以給多個學生選修,課程與學生之間是典型的多對多。實現(xiàn)查詢一個學生信息,同時查出他的所有選修課,還有實現(xiàn)查詢一門課程信息,同時查出所有的選修了該課程的學生信息。
思路分析: 多對多需要第三表來體現(xiàn),數(shù)據(jù)庫中除了課程表,學生表,還需要學生課程表。
實現(xiàn)步驟:
【1】修改數(shù)據(jù)庫,代碼如下:
CREATE DATABASE studentdb; USE studentdb ; DROP TABLE IF EXISTS student ; CREATE TABLE student ( id INT(11) NOT NULL, studentname VARCHAR(20) DEFAULT NULL, gender CHAR(2) DEFAULT NULL, age INT(11) DEFAULT NULL, classno VARCHAR(10), PRIMARY KEY ( id ) ) INSERT INTO student ( id , studentname , gender , age , classno ) VALUES (1,'張飛','男',18,'201801'),(2,'李白','男',20,'201801'),(3,'張無忌','男',19,'201801'),(4,'趙敏','女',17,'201801'); CREATE TABLE classes ( cid VARCHAR (30), cname VARCHAR (60) ); INSERT INTO classes (cid, cname) VALUES('201801','計算機軟件1班'); INSERT INTO classes (cid, cname) VALUES('201802','計算機軟件2班'); CREATE TABLE employee ( empid DOUBLE , empname VARCHAR (60), job VARCHAR (60), leader DOUBLE ); INSERT INTO employee (empid, empname, job, leader) VALUES('1','jack','clerk','3'); INSERT INTO employee (empid, empname, job, leader) VALUES('2','mike','salesman','3'); INSERT INTO employee (empid, empname, job, leader) VALUES('3','john','manager','4'); INSERT INTO employee (empid, empname, job, leader) VALUES('4','smith','president',NULL); INSERT INTO employee (empid, empname, job, leader) VALUES('5','rose','salesman','3'); CREATE TABLE course ( courseid DOUBLE , coursename VARCHAR (90) ); INSERT INTO course (courseid, coursename) VALUES('1','java'); INSERT INTO course (courseid, coursename) VALUES('2','android'); INSERT INTO course (courseid, coursename) VALUES('3','PHP'); CREATE TABLE studentcourse ( id DOUBLE , studentid DOUBLE , courseid DOUBLE ); INSERT INTO studentcourse (id, studentid, courseid) VALUES('1','1','1'); INSERT INTO studentcourse (id, studentid, courseid) VALUES('2','1','2'); INSERT INTO studentcourse (id, studentid, courseid) VALUES('3','2','1'); INSERT INTO studentcourse (id, studentid, courseid) VALUES('4','2','2'); INSERT INTO studentcourse (id, studentid, courseid) VALUES('5','3','1'); INSERT INTO studentcourse (id, studentid, courseid) VALUES('6','3','2'); INSERT INTO studentcourse (id, studentid, courseid) VALUES('7','1','3');
【2】新增實體類 Course 和修改實體類 Student 。
Course 類如下:
package cn.kgc.my01.entity; import lombok.Data; import java.util.List; @Data public class Course { private int courseid; private String coursename; private List<Student> students; public String toString(){ return "課程編號:"+getCourseid()+",課程名稱:"+getCoursename(); } }
Student類如下,添加一個屬性courses和getter,setter方法。
private List<Course> courses; public List<Course> getCourses() { return courses; } public void setCourses(List<Course> courses) { this.courses = courses; }
【3】新建 StudentMapper.java 接口,并添加一個方法如下:
package cn.kgc.my01.mapper; import cn.kgc.my01.entity.Student; public interface StudentMapper { public Student searchStudentById(int id); }
【4】配置對應的 StudentMapper.xml 映射,代碼如下:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "https://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="cn.kgc.my01.mapper.StudentMapper"> <resultMap id="studentMap2" type="student"> <id property="sid" column="id" /> <result property="sname" column="studentname" /> <result property="sex" column="gender" /> <result property="age" column="age" /> <!-- 關聯(lián)屬性的映射關系 --> <collection property="courses" ofType="Course"> <id property="courseid" column="courseid" /> <result property="coursename" column="coursename" /> </collection> </resultMap> <!-- 多表連接查詢 --> <select id="searchStudentById" parameterType="int" resultMap="studentMap2"> select student.id,studentname,gender,age,course.courseid,coursename from course,student,studentcourse where course.courseid=studentcourse.courseid and student.id=studentcourse.studentid and student.id=#{id} </select> </mapper>
【5】創(chuàng)建測試類 StudentMapperTest 類
package cn.kgc.my01.mapper; import cn.kgc.my01.entity.Classes; import cn.kgc.my01.entity.Course; import cn.kgc.my01.entity.Student; import junit.framework.TestCase; 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 org.junit.Before; import org.junit.Test; import java.io.IOException; import java.io.InputStream; import java.util.List; public class StudentMapperTest { SqlSessionFactory factory=null; @Before public void init(){ try { InputStream resourceAsStream = Resources.getResourceAsStream("config/mybatis-config.xml"); factory = new SqlSessionFactoryBuilder().build(resourceAsStream); } catch (IOException e) { e.printStackTrace(); } } @Test public void testSearchStudentsById() { SqlSession sqlSession = factory.openSession(true); StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); Student student = mapper.searchStudentById(1); System.out.println(student.show()); System.out.println("-----該生選修了以下課程:-----------"); List<Course> courses=student.getCourses(); for(Course course:courses){ System.out.println(course.toString()); } } }
測試結果:
【6】新建 CourseMapper.java 接口,并添加一個方法如下:
package cn.kgc.my01.mapper; import cn.kgc.my01.entity.Course; public interface CourseMapper { //根據(jù)id查找課程,即時獲取選個性該課程的學生 public Course searchCourseById(int id); }
【7】配置對應的 CourseMapper.xml 映射,代碼如下:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "https://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="cn.kgc.my01.mapper.CourseMapper"> <resultMap id="courseMap" type="course"> <id property="courseid" column="courseid" /> <result property="coursename" column="coursename" /> <!-- 關聯(lián)屬性的映射關系 --> <collection property="students" ofType="Student"> <id property="sid" column="id" /> <result property="sname" column="studentname" /> <result property="sex" column="gender" /> <result property="age" column="age" /> </collection> </resultMap> <!-- 多表連接查詢 --> <select id="searchCourseById" parameterType="int" resultMap="courseMap"> select student.id,studentname,gender,age,course.courseid,coursename from course,student,studentcourse where course.courseid=studentcourse.courseid and student.id=studentcourse.studentid and course.courseid=#{courseid} </select> </mapper>
【8】創(chuàng)建測試類 CourseMapperTest 類
package cn.kgc.my01.mapper; import cn.kgc.my01.entity.Course; import cn.kgc.my01.entity.Employee; import cn.kgc.my01.entity.Student; import junit.framework.TestCase; 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 org.junit.Before; import org.junit.Test; import java.io.IOException; import java.io.InputStream; import java.util.List; public class CourseMapperTest{ SqlSessionFactory factory=null; @Before public void init(){ try { InputStream resourceAsStream = Resources.getResourceAsStream("config/mybatis-config.xml"); factory = new SqlSessionFactoryBuilder().build(resourceAsStream); } catch (IOException e) { e.printStackTrace(); } } @Test public void testSearchCourseById() { SqlSession sqlSession = factory.openSession(true); CourseMapper mapper = sqlSession.getMapper(CourseMapper.class); Course course = mapper.searchCourseById(1); System.out.println(course.toString()); System.out.println("-------該課程有以下學生選修:------"); List<Student> students=course.getStudents(); for(Student student:students){ System.out.println(student.show()); } } }
測試效果:
到此這篇關于MyBatis多表關聯(lián)查詢的實現(xiàn)示例的文章就介紹到這了,更多相關MyBatis多表關聯(lián)查詢內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
- MyBatis-Plus實現(xiàn)多表聯(lián)查的方法實戰(zhàn)
- Mybatis-Plus多表關聯(lián)查詢的使用案例解析
- mybatis-plus多表聯(lián)查join的實現(xiàn)
- MyBatis-Plus多表聯(lián)查(動態(tài)查詢)的項目實踐
- MyBatis實現(xiàn)多表聯(lián)查的詳細代碼
- MyBatis-Plus多表聯(lián)查的實現(xiàn)方法(動態(tài)查詢和靜態(tài)查詢)
- Spring boot2基于Mybatis實現(xiàn)多表關聯(lián)查詢
- Mybatis-Plus 多表聯(lián)查分頁的實現(xiàn)代碼
- MyBatis-Flex實現(xiàn)多表聯(lián)查(自動映射)
相關文章
Java異常中toString()和getMessage()區(qū)別
在java異常體系中,要打印異常信息,可以通過:e.getMessage() 、 e.toString() e.printStackTrace() 等方法打印,本文主要介紹了Java異常中toString()和getMessage()區(qū)別,具有一定的參考價值,感興趣的可以了解一下2024-01-01Java中HashMap和Hashtable的區(qū)別淺析
這篇文章主要介紹了Java中HashMap和Hashtable的區(qū)別淺析,本文總結了6條它們之間的不同之處,需要的朋友可以參考下2015-03-03idea運行tomcat報錯找不到catalina.bat,系統(tǒng)找不到指定的文件問題
這篇文章主要介紹了idea運行tomcat報錯找不到catalina.bat,系統(tǒng)找不到指定的文件問題,具有很好的參考價值,希望對大家有所幫助,2023-11-11