一、Mybatis的多對多映射
本例講述使用mybatis開發過程中常見的多對多映射查詢案例。只抽取關鍵代碼和mapper文件中的關鍵sql和配置,詳細的工程搭建和Mybatis詳細的流程代碼可參見《Mybatis入門和簡單Demo》和《Mybatis的CRUD案例》
完整的工程代碼已上傳至https://files.cnblogs.com/files/jiyukai/MyBatis.zip
案例:查詢xx同學所選擇的多個不同選修課,查詢xx選修課被多少同學選修
步驟1.建表腳本,分別創建學生表,課程表,以及學生課程表,作為學生關系到課程的中間關聯表。
create table students( sid int(5) primary key, sname varchar(10) ); create table courses( cid int(5) primary key, cname varchar(10) ); create table course_stu( sid int(5), cid int(5), primary key(sid,cid) ); insert into students(sid,sname) values(1,'cat'); insert into students(sid,sname) values(2,'dog'); insert into courses(cid,cname) values(1,'java'); insert into courses(cid,cname) values(2,'net'); insert into course_stu(sid,cid) values(1,1); insert into course_stu(sid,cid) values(1,2); insert into course_stu(sid,cid) values(2,1); insert into course_stu(sid,cid) values(2,2);
步驟2.編寫課程和學生實體類,學生可選擇多門課程,課程中有多個學生,因此在各自的實體類中都以集合的形式引入對方
package com.jyk.mybatis.moreTomore; import java.util.ArrayList; import java.util.List; public class Course { private Integer id; //課程id private String name; //課程名稱 private List<Student> studentList = new ArrayList<Student>(); //對應的學生名稱 public Course(){} public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public List<Student> getStudentList() { return studentList; } public void setStudentList(List<Student> studentList) { this.studentList = studentList; } }
package com.jyk.mybatis.moreTomore; import java.util.ArrayList; import java.util.List; public class Student { private Integer id; //學生id private String name; //學生姓名 private List<Course> courseList = new ArrayList<Course>(); //選修的課程 public Student(){} public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public List<Course> getCourseList() { return courseList; } public void setCourseList(List<Course> courseList) { this.courseList = courseList; } }
步驟3.編寫mapper文件,在CourseMapper.xml中編寫課程信息表字段與實體屬性的映射關系,在StudentMapper.xml中編寫學生實體和表字段的映射關系,並編寫好根據學生姓名查詢所有選修課程,以及根據選修課名稱查詢有多少學生的SQL,並將mapper文件和對應實體類的別名加入mybatis.xml(mybatis.xml的描述見Mybatis系列第一篇博客,此處由於配置type時指定了類的全路徑,故無需將別名加入至mybatis.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="studentNamespace"> <resultMap type="com.jyk.mybatis.moreTomore.Student" id="studentMap"> <id property="id" column="sid" /> <result property="name" column="sname"/> </resultMap> <!-- 查詢java課程有哪些學生 --> <select id="findStudentByName" parameterType="string" resultMap="studentMap"> select s.sid,s.sname from students s,course_stu m,courses c where s.sid = m.sid and m.cid = c.cid and c.cname = #{name} </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="courseNamespace"> <resultMap type="com.jyk.mybatis.moreTomore.Course" id="courseMap"> <id property="id" column="cid" /> <result property="name" column="cname"/> </resultMap> <!-- 查詢cat選學的課程 --> <select id="findCourseByName" parameterType="string" resultMap="courseMap"> select c.cid,c.cname from students s,course_stu m,courses c where s.sid = m.sid and m.cid = c.cid and s.sname = #{name} </select> </mapper>
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!-- 加載類路徑下的屬性文件 --> <properties resource="db.properties"> </properties> <!-- 設置類型別名 --> <typeAliases> </typeAliases> <!-- 設置一個默認的連接環境信息 --> <environments default="mysql_env"> <!-- 連接環境信息,取一個唯一的編號 --> <environment id="mysql_env"> <!-- mybatis使用的jdbc事務管理方式 --> <transactionManager type="jdbc"> </transactionManager> <!-- mybatis使用連接池方式來獲取鏈接 --> <dataSource type="pooled"> <!-- 配置與數據庫交互的四個屬性 --> <property name="driver" value="${mysql.driver}"/> <property name="url" value="${mysql.url}"/> <property name="username" value="${mysql.username}"/> <property name="password" value="${mysql.password}"/> </dataSource> </environment> </environments> <mappers> <mapper resource="com/jyk/mybatis/moreTomore/CourseMapper.xml"/> <mapper resource="com/jyk/mybatis/moreTomore/StudentMapper.xml"/> </mappers> </configuration>
步驟4.編寫Java代碼實現該多對多查詢,需要注意的是,區分於一對一查詢,此處由於查詢的結果有多個,是集合的形式返回,故查詢的API應使用SqlSession提供的selectList接口而不再是selectOne。
package com.jyk.mybatis.moreTomore; import java.util.List; import org.apache.ibatis.session.SqlSession; import com.jyk.mybatis.util.MyBatisUtil; public class StudentCourseDao { /** * 查詢cat選學的課程 */ public List<Course> findCourseByName(String name) throws Exception{ SqlSession sqlSession = null; try{ sqlSession = MyBatisUtil.getSqlSession(); return sqlSession.selectList("courseNamespace.findCourseByName",name); }catch(Exception e){ e.printStackTrace(); throw e; }finally{ MyBatisUtil.closeSqlSession(); } } /** * 查詢java課程有哪些學生 */ public List<Student> findStudentByName(String name) throws Exception{ SqlSession sqlSession = null; try{ sqlSession = MyBatisUtil.getSqlSession(); return sqlSession.selectList("studentNamespace.findStudentByName",name); }catch(Exception e){ e.printStackTrace(); throw e; }finally{ MyBatisUtil.closeSqlSession(); } } public static void main(String[] args) throws Exception{ StudentCourseDao dao = new StudentCourseDao(); List<Course> courseList = dao.findCourseByName("cat"); for(Course c : courseList){ System.out.println(c.getId()+":"+c.getName()); } /*List<Student> studentList = dao.findStudentByName("java"); for(Student s : studentList){ System.out.println(s.getId()+":"+s.getName()); }*/ } }