Mybatis的多对多映射
一、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()); }*/ } }