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


    原文地址:http://www.cnblogs.com/dongying/p/4073259.html

    先看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只演示了一对多的映射,其实多对一、多对多也与它类似,所以我就没演示了,有兴趣的可以自己动手再做做。

    注:mybatis还支持注解式的定义。使用方法是在interface的方法上直接使用注解来写sql,这种方式我不建议使用,因为SQL语句可能很长,而且设计格式化的问题,还是xml中一目了然。

    Mapper接口开发需要遵循以下规范:

    • Mapper.xml文件中的namespace与mapper接口的类路径相同。
    • Mapper接口方法名和Mapper.xml中定义的每个statement的id相同 
    • Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同
    • Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同
  • 相关阅读:
    休息一会。。。。。。
    iPhone开发之webview 拖动和显示本地图片的几组代码
    Android 防止手机休眠
    Android数据存储SQLite 事务操作
    解决png图片在IE6下的透明问题
    教你如何在博客园放“可运行"代码
    弹出层原理
    右键集成JS文件压缩 YUI Compressor
    原来window.event快达到全浏览器支持了
    QWrap入门指南
  • 原文地址:https://www.cnblogs.com/xiaolang8762400/p/7011663.html
Copyright © 2020-2023  润新知