第一部分 示例
一、爲Teacher實體增加相關屬性
爲教師實體增加指導學生集合的屬性如下:
- private List<Student> supStudents;
併爲其增加setter和getter方法,這裏略過。
二、TeacherMapper接口
爲實現教師實體映射,應先創建映射器接口如下:
- package com.abc.mapper;
-
- import com.abc.domain.Teacher;
-
- public interface TeacherMapper {
-
- public Teacher getById(int id);
-
- }
三、映射文件
爲教師實體創建的映射文件如下:
- <?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.TeacherMapper">
-
- <!--TeacherMapper接口中getById方法對應的SQL語句。
- 查詢教師及其指導的學生的信息。由於教師、學生都有
- id、name、gender等屬性,因此給教師的字段都起了別名-->
- <select id="getById" parameterType="int" resultMap="supervisorResultMap">
- select t.id t_id, t.name t_name, t.gender t_gender,
- t.research_area t_research_area, t.title t_title,
- s.id,s.name, s.gender,s.major,s.grade
- from teacher t,student s where t.id=#{id}
- and s.supervisor_id = t.id
- </select>
-
-
- <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"/>
- <!--collection元素映射教師的指導學生集合的屬性。resultMap
- 以命名空間名.resultMap的id的形式,引用studentResultMap。
- 需要注意的是,上面的select語句中學生的字段名/別名應與
- studentResultMap中的column屬性一致-->
- <collection property="supStudents"
- resultMap="com.abc.mapper.StudentMapper.studentResultMap"/>
- </resultMap>
-
- </mapper>
相應地,學生實體的映射文件如下:
- <?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">
-
- <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"/>
- <!--相應地,在此引用supervisorResultMap,亦採用
- 命名空間名.resultMap的id的形式。-->
- <association property="supervisor"
- resultMap="com.abc.mapper.TeacherMapper.supervisorResultMap"/>
- </resultMap>
-
- </mapper>
在工程的src\resources目錄下新建子目錄mappers,用來統一存放映射文件。爲了能讓MyBatis找到這些映射文件,修改其核心配置文件configuration.xml中的mappers元素如下:
-
- <mappers>
- <mapper resource="resources/mappers/StudentMapper.xml"/>
- <mapper resource="resources/mappers/TeacherMapper.xml"/>
- </mappers>
注意:resources目錄在工程編譯前會被複制到classes目錄下(詳見工程生成文件build.xml中的copy-resources和compile這兩個target),而classes目錄會被ant添加到classpath中。
四、執行類
執行類爲CollectionDemo,其內容如下:
- package com.demo;
-
- import org.springframework.context.ApplicationContext;
- import com.abc.mapper.StudentMapper;
- import com.abc.mapper.TeacherMapper;
- import com.abc.domain.Teacher;
- import com.abc.domain.Student;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- import java.util.List;
-
- public class CollectionDemo
- {
- private static ApplicationContext ctx;
-
- static
- {
-
- ctx = new ClassPathXmlApplicationContext("resources/beans.xml");
- }
-
-
- public static void main(String[] args)
- {
-
- TeacherMapper mapper =
- (TeacherMapper)ctx.getBean("teacherMapper");
-
-
- Teacher teacher = mapper.getById(1);
-
- if(teacher == null)
- {
- System.out.println("未找到相關教師信息。");
- }
- else
- {
-
- System.out.println("**********************************************");
- System.out.println("教師姓名:" + " " + teacher.getName());
- System.out.println("教師職稱:" + " " + teacher.getTitle());
- System.out.println("**********************************************");
-
- System.out.println("指導學生信息:");
-
- for(Student s : teacher.getSupStudents())
- {
- System.out.println("**********************************************");
- System.out.println( s.getName() + " " + s.getGender() + " " + s.getGrade()
- + " " + s.getMajor());
-
- System.out.println("指導教師研究方向:" + s.getSupervisor().getResearchArea());
-
- }
-
- System.out.println("**********************************************");
- }
-
- }
-
- }
從中可看出,可以從任意一端訪問另一端的對象。
第二部分 :上面是比較典型的使用方式,還有其他方式即:嵌套的Select,但是會產生 N+1的問題
(1) association 中嵌套select
- <?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_area
- from 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>
(2)collection 中嵌套select
二、嵌套的select語句
- <?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.TeacherMapper">
-
- <!--TeacherMapper接口中getById方法對應的SQL語句。
- 查詢教師的信息。-->
- <select id="getById" parameterType="int" resultMap="supervisorResultMap">
- select * from teacher where id=#{id}
- </select>
-
-
- <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"/>
- <!--ofType指collection包含的元素的類型,此屬性不可少。
- column屬性指把上述的getById的select語句中的教師id列的值作爲參數
- 傳遞給將要引用到的下述的getStudents的select語句,此屬性不可少。
- 引用的形式爲:命名空間.select語句id-->
- <collection property="supStudents" column="id" ofType="Student"
- select="com.abc.mapper.StudentMapper.getStudents"/>
- </resultMap>
-
- </mapper>
在這裏把根據指導教師id查詢學生信息的SQL語句寫在StudentMapper.xml中,並引用其中的學生實體映射studentResultMap。修改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">
-
- <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"/>
- <!--在這裏引用supervisorResultMap和getById,亦採用
- 命名空間名.相關元素id的形式。column="supervisor_id"
- 屬性不可少-->
- <association property="supervisor"
- resultMap="com.abc.mapper.TeacherMapper.supervisorResultMap"
- select="com.abc.mapper.TeacherMapper.getById" column="supervisor_id"/>
- </resultMap>
-
-
- <select id="getStudents" parameterType="int"
- resultMap="studentResultMap">
- select * from student where supervisor_id = #{id}
- </select>
-
- </mapper>
第三部分 :延遲加載
1、MyBatis的延遲加載機制需要使用cglib包,因此應向工程中添加此包,本文使用的是cglib-nodep-2.2.3.jar。
2、在MyBatis的核心配置文件(在本示例中是configuration.xml)裏的settings元素中添加以下配置:
- <setting name="lazyLoadingEnabled" value="true" />
- <setting name="aggressiveLazyLoading" value="false" />
現在來對延遲加載進行測試。首先改造類CollectionDemo.java,讓它先遍歷查找到的教師,然後遍歷某個教師指導的學生的信息
-
- List<Teacher> teachers = mapper.findTeacherByPage(params);
-
- if(teachers == null)
- {
- System.out.println("未找到相關教師信息。");
- }
- else
- {
- Object[] t = teachers.toArray();
- System.out.println("**********************************************");
-
- for(int i = 0; i < t.length; i++)
- {
- teacher = (Teacher)t[i];
- System.out.println("教師姓名:" + " " + teacher.getName());
- System.out.println("教師職稱:" + " " + teacher.getTitle());
- System.out.println("**********************************************");
- }
-
-
- for(Student s : teacher.getSupStudents())
- {
- System.out.println( s.getName() + " " + s.getGender () + " " + s.getGrade()
- + " " + s.getMajor());
- }
- }
原文 http://legend2011.blog.51cto.com/3018495/973579