一、Mybatis的一对多映射
本例讲述使用mybatis开发过程中常见的一对多映射查询案例。只抽取关键代码和mapper文件中的关键sql和配置,详细的工程搭建和Mybatis详细的流程代码可参见《Mybatis入门和简单Demo》和《Mybatis的CRUD案例》
完整的工程代码已上传至https://files.cnblogs.com/files/jiyukai/MyBatis.zip
案例:根据一个班级名称查询所有的任课老师
步骤1.建表脚本,创建班级表grades和教师表teachers,teachers字段tgid(所属班级id)作为grades字段id的外键
create table grades( gid int(5) primary key, gname varchar(10) ); create table teachers( sid int(5) primary key, sname varchar(10), sgid int(5), constraint sgid_fk foreign key(sgid) references grades(gid) ); insert into grades(gid,gname) values(1,'3年2班'); insert into teachers(sid,sname,sgid) values(1,'math',1); insert into teachers(sid,sname,sgid) values(2,'english',1); insert into teachers(sid,sname,sgid) values(2,'science',1);
步骤2.编写班级,教师信息实体类,由于一个班级任课老师有多个,故用集合的形式来表示
package com.jyk.mybatis.oneTomore; import java.util.ArrayList; import java.util.List; public class Grade { private int gid; //班级id private String gname; //班级名称 private List<Teacher> teacherList = new ArrayList<Teacher>(); //班级拥有的老师 public int getGid() { return gid; } public void setGid(int gid) { this.gid = gid; } public String getGname() { return gname; } public void setGname(String gname) { this.gname = gname; } public List<Teacher> getTeacherList() { return teacherList; } public void setTeacherList(List<Teacher> teacherList) { this.teacherList = teacherList; } }
package com.jyk.mybatis.oneTomore; public class Teacher { private int tid; //老师id private String tname; //老师姓名 private Grade grade; //老师所属班级 public int getTid() { return tid; } public void setTid(int tid) { this.tid = tid; } public String getTname() { return tname; } public void setTname(String tname) { this.tname = tname; } public Grade getGrade() { return grade; } public void setGrade(Grade grade) { this.grade = grade; } }
步骤3.编写mapper文件,在GradeMapper.xml中编写班级信息和表字段的映射关系,在TeacherMapper.xml中编写教师实体和表字段的映射关系,并编写好根据一个班级名称查询所有教师信息的SQL,并将mapper文件和对应实体类的别名加入mybatis.xml(mybatis.xml的描述见Mybatis系列第一篇博客,此处由于配置type时指定了类的全路径,故无需将别名加入至mybatis.xml)
在Grade实体中有一属性为teacherList对象,该对象为一集合,意为一个班级拥有的所有任课老师,此时在配置映射关系时,可使用<collection property="teacherList" resultMap="teacherNamespace.teacherMap"/>标签来引入,property为属性名称,resultMap关联到对应实体类的mapper配置,用名称空间.id来表示。
<?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"> <!-- 名称空间namespace必须唯一 --> <mapper namespace="gradeNamespace"> <!-- resultMap标签:映射实体与表 type属性:实体全路径名 id属性:为实体与表的映射取一个唯一的编号 --> <resultMap type="com.jyk.mybatis.oneTomore.Grade" id="gradeMap"> <!-- id标签:映射主键属性 result标签:映射非主键属性 property属性:实体属性名 column属性:表的字段名 --> <id property="gid" column="gid"/> <result property="gname" column="gname"/> <collection property="teacherList" resultMap="teacherNamespace.teacherMap"/> </resultMap> <select id="findByName" parameterType="string" resultMap="gradeMap"> select g.gname,t.tid,t.tname from grades g,teachers t where t.tgid = g.gid and t.tname = #{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"> <!-- 名称空间namespace必须唯一 --> <mapper namespace="teacherNamespace"> <!-- resultMap标签:映射实体与表 type属性:实体全路径名 id属性:为实体与表的映射取一个唯一的编号 --> <resultMap type="com.jyk.mybatis.oneTomore.Teacher" id="teacherMap"> <!-- id标签:映射主键属性 result标签:映射非主键属性 property属性:实体属性名 column属性:表的字段名 --> <id property="tid" column="tid"/> <result property="tname" column="tname"/> <!-- <association property="grade" resultMap="gradeNamespace.gradeMap"/> --> </resultMap> <select id="findAllTeacher" parameterType="string" resultMap="teacherMap"> select t.tid,t.tname,g.gname from teachers t,grades g where t.tgid = g.gid and g.gname = #{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/oneTomore/TeacherMapper.xml"/> <mapper resource="com/jyk/mybatis/oneTomore/GradeMapper.xml"/> </mappers> </configuration>
步骤4.编写Java代码实现该一对多查询,需要注意的是,区分于一对一查询,此处由于查询的结果有多个,是集合的形式返回,故查询的API应使用SqlSession提供的selectList接口而不再是selectOne。
package com.jyk.mybatis.oneTomore; import java.util.List; import org.apache.ibatis.session.SqlSession; import com.jyk.mybatis.util.MyBatisUtil; public class GradeDao { /* * 根据班级name查找所有老师 */ public List<Teacher> findAllTeacher(String gradeName) { SqlSession sqlSession = null; try{ sqlSession = MyBatisUtil.getSqlSession(); List<Teacher> teachers = sqlSession.selectList("teacherNamespace.findAllTeacher", gradeName); return teachers; }catch(Exception e){ e.printStackTrace(); throw e; }finally{ MyBatisUtil.closeSqlSession(); } } public static void main(String[] args) { GradeDao gd = new GradeDao(); List<Teacher> teachers = gd.findAllTeacher("3年2班"); System.out.println("teachers=="+teachers); } }