MyBatis的association示例以及association的两种形式

来源:互联网 发布:java 异或 php 编辑:程序博客网 时间:2024/05/17 01:10

一、association示例

假设每个学生都有一名指导老师,本示例的任务就是查询出学生的详细信息,这就包括学生的指导教师的信息。为此,应先增加一个教师的实体类。

package com.abc.domain;public class Teacher{private int id;private String name;  //姓名private String gender;//性别private String researchArea;//研究方向private String title;//职称public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getGender() {return gender;}public void setGender(String gender) {this.gender = gender;}public String getResearchArea() {return researchArea;}public void setResearchArea(String researchArea) {this.researchArea = researchArea;}public String getTitle() {return title;}public void setTitle(String title) {this.title = title;}}

相应地,在数据库中,应增加教师表。完成此任务的脚本(teacher.sql)如下:

/*数据库编码UTF8,以下命令是为了在脚本和命令行中支持中文*/set names gbk;/*切换到courseman数据库*/use courseman;/*创建成绩表*/drop table if exists teacher;CREATE TABLE teacher(id int NOT NULL AUTO_INCREMENT primarykey,name varchar(10) NOT NULL,/*姓名*/gender char(1) NOT NULL,/*性别*/research_area varchar(20) NOT NULL,/*研究方向*/title varchar(6) NOT NULL/*职称*/);/*添加第一条记录,自动生成的ID为1*/insert into teacher(name,gender,research_area, title)values('张伟','男','软件工程','讲师');

接着为学生增加指导教师属性,如下:

private Teacher supervisor; //指导教师

并为此属性编写getter和setter方法,此处略去。

      相应地,为学生表增加一个指导教师ID的字段,脚本(supervisor.sql)如下: 

/*切换到courseman数据库*/use courseman;/*为学生表添加指导老师ID列*/alter TABLE student add supervisor_id int not nullreferences teacher(id);/*把上面新增的教师作为目前学生的指导教师*/update student set supervisor_id=1;

在MyBatis的核心配置文件configuration.xml中增加教师类型的别名定义,如下:

<typeAliases><typeAlias alias="Student"type="com.abc.domain.Student"/><!--增加的教师类型别名--><typeAlias alias="Teacher"type="com.abc.domain.Teacher"/></typeAliases>


然后,我们需要修改StudentMapper.xml中的select语句及要用到的resultMap元素,这是本示例的关键部分。

     首先,为了能够同时查询到学生的指导教师的信息,修改select语句如下: 

<select id="getById" parameterType="int" resultMap="studentResultMap">select st.id,st.name,st.gender,st.major,st.grade,<!--为教师的id取别名,避免MyBatis向教师实体注入此属性时与学生id混淆。以下的name和gender等属性也是如此-->t.id t_id,t.name t_name,t.gender t_gender,t.title,t.research_areafrom student st, teacher twhere st.supervisor_id = t.idand st.id=#{id}</select>



为了实现查询结果与实体的映射,需要修改resultMap元素。此时的学生实体拥有一个指导教师属性(supervisor),而该属性本身就是一个实体。这是一种has-a关系,亦即一个学生有一个指导教师,而association元素就是处理这种关系的映射的。我们为resultMap添加association如下(从第11行开始): 

<resultMap id="studentResultMap" type="Student"><!--普通属性映射与以前一致--><id property="id" column="id"/><result property="name" column="name"/><result property="gender" column="gender"/><result property="major"  column="major"/><result property="grade"  column="grade"/><!--property="supervisor"表明这是为了映射学生实体的supervisor属性。javaType="Teacher"用到了Teacher这个别名定义,并指出了supervisor属性的java类型--><association property="supervisor" javaType="Teacher"><!--教师自身的属性与数据库字段的映射。注意这里用到了字段别名--><id property="id" column="t_id"/><result property="name" column="t_name"/><result property="gender" column="t_gender"/><result property="researchArea" column="research_area"/><result property="title" column="title"/></association></resultMap>

其中的javaType属性为必须,否则报错。

这次的执行类是AssociationDemo,代码如下: 

package com.demo;import org.apache.ibatis.session.SqlSessionFactory;import org.apache.ibatis.session.SqlSession;import com.abc.mapper.StudentMapper;import com.abc.domain.Student;import com.util.SqlSessionFactoryGen;public class AssociationDemo{//获取SqlSessionFactory实例private static SqlSessionFactory factory= SqlSessionFactoryGen.getSqlSessionFactory();public static void main(String[] args){SqlSession session = factory.openSession();StudentMapper mapper =session.getMapper(StudentMapper.class);//笔者的数据库中只有ID为4的学生。读者若运行此程序,//须使用你的数据库中存在的学生ID。否则报空指针异常Student student = mapper.getById(4);//使用StringBuilder的append操作代替字符串的“+”//操作可提高执行效率StringBuilder sb = new StringBuilder("学生信息:\n");sb.append("姓名:");sb.append(student.getName());sb.append(" ");sb.append( "专业:");sb.append(student.getMajor());sb.append(" 年级:");sb.append(student.getGrade());sb.append("\n");sb.append("指导教师信息:\n");sb.append("姓名:");sb.append(student.getSupervisor().getName());sb.append(" ");sb.append("职称:");sb.append(student.getSupervisor().getTitle());sb.append(" ");sb.append("研究方向:");sb.append(student.getSupervisor().getResearchArea());System.out.println(sb.toString());session.close();}}


二、association的两种形式

  1、嵌套的resultMap

这种方法本质上就是上篇博文介绍的方法,只是把教师实体映射从association元素中提取出来,用一个resultMap元素表示。然后association元素再引用这个resultMap元素。修改上篇博文示例的StudentMapper.xml如下:

<?xml version="1.0" encoding="utf8"?><!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.abc.mapper.StudentMapper"><select id="getById" parameterType="int" resultMap="studentResultMap">select s.id s_id,s.name s_name,s.gender s_gender,s.major s_major,s.grade s_grade,t.id t_id,t.name t_name,t.gender t_gender,t.title t_title,t.research_area t_research_areafrom student s left join teacher ton s.supervisor_id = t.idwhere s.id=#{id}</select><resultMap id="studentResultMap" type="Student"><id property="id" column="s_id"/><result property="name" column="s_name"/><result property="gender" column="s_gender"/><result property="major"  column="s_major"/><result property="grade"  column="s_grade"/><!--使用resultMap属性引用下面的教师实体映射--><association property="supervisor" javaType="Teacher"resultMap="supervisorResultMap"/></resultMap><!--教师实体映射--><resultMap id="supervisorResultMap" type="Teacher"><id property="id" column="t_id"/><result property="name" column="t_name"/><result property="gender" column="t_gender"/><result property="researchArea" column="t_research_area"/><result property="title" column="t_title"/></resultMap></mapper>

在这里,为了让select语句更加清晰可读,每个字段都使用了别名。association元素的属性javaType="Teacher"可以不要,不像上面示例那样,没有此属性即报错。这大概是因为引用的resultMap元素已经指明了映射的类型为“Teacher”。另外,今天偶然发现,把StudentMapper.xml的encoding属性由“UTF-8”改为“utf8”即可添加中文注释。

  2、嵌套的select语句

这种方式是使用一条单独的select语句来加载关联的实体(在本例中就是教师实体),然后在association元素中引用此select语句

修改StudentMapper.xml如下:

<?xml version="1.0" encoding="utf8"?><!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.abc.mapper.StudentMapper"><select id="getById" parameterType="int" resultMap="studentResultMap">select id,name,gender,major,grade,supervisor_id from student where id=#{id}</select><select id="selectSupervisor" parameterType="int" resultMap="supervisorResultMap">select id,name,gender,title,research_areafrom teacher where id=#{id}</select><resultMap id="studentResultMap" type="Student"><id property="id" column="id"/><result property="name" column="name"/><result property="gender" column="gender"/><result property="major"  column="major"/><result property="grade"  column="grade"/><!--column="supervisor_id"不能少。此列的值作为参数传递给要引用的select语句,用来查询相应学生的指导教师的信息。select属性指定要引用的select语句--><association property="supervisor" javaType="Teacher"column="supervisor_id" select="selectSupervisor"/></resultMap><!--教师实体映射--><resultMap id="supervisorResultMap" type="Teacher"><id property="id" column="id"/><result property="name" column="name"/><result property="gender" column="gender"/><result property="researchArea" column="research_area"/><result property="title" column="title"/></resultMap></mapper>

association元素的属性javaType="Teacher"也可以不要,这大概也是因为引用的select语句中已经指明了要用到的resultMap。


0 0
原创粉丝点击