:本文转载自南轲梦

注:博主 Chloneda个人博客 | 博客园 | Github | Gitee | 知乎

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

先看select的配置吧:

select配置

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

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

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

数据库:新增两张表(t_course, t_student),以下为相关实体类。

Course.java

  1. public class Course {
  2. private int id;
  3. private String name;
  4. private int deleteFlag;
  5. //setter和getter方法省略...
  6. }

Student.java

  1. public class Student {
  2. private int id;
  3. private String idCard;
  4. private String name;
  5. private List<Course> courseList;
  6. private int deleteFlag;
  7. //setter和getter方法省略...
  8. }

CourseDao.java

  1. public interface CourseDao {
  2. public Course findCourseById(int courseId);
  3. }

StudentDao.java

  1. public interface StudentDao {
  2. public Student findStudentById(String idCard);
  3. }

courseDao.xml

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

CourseDaoTest.java

  1. public class CourseDaoTest {
  2. @Test
  3. public void findCourseById() {
  4. SqlSessionFactory sqlSessionFactory = getSessionFactory();
  5. SqlSession sqlSession = sqlSessionFactory.openSession();
  6. CourseDao courseDao = sqlSession.getMapper(CourseDao.class);
  7. Course course = courseDao.findCourseById(1);
  8. }
  9. //Mybatis 通过SqlSessionFactory获取SqlSession, 然后才能通过SqlSession与数据库进行交互
  10. private static SqlSessionFactory getSessionFactory() {
  11. SqlSessionFactory sessionFactory = null;
  12. String resource = "mybatis-conf.xml";
  13. try {
  14. sessionFactory = new SqlSessionFactoryBuilder().build(Resources
  15. .getResourceAsReader(resource));
  16. } catch (IOException e) {
  17. e.printStackTrace();
  18. }
  19. return sessionFactory;
  20. }
  21. }

上面的示例,我们针对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. 不一定会是数据库的主键(不要把它理解为数据库对应表的主键)
  9. property属性对应javabean的属性名,column对应数据库表的列名
  10. (这样,当javabean的属性与数据库对应表的列名不一致的时候,就能通过指定这个保持正常映射了)
  11. -->
  12. <id property="" column=""/>
  13. <!-- result与id相比, 对应普通属性 -->
  14. <result property="" column=""/>
  15. <!--
  16. constructor对应javabean中的构造方法
  17. -->
  18. <constructor>
  19. <!-- idArg 对应构造方法中的id参数 -->
  20. <idArg column=""/>
  21. <!-- arg 对应构造方法中的普通参数 -->
  22. <arg column=""/>
  23. </constructor>
  24. <!--
  25. collection,对应javabean中容器类型, 是实现一对多的关键
  26. property 为javabean中容器对应字段名
  27. column 为体现在数据库中列名
  28. ofType 就是指定javabean中容器指定的类型
  29. -->
  30. <collection property="" column="" ofType=""></collection>
  31. <!--
  32. association 为关联关系,是实现N对一的关键。
  33. property 为javabean中容器对应字段名
  34. column 为体现在数据库中列名
  35. javaType 指定关联的类型
  36. -->
  37. <association property="" column="" javaType=""></association>
  38. </resultMap>

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

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

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

studentDao.xml

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

StudentDaoTest.java

  1. public class StudentDaoTest {
  2. @Test
  3. public void findCourseById() {
  4. SqlSessionFactory sqlSessionFactory = getSessionFactory();
  5. SqlSession sqlSession = sqlSessionFactory.openSession();
  6. StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
  7. Student student = studentDao.findStudentById("20140101");
  8. List<Course> courseList = student.getCourseList();
  9. for (Course course: courseList) {
  10. System.out.println(course.getId() + " " + course.getName());
  11. }
  12. }
  13. //Mybatis 通过SqlSessionFactory获取SqlSession, 然后才能通过SqlSession与数据库进行交互
  14. private static SqlSessionFactory getSessionFactory() {
  15. SqlSessionFactory sessionFactory = null;
  16. String resource = "mybatis-conf.xml";
  17. try {
  18. sessionFactory = new SqlSessionFactoryBuilder().build(Resources
  19. .getResourceAsReader(resource));
  20. } catch (IOException e) {
  21. e.printStackTrace();
  22. }
  23. return sessionFactory;
  24. }
  25. }

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


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

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

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

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

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

  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. k8s系列---存储卷pv/pvc。configMap/secert

    因为pod是有生命周期的,pod一重启,里面的数据就没了.所以我们需要数据持久化存储. 在k8s中,存储卷不属于容器,而是属于pod.也就是说同一个pod中的容器可以共享一个存储卷. 存储卷可以是宿主 ...

  2. 使用 pyenv 管理不同的 Python 版本

    1. pyenv 的安装 $ yum install git -y $ yum install gcc make patch gdbm-devel openssl-devel sqlite-devel ...

  3. chromedriver和firefox driver的安装过程

    环境:ubuntu14.04, python2.7 selenium2.0 文章参考出处:http://blog.csdn.net/heybob/article/details/52922645 ch ...

  4. light oj 1035 - Intelligent Factorial Factorization 素因子分解

    1035 - Intelligent Factorial Factorization Given an integer N, you have to prime factorize N! (facto ...

  5. Yet Another Broken Keyboard[双指针]

    题目大意: 求贡献,已知公式n*(n+1)/2,求总和 收获: long long的转换技巧只能在乘或除上进行 题目链接 #include<bits/stdc++.h> typedef l ...

  6. git的使用方法大全

    换了一个新的工作环境,由于以前都是使用SVN管理代码,现在要换成git,但我对git了解不多,只好下功夫咯!脑子不灵活,命令语句容易忘,所以做个笔记记录下~~~1.安装git到Git官网下载合适自己电 ...

  7. 刷题94. Binary Tree Inorder Traversal

    一.题目说明 题目94. Binary Tree Inorder Traversal,给一个二叉树,返回中序遍历序列.题目难度是Medium! 二.我的解答 用递归遍历,学过数据结构的应该都可以实现. ...

  8. R12客户表结构分析

    客户表/联系人/PARTY关联   HZ_PARTIES 客户账户表   HZ_CUST_ACCOUNTS 例子:    select hp.party_number --客户注册标识         ...

  9. Java学习随笔---常用API(二)

    Object类的toString方法 将一个对象返回为字符串形式,但一般使用的时候会覆盖重写toString方法 Object类是所有类的父亲 // public class Person { pri ...

  10. Jstree在加载时和加载完成的回调方法-sunziren

    1.有时候在使用jstree的时候我们想在它加载完成后立刻执行某个方法,于是我们可以用下面这个jstree自带的回调: .on('ready.jstree', function(event, obj) ...