上篇《深入浅出Mybatis系列(七)---mapper映射文件配置之insert、update、delete》介绍了insert、update、delete的用法,本篇将介绍select、resultMap的用法。select无疑是我们最常用,也是最复杂的,mybatis通过resultMap能帮助我们很好地进行高级映射。下面就开始看看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">

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

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

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

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

t_course:

t_student:

其中,1个student可选择多个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. import com.dy.entity.Student;
  4.  
  5. public interface StudentDao {
  6.  
  7. public Student findStudentById(String idCard);
  8. }

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. //Mybatis 通过SqlSessionFactory获取SqlSession, 然后才能通过SqlSession与数据库进行交互
  24. private static SqlSessionFactory getSessionFactory() {
  25. SqlSessionFactory sessionFactory = null;
  26. String resource = "mybatis-conf.xml";
  27. try {
  28. sessionFactory = new SqlSessionFactoryBuilder().build(Resources
  29. .getResourceAsReader(resource));
  30. } catch (IOException e) {
  31. e.printStackTrace();
  32. }
  33. return sessionFactory;
  34. }
  35. }

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

这儿,就不得不提到 resultMap 这个东西, mybatis的resultMap功能可谓十分强大,能够处理复杂的关系映射, 那么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. //Mybatis 通过SqlSessionFactory获取SqlSession, 然后才能通过SqlSession与数据库进行交互
  30. private static SqlSessionFactory getSessionFactory() {
  31. SqlSessionFactory sessionFactory = null;
  32. String resource = "mybatis-conf.xml";
  33. try {
  34. sessionFactory = new SqlSessionFactoryBuilder().build(Resources
  35. .getResourceAsReader(resource));
  36. } catch (IOException e) {
  37. e.printStackTrace();
  38. }
  39. return sessionFactory;
  40. }
  41. }

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

好啦,本次就写到这儿了。(PS,生病一周了,所以到现在才更新博客)。

另附上demo, 需要的童鞋可以前往下载:

demo 下载地址:http://pan.baidu.com/s/1qWjsDzA

深入浅出Mybatis系列(八)---mapper映射文件配置之select、resultMap的更多相关文章

  1. 深入浅出Mybatis系列八-mapper映射文件配置之select、resultMap

    注:本文转载自南轲梦 注:博主 Chloneda:个人博客 | 博客园 | Github | Gitee | 知乎 上篇<深入浅出Mybatis系列(七)---mapper映射文件配置之inse ...

  2. 深入浅出Mybatis系列七-mapper映射文件配置之insert、update、delete

    注:本文转载自南轲梦 注:博主 Chloneda:个人博客 | 博客园 | Github | Gitee | 知乎 上篇文章<深入浅出Mybatis系列(六)---objectFactory.p ...

  3. 深入浅出Mybatis系列(八)---mapper映射文件配置之select、resultMap good

    上篇<深入浅出Mybatis系列(七)---mapper映射文件配置之insert.update.delete>介绍了insert.update.delete的用法,本篇将介绍select ...

  4. 深入浅出Mybatis系列(八)---mapper映射文件配置之select、resultMap[转]

    上篇<深入浅出Mybatis系列(七)---mapper映射文件配置之insert.update.delete>介绍了insert.update.delete的用法,本篇将介绍select ...

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

    原文地址:http://www.cnblogs.com/dongying/p/4073259.html 先看select的配置吧: <select         <!-- 1. id ( ...

  6. 深入浅出Mybatis系列(七)---mapper映射文件配置之insert、update、delete

    上篇文章<深入浅出Mybatis系列(六)---objectFactory.plugins.mappers简介与配置>简单地给mybatis的配置画上了一个句号.那么从本篇文章开始,将会介 ...

  7. mapper映射文件配置之insert、update、delete(转载)

    原文地址:http://www.cnblogs.com/dongying/p/4048828.html 在mapper文件中,以mapper作为根节点,其下面可以配置的元素节点有: select, i ...

  8. 深入浅出Mybatis系列五-TypeHandler简介及配置(mybatis源码篇)

    注:本文转载自南轲梦 注:博主 Chloneda:个人博客 | 博客园 | Github | Gitee | 知乎 上篇文章<深入浅出Mybatis系列(四)---配置详解之typeAliase ...

  9. Mybatis将mapper映射文件配置到recources下

    关于为什么要将Mybatis的mappers.xml文件配置到resources目录下的粗浅看法: (1).使文件目录更加清晰.resources文件目录下通常为配置文件,所以将Mappers.xml ...

随机推荐

  1. mySQL函数根据经纬度计算两点距离

    DROP FUNCTION IF EXISTS func_calcDistance ; CREATE FUNCTION func_calcDistance( origLng ,), -- 目的地经度 ...

  2. mysqli链接数据库:面向对象

    $mysqli = new mysqli('localhost','root','123','test');//检查连接是否成功if (mysqli_connect_error()){ //注意mys ...

  3. 启动tomcat时,报错:IOException while loading persisted sessions: java.io.EOFException解决方法

    报错原因:加载持久化session错误,tomcat加载时读取的文件是是*.ser,session序列化文件,文件的位置是tomcat\work\Catalina\localhost,找到sessio ...

  4. html5本地存储(localStorage)使用介绍

    1.html5几种存储形式 本地存储(localStorage && sessionStorage) 离线缓存(application cache) indexedDB 和 webSQ ...

  5. [issue] [iOS 10] 升级后无法真机测试 Could not find Developer Disk Image

    说明:更新了手机的到了iOS 10.0.2.真机调试时候提示"Could not find Developer Disk Image" 并且之前就下载了Xcode8,但是没有安装X ...

  6. 彻底卸载Visual Studio 2013、Visual Studio 2015

    彻底卸载 Visual Studio 2013. Visual Studio 2015 以及后续各种版本使用方法0. 解压下载的 TotalUninstaller.zip 文件1. 使用 admini ...

  7. Analyzer中进行货币转换

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...

  8. C# 文件及文件夹深度复制

    完善了下 文件中的文件及文件夹中的复制!如果有更优解决方案请不吝指教 protected void FileDepthCopy(string source, string target){ if (D ...

  9. Reactor事件驱动的两种设计实现:面向对象 VS 函数式编程

    Reactor事件驱动的两种设计实现:面向对象 VS 函数式编程 这里的函数式编程的设计以muduo为例进行对比说明: Reactor实现架构对比 面向对象的设计类图如下: 函数式编程以muduo为例 ...

  10. kafka使用getOffsetsBefore()获取获取offset异常分析

    根据时间戳获取kafka的topic的偏移量,结果获取的偏移量量数据组的长度为0,就会出现如下的数组下标越界的异常,实现的原理是使用了kafka的getOffsetsBefore()方法: Excep ...