mybatis 一对多

第一部分 示例

一、为Teacher实体增加相关属性

      为教师实体增加指导学生集合的属性如下:

  1. private List<Student> supStudents;//指导学生 

       并为其增加setter和getter方法,这里略过。

二、TeacherMapper接口

      为实现教师实体映射,应先创建映射器接口如下:

  1. package com.abc.mapper;  
  2.  
  3. import com.abc.domain.Teacher;  
  4.  
  5. public interface TeacherMapper {  
  6.           
  7.     public Teacher getById(int id);  
  8.       
  9. }  

 三、映射文件

      为教师实体创建的映射文件如下:

  1. <?xml version="1.0" encoding="utf8"?> 
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 
  3.      <!--与以前一样,namespace的值是对应的映射器接口的完整名称--> 
  4.      <mapper namespace="com.abc.mapper.TeacherMapper"> 
  5.         
  6.          <!--TeacherMapper接口中getById方法对应的SQL语句。  
  7.          查询教师及其指导的学生的信息。由于教师、学生都有  
  8.          id、name、gender等属性,因此给教师的字段都起了别名--> 
  9.          <select id="getById" parameterType="int"  resultMap="supervisorResultMap"> 
  10.           select t.id t_id, t.name t_name, t.gender t_gender,  
  11.           t.research_area t_research_area, t.title t_title,  
  12.           s.id,s.name, s.gender,s.major,s.grade  
  13.           from teacher t,student s where t.id=#{id}  
  14.           and s.supervisor_id = t.id  
  15.          </select> 
  16.  
  17.          <!--教师实体映射--> 
  18.          <resultMap id="supervisorResultMap" type="Teacher"> 
  19.             <id property="id" column="t_id"/> 
  20.             <result property="name" column="t_name"/> 
  21.             <result property="gender" column="t_gender"/> 
  22.             <result property="researchArea" column="t_research_area"/>   
  23.             <result property="title" column="t_title"/> 
  24.             <!--collection元素映射教师的指导学生集合的属性。resultMap  
  25.             以命名空间名.resultMap的id的形式,引用studentResultMap。  
  26.             需要注意的是,上面的select语句中学生的字段名/别名应与  
  27.             studentResultMap中的column属性一致--> 
  28.             <collection property="supStudents"   
  29.               resultMap="com.abc.mapper.StudentMapper.studentResultMap"/> 
  30.          </resultMap>      
  31.            
  32.    </mapper> 

       相应地,学生实体的映射文件如下:

  1. <?xml version="1.0" encoding="utf8"?> 
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 
  3.      <mapper namespace="com.abc.mapper.StudentMapper"> 
  4.         
  5.        <resultMap id="studentResultMap" type="Student"> 
  6.           <id property="id" column="id"/> 
  7.           <result property="name" column="name"/> 
  8.           <result property="gender" column="gender"/> 
  9.           <result property="major" column="major"/>   
  10.           <result property="grade" column="grade"/> 
  11.           <!--相应地,在此引用supervisorResultMap,亦采用  
  12.           命名空间名.resultMap的id的形式。--> 
  13.           <association property="supervisor"        
  14.           resultMap="com.abc.mapper.TeacherMapper.supervisorResultMap"/> 
  15.        </resultMap> 
  16.        
  17.      </mapper> 

       在工程的src\resources目录下新建子目录mappers,用来统一存放映射文件。为了能让MyBatis找到这些映射文件,修改其核心配置文件configuration.xml中的mappers元素如下:

  1. <!--在classpath中以相对路径的形式引用映射文件--> 
  2. <mappers> 
  3.    <mapper resource="resources/mappers/StudentMapper.xml"/> 
  4. <mapper resource="resources/mappers/TeacherMapper.xml"/> 
  5. </mappers> 

       注意:resources目录在工程编译前会被复制到classes目录下(详见工程生成文件build.xml中的copy-resources和compile这两个target),而classes目录会被ant添加到classpath中。

四、执行类

      执行类为CollectionDemo,其内容如下:

  1. package com.demo;  
  2.  
  3. import org.springframework.context.ApplicationContext;  
  4. import com.abc.mapper.StudentMapper;  
  5. import com.abc.mapper.TeacherMapper;  
  6. import com.abc.domain.Teacher;  
  7. import com.abc.domain.Student;  
  8. import org.springframework.context.support.ClassPathXmlApplicationContext;  
  9. import java.util.List;  
  10.  
  11. public class CollectionDemo  
  12. {  
  13.     private static ApplicationContext ctx;  
  14.       
  15.     static 
  16.     {  
  17.         //在类路径下寻找resources/beans.xml文件  
  18.         ctx = new ClassPathXmlApplicationContext("resources/beans.xml");  
  19.     }  
  20.       
  21.       
  22.     public static void main(String[] args)  
  23.     {  
  24.         //从Spring容器中请求映射器  
  25.         TeacherMapper mapper =   
  26.                (TeacherMapper)ctx.getBean("teacherMapper");  
  27.  
  28.         //查询id为1的教师  
  29.         Teacher teacher = mapper.getById(1);  
  30.  
  31.         if(teacher == null)  
  32.         {  
  33.             System.out.println("未找到相关教师信息。");  
  34.         }  
  35.         else 
  36.         {  
  37.             //教师信息  
  38.             System.out.println("**********************************************");  
  39.             System.out.println("教师姓名:" + "  " + teacher.getName());  
  40.             System.out.println("教师职称:" + "  " + teacher.getTitle());  
  41.             System.out.println("**********************************************");  
  42.               
  43.             System.out.println("指导学生信息:");  
  44.             //遍历指导的学生  
  45.             for(Student s : teacher.getSupStudents())  
  46.             {  
  47.                System.out.println("**********************************************");  
  48.                System.out.println( s.getName() + "  " + s.getGender() + "  " + s.getGrade()  
  49.                                 + "  " + s.getMajor());  
  50.                //从学生端访问教师  
  51.                System.out.println("指导教师研究方向:" + s.getSupervisor().getResearchArea());  
  52.               
  53.             }  
  54.  
  55.             System.out.println("**********************************************");  
  56.         }         
  57.  
  58.     }  
  59.  

       从中可看出,可以从任意一端访问另一端的对象。



第二部分 :上面是比较典型的使用方式,还有其他方式即:嵌套的Select,但是会产生 N+1的问题

(1)  association 中嵌套select

  1. <?xml version="1.0" encoding="utf8"?> 
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 
  3.      <mapper namespace="com.abc.mapper.StudentMapper"> 
  4.         
  5.      <select id="getById" parameterType="int"  resultMap="studentResultMap"> 
  6.           select id,name,gender,major,grade,supervisor_id from student where id=#{id}  
  7.      </select> 
  8.  
  9.      <select id="selectSupervisor" parameterType="int"  resultMap="supervisorResultMap"> 
  10.           select id,name,gender,title,research_area  
  11.           from teacher where id=#{id}  
  12.      </select> 
  13.  
  14.      <resultMap id="studentResultMap" type="Student"> 
  15.           <id property="id" column="id"/> 
  16.           <result property="name" column="name"/> 
  17.           <result property="gender" column="gender"/> 
  18.           <result property="major" column="major"/>   
  19.           <result property="grade" column="grade"/> 
  20.             
  21.           <!--column="supervisor_id"不能少。此列的值作为参数  
  22.           传递给要引用的select语句,用来查询相应学生的指导教师  
  23.           的信息。select属性指定要引用的select语句--> 
  24.           <association property="supervisor" javaType="Teacher" 
  25.           column="supervisor_id" select="selectSupervisor"/> 
  26.      </resultMap> 
  27.        
  28.      <!--教师实体映射--> 
  29.      <resultMap id="supervisorResultMap" type="Teacher"> 
  30.          <id property="id" column="id"/> 
  31.          <result property="name" column="name"/> 
  32.          <result property="gender" column="gender"/> 
  33.          <result property="researchArea" column="research_area"/>   
  34.          <result property="title" column="title"/> 
  35.      </resultMap> 
  36.            
  37.    </mapper> 

(2)collection 中嵌套select

二、嵌套的select语句

  1. <?xml version="1.0" encoding="utf8"?> 
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 
  3.      <!--与以前一样,namespace的值是对应的映射器接口的完整名称--> 
  4.      <mapper namespace="com.abc.mapper.TeacherMapper"> 
  5.         
  6.          <!--TeacherMapper接口中getById方法对应的SQL语句。  
  7.          查询教师的信息。--> 
  8.          <select id="getById" parameterType="int"  resultMap="supervisorResultMap"> 
  9.           select * from teacher where id=#{id}  
  10.          </select>             
  11.  
  12.          <!--教师实体映射--> 
  13.          <resultMap id="supervisorResultMap" type="Teacher"> 
  14.             <id property="id" column="id"/> 
  15.             <result property="name" column="name"/> 
  16.             <result property="gender" column="gender"/> 
  17.             <result property="researchArea" column="research_area"/>   
  18.             <result property="title" column="title"/> 
  19.             <!--ofType指collection包含的元素的类型,此属性不可少。  
  20.             column属性指把上述的getById的select语句中的教师id列的值作为参数  
  21.             传递给将要引用到的下述的getStudents的select语句,此属性不可少。  
  22.             引用的形式为:命名空间.select语句id--> 
  23.             <collection property="supStudents" column="id" ofType="Student" 
  24.             select="com.abc.mapper.StudentMapper.getStudents"/> 
  25.          </resultMap>      
  26.            
  27.    </mapper> 

       在这里把根据指导教师id查询学生信息的SQL语句写在StudentMapper.xml中,并引用其中的学生实体映射studentResultMap。修改StudentMapper.xml如下:

  1. <?xml version="1.0" encoding="utf8"?> 
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 
  3.      <mapper namespace="com.abc.mapper.StudentMapper"> 
  4.         
  5.        <resultMap id="studentResultMap" type="Student"> 
  6.           <id property="id" column="id"/> 
  7.           <result property="name" column="name"/> 
  8.           <result property="gender" column="gender"/> 
  9.           <result property="major" column="major"/>   
  10.           <result property="grade" column="grade"/> 
  11.           <!--在这里引用supervisorResultMap和getById,亦采用  
  12.           命名空间名.相关元素id的形式。column="supervisor_id" 
  13.           属性不可少--> 
  14.           <association property="supervisor"        
  15.           resultMap="com.abc.mapper.TeacherMapper.supervisorResultMap" 
  16.           select="com.abc.mapper.TeacherMapper.getById" column="supervisor_id"/> 
  17.        </resultMap> 
  18.  
  19.        <!--根据指导教师id查询学生信息--> 
  20.        <select id="getStudents" parameterType="int"   
  21.          resultMap="studentResultMap"> 
  22.             select * from student where supervisor_id = #{id}  
  23.        </select> 
  24.        
  25.      </mapper> 

  
第三部分 :延迟加载

1、MyBatis的延迟加载机制需要使用cglib包,因此应向工程中添加此包,本文使用的是cglib-nodep-2.2.3.jar。

      2、在MyBatis的核心配置文件(在本示例中是configuration.xml)里的settings元素中添加以下配置:

  1. <setting name="lazyLoadingEnabled" value="true" /> 
  2. <setting name="aggressiveLazyLoading" value="false" /> 

      现在来对延迟加载进行测试。首先改造类CollectionDemo.java,让它先遍历查找到的教师,然后遍历某个教师指导的学生的信息

  1. //分页查询教师信息  
  2. List<Teacher> teachers =        mapper.findTeacherByPage(params);  
  3.  
  4. if(teachers == null)  
  5.   {  
  6.      System.out.println("未找到相关教师信息。");  
  7.   }  
  8. else 
  9.   {           
  10.      Object[] t = teachers.toArray();  
  11.      System.out.println("**********************************************");  
  12.  
  13.       for(int i = 0; i < t.length; i++)  
  14.     {  
  15.        teacher = (Teacher)t[i];  
  16.        System.out.println("教师姓名:" + "  " + teacher.getName());  
  17.             System.out.println("教师职称:" + "  " + teacher.getTitle());  
  18.        System.out.println("**********************************************");  
  19.     }  
  20.  
  21.    //遍历当前teacher对象指导的学生  
  22.    for(Student s : teacher.getSupStudents())  
  23.    {  
  24.      System.out.println( s.getName() + "  " +  s.getGender  () + "  " + s.getGrade()  
  25.            + "  " + s.getMajor());  
  26.    }  
  27. }    

     原文 http://legend2011.blog.51cto.com/3018495/973579


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章