首页 > 代码库 > mapper映射文件配置之select、resultMap(转载)

mapper映射文件配置之select、resultMap(转载)

先看select的配置吧:

  1. <select
  2.         <!-- 1. id (必须配置)
  3.         id是命名空间中的唯一标识符,可被用来代表这条语句。
  4.         一个命名空间(namespace) 对应一个dao接口,
  5.         这个id也应该对应dao里面的某个方法(相当于方法的实现),因此id 应该与方法名一致 -->
  6.  
  7.      id="selectPerson"
  8.  
  9.      <!-- 2. parameterType (可选配置, 默认为mybatis自动选择处理)
  10.         将要传入语句的参数的完全限定类名或别名, 如果不配置,mybatis会通过ParameterHandler 根据参数类型默认选择合适的typeHandler进行处理
  11.         parameterType 主要指定参数类型,可以是int, short, long, string等类型,也可以是复杂类型(如对象) -->
  12.      parameterType="int"
  13.  
  14.      <!-- 3. resultType (resultType 与 resultMap 二选一配置)
  15.          resultType用以指定返回类型,指定的类型可以是基本类型,可以是java容器,也可以是javabean -->
  16.      resultType="hashmap"
  17.  
  18.      <!-- 4. resultMap (resultType 与 resultMap 二选一配置)
  19.          resultMap用于引用我们通过 resultMap标签定义的映射类型,这也是mybatis组件高级复杂映射的关键 -->
  20.      resultMap="personResultMap"
  21.  
  22.      <!-- 5. flushCache (可选配置)
  23.          将其设置为 true,任何时候只要语句被调用,都会导致本地缓存和二级缓存都会被清空,默认值:false -->
  24.      flushCache="false"
  25.  
  26.      <!-- 6. useCache (可选配置)
  27.          将其设置为 true,将会导致本条语句的结果被二级缓存,默认值:对 select 元素为 true -->
  28.      useCache="true"
  29.  
  30.      <!-- 7. timeout (可选配置)
  31.          这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为 unset(依赖驱动)-->
  32.      timeout="10000"
  33.  
  34.      <!-- 8. fetchSize (可选配置)
  35.          这是尝试影响驱动程序每次批量返回的结果行数和这个设置值相等。默认值为 unset(依赖驱动)-->
  36.      fetchSize="256"
  37.  
  38.      <!-- 9. statementType (可选配置)
  39.          STATEMENT,PREPARED 或 CALLABLE 的一个。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED-->
  40.      statementType="PREPARED"
  41.  
  42.      <!-- 10. resultSetType (可选配置)
  43.          FORWARD_ONLY,SCROLL_SENSITIVE 或 SCROLL_INSENSITIVE 中的一个,默认值为 unset (依赖驱动)-->
  44.      resultSetType="FORWARD_ONLY">

注:resultType设置的是一个类型,如设置为map,那么sql的结果应该可以是Map(只有一行) ,或者ListMap),(有多行),对于java bean也是一样。其实对应的是Session对象的selectListselectOne方法。

 

配置看起来总是这么多,不过实际常用的配置也就那么几个, 根据自己的需要吧,上面都已注明是否必须配置。

下面还是上个demo及时练练手吧:

------------------------------------------------------------------------下面是针对select 的练手demo---------------------------------------------------------------------------------------

数据库:新增两张表(t_course, t_student

t_course:

技术分享

t_student:

技术分享

其中,1student可选择多个course进行学习。

我们还是拿上篇文章的demo, 继续写:

增加后,项目目录如下所示:

技术分享

   

Course.java:

  1. package com.dy.entity;
  2.  
  3. public class Course {
  4.  
  5.     private int id;
  6.     private String name;
  7.     private int deleteFlag;
  8.  
  9.     public int getId() {
  10.         return id;
  11.     }
  12.     public void setId(int id) {
  13.         this.id = id;
  14.     }
  15.     public String getName() {
  16.         return name;
  17.     }
  18.     public void setName(String name) {
  19.         this.name = name;
  20.     }
  21.     public int getDeleteFlag() {
  22.         return deleteFlag;
  23.     }
  24.     public void setDeleteFlag(int deleteFlag) {
  25.         this.deleteFlag = deleteFlag;
  26.     }
  27.  
  28. }

Student.java:

  1. package com.dy.entity;
  2.  
  3. import java.util.List;
  4.  
  5. public class Student {
  6.  
  7.     private int id;
  8.     private String idCard;
  9.     private String name;
  10.     private List<Course> courseList;
  11.     private int deleteFlag;
  12.  
  13.     public Student(int id, String idCard, String name, List<Course> courseList, int deleteFlag) {
  14.         this.id = id;
  15.         this.idCard = idCard;
  16.         this.name = name;
  17.         this.courseList = courseList;
  18.         this.deleteFlag = deleteFlag;
  19.     }
  20.  
  21.     public int getId() {
  22.         return id;
  23.     }
  24.     public void setId(int id) {
  25.         this.id = id;
  26.     }
  27.     public String getIdCard() {
  28.         return idCard;
  29.     }
  30.     public void setIdCard(String idCard) {
  31.         this.idCard = idCard;
  32.     }
  33.     public String getName() {
  34.         return name;
  35.     }
  36.     public void setName(String name) {
  37.         this.name = name;
  38.     }
  39.     public List<Course> getCourseList() {
  40.         return courseList;
  41.     }
  42.     public void setCourseList(List<Course> courseList) {
  43.         this.courseList = courseList;
  44.     }
  45.     public int getDeleteFlag() {
  46.         return deleteFlag;
  47.     }
  48.     public void setDeleteFlag(int deleteFlag) {
  49.         this.deleteFlag = deleteFlag;
  50.     }
  51. }

CourseDao.java:

  1. package com.dy.dao;
  2.  
  3. import com.dy.entity.Course;
  4.  
  5. public interface CourseDao {
  6.  
  7.     public Course findCourseById(int courseId);
  8.  
  9. }

StudentDao.java:

  1. package com.dy.dao;
  2.  
  3.  
  4. import com.dy.entity.Student;
  5.  
  6. public interface StudentDao {
  7.  
  8.     public Student findStudentById(String idCard);
  9. }

courseDao.xml:

  1. <mapper namespace="com.dy.dao.CourseDao">
  2.  
  3.     <!--
  4.         1.此处直接将resultType 设置为course, 一看就知道我设置了别名吧,如果没有设置别名,那么resultType = com.dy.entity.Course。
  5.          2.可能细心的你会发现:Course.java中的属性名与数据库字段名不一致,下面,我就在sql语句中用了as, 使之匹配,当然方法不止一种,
  6.              在学习了resultMap之后,你能看到一种更直观优雅的方式去将javabean中的属性与数据库字段名保持一致
  7.          3.findCourseById 与CourseDao中findCourseById方法对应, 那么传入的参数名称以及类型也应该保持对应关系。
  8.          4.可以看到,在sql语句中,通过#{}表达式可以获取参数。
  9.          5.下面这条sql语句,实际上的形式是怎么样的?还记得之前说过,mybatis默认为preparedStatement吧,那么,用我们jdbc代码来看,它其实就是:
  10.              select course_id as id, course_name as name, course_delete_flg as deleteFlag from t_course where course_id=?
  11.      -->
  12.     <select id="findCourseById" resultType="course" >
  13.         select course_id as id, course_name as name, course_delete_flg as deleteFlag from t_course where course_id=#{courseId}
  14.     </select>
  15.  
  16. </mapper>

CourseDaoTest.java:

  1. package com.dy.dao;
  2.  
  3. import java.io.IOException;
  4.  
  5. import org.apache.ibatis.io.Resources;
  6. import org.apache.ibatis.session.SqlSession;
  7. import org.apache.ibatis.session.SqlSessionFactory;
  8. import org.apache.ibatis.session.SqlSessionFactoryBuilder;
  9. import org.junit.Test;
  10.  
  11. import com.dy.entity.Course;
  12.  
  13. public class CourseDaoTest {
  14.  
  15.     @Test
  16.     public void findCourseById() {
  17.         SqlSessionFactory sqlSessionFactory = getSessionFactory();
  18.         SqlSession sqlSession = sqlSessionFactory.openSession();
  19.         CourseDao courseDao = sqlSession.getMapper(CourseDao.class);
  20.         Course course = courseDao.findCourseById(1);
  21.     }
  22.  
  23.  
  24.     //Mybatis 通过SqlSessionFactory获取SqlSession, 然后才能通过SqlSession与数据库进行交互
  25.     private static SqlSessionFactory getSessionFactory() {
  26.         SqlSessionFactory sessionFactory = null;
  27.         String resource = "mybatis-conf.xml";
  28.         try {
  29.             sessionFactory = new SqlSessionFactoryBuilder().build(Resources
  30.                     .getResourceAsReader(resource));
  31.         } catch (IOException e) {
  32.             e.printStackTrace();
  33.         }
  34.         return sessionFactory;
  35.     }
  36. }

上面的示例,我们针对course, 简单演示了 select的用法, 不过有个问题值得思考: 一个student可以对应多个course,  那么,在mybatis中如何处理这种一对多, 甚至于多对多,一对一的关系呢?

这儿,就不得不提到 resultMap 这个东西, mybatisresultMap功能可谓十分强大,能够处理复杂的关系映射, 那么resultMap 该怎么配置呢? 别急,这就来了:

resultMap的配置:

  1. <!--
  2.         1.type 对应类型,可以是javabean, 也可以是其它
  3.         2.id 必须唯一, 用于标示这个resultMap的唯一性,在使用resultMap的时候,就是通过id指定
  4.      -->
  5.     <resultMap type="" id="">
  6.  
  7.         <!-- id, 唯一性,注意啦,这个id用于标示这个javabean对象的唯一性, 不一定会是数据库的主键(不要把它理解为数据库对应表的主键)
  8.             property属性对应javabean的属性名,column对应数据库表的列名
  9.             (这样,当javabean的属性与数据库对应表的列名不一致的时候,就能通过指定这个保持正常映射了)
  10.         -->
  11.         <id property="" column=""/>
  12.  
  13.         <!-- result与id相比, 对应普通属性 -->
  14.         <result property="" column=""/>
  15.  
  16.         <!--
  17.             constructor对应javabean中的构造方法
  18.          -->
  19.         <constructor>
  20.             <!-- idArg 对应构造方法中的id参数 -->
  21.             <idArg column=""/>
  22.             <!-- arg 对应构造方法中的普通参数 -->
  23.             <arg column=""/>
  24.         </constructor>
  25.  
  26.         <!--
  27.             collection,对应javabean中容器类型, 是实现一对多的关键
  28.             property 为javabean中容器对应字段名
  29.             column 为体现在数据库中列名
  30.             ofType 就是指定javabean中容器指定的类型
  31.         -->
  32.         <collection property="" column="" ofType=""></collection>
  33.  
  34.         <!--
  35.             association 为关联关系,是实现N对一的关键。
  36.             property 为javabean中容器对应字段名
  37.             column 为体现在数据库中列名
  38.             javaType 指定关联的类型
  39.          -->
  40.         <association property="" column="" javaType=""></association>
  41.     </resultMap>

好啦,知道resutMap怎么配置后,咱们立即接着上面的demo来练习一下吧:

------------------------------------------------------------------下面是用resultMap处理一对多关系的映射的示例-------------------------------------------------------------

一个student对应多个course 典型的一对多,咱们就来看看mybatis怎么配置这种映射吧:

studentDao.xml:

  1. <mapper namespace="com.dy.dao.StudentDao">
  2.  
  3.     <!-- 这儿定义一个resultMap -->
  4.     <resultMap type="student" id="studentMap">
  5.  
  6.         <!--
  7.             数据库中主键是id, 但是我这儿却是指定idCard为主键,为什么?
  8.             刚刚讲了,id用来表示唯一性, 我们可以认为只要idCard一样,那么他就是同一个学生。
  9.             如果此处用数据库中id, 那么mybatis将会认为数据库中每条记录都是一个student, 这显然不符合逻辑
  10.         -->
  11.         <id property="idCard" column="stu_id_card"/>
  12.         <result property="id" column="stu_id"/>
  13.         <result property="name" column="stu_name"/>
  14.         <result property="deleteFlag" column="stu_delete_flg"/>
  15.  
  16.         <!--
  17.             这儿就是实现一对多的关键。
  18.             在Student中,courseList为List<Course>, 因此,ofType也应该与之对应(当然,我用了别名,不然要蛋疼的写全名了)。
  19.             collection的子标签是在指定Course的映射关系(由于Course的javabean的属性名与数据库的列名不一致)
  20.         -->
  21.         <collection property="courseList" column="stu_course_id" ofType="Course">
  22.             <id property="id" column="course_id"/>
  23.             <result property="name" column="course_name"/>
  24.             <result property="deleteFlag" column="course_delete_flg"/>
  25.         </collection>
  26.     </resultMap>
  27.  
  28.     <!-- 这儿将返回类型设置成了上面指定的studentMap -->
  29.     <select id="findStudentById" resultMap="studentMap">
  30.         SELECT s.*, c.* FROM t_student s LEFT JOIN t_course c ON s.stu_course_id=c.course_id WHERE s.stu_id_card=#{idCard}
  31.     </select>
  32.  
  33. </mapper>

StudentDaoTest.java:

  1. package com.dy.dao;
  2.  
  3. import java.io.IOException;
  4. import java.util.List;
  5.  
  6. import org.apache.ibatis.io.Resources;
  7. import org.apache.ibatis.session.SqlSession;
  8. import org.apache.ibatis.session.SqlSessionFactory;
  9. import org.apache.ibatis.session.SqlSessionFactoryBuilder;
  10. import org.junit.Test;
  11.  
  12. import com.dy.entity.Course;
  13. import com.dy.entity.Student;
  14.  
  15. public class StudentDaoTest {
  16.  
  17.     @Test
  18.     public void findCourseById() {
  19.         SqlSessionFactory sqlSessionFactory = getSessionFactory();
  20.         SqlSession sqlSession = sqlSessionFactory.openSession();
  21.         StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
  22.         Student student = studentDao.findStudentById("20140101");
  23.         List<Course> courseList = student.getCourseList();
  24.         for (Course course: courseList) {
  25.             System.out.println(course.getId() + " " + course.getName());
  26.         }
  27.     }
  28.  
  29.  
  30.     //Mybatis 通过SqlSessionFactory获取SqlSession, 然后才能通过SqlSession与数据库进行交互
  31.     private static SqlSessionFactory getSessionFactory() {
  32.         SqlSessionFactory sessionFactory = null;
  33.         String resource = "mybatis-conf.xml";
  34.         try {
  35.             sessionFactory = new SqlSessionFactoryBuilder().build(Resources
  36.                     .getResourceAsReader(resource));
  37.         } catch (IOException e) {
  38.             e.printStackTrace();
  39.         }
  40.         return sessionFactory;
  41.     }
  42. }

 关联映射在我的项目里很少用到,一般的查询不是两张表能够解决的。对于报表统计的复杂查询,可以直接写sql语句,然后把returntype设置为map,就可以得到一个list<map>。传入的参数,可以设置为map。参考文章http://lafecat.iteye.com/blog/2218977

相信通过以上demo 大家也能够使用mybatisselect resultMap的用法了。上面demo只演示了一对多的映射,其实多对一、多对多也与它类似,所以我就没演示了,有兴趣的可以自己动手再做做。

mapper映射文件配置之select、resultMap(转载)