我是靠谱客的博主 舒心机器猫,最近开发中收集的这篇文章主要介绍Mybatis-XxxMapper.xml配置文件一、了解内容二、映射配置文件Mapper.xml,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

一、了解内容

  • 配置Mybatis两种方式:

    • 第一种:Mybatis通过读取mybatis-config.xml文件配置mybatis,通过动态读取配置文件,调用SqlSessionFactoryBuilder的bulid方法获取配置文件字节流获得SqlSessionFactory,创建SqlSession实现类DefultSqlSession的对象,动态代理去执行sql方法

    • 第二种:使用Java API配置Mybatis,不去配置任何信息直接把信息写在代码中,然后在按着之前的顺序创建出我们需要的SqlSessionFactory,再进一步得到sqlSession,最后再进行各种数据库操作

      例如:使用Java API创建SqlSessionFactory对象,之前是读取配置文件之后再创建,现在是自己把信息写到代码中,然后再创建该对象
      public static SqlSessionFactory getSqlSessionFactory() {
      SqlSessionFactory sqlSessionFactory = null;
      try {
      DataSourcedata Source = DataSourceFactory.getDataSource();
      TransactionFactory transactionFactory = new JdbcTransactionFactory();
      Environment environment = new Environment("development", transactionFactory, dataSource);
      Configuration configuration = new Configuration(environment);
      configuration.getTypeAliasRegistry().registerAlias("student",Student.class);
      configuration.getTypeHandlerRegistry().register(PhoneNumber.class, PhoneTypeHandler.class);
      configuration.addMapper(StudentMapper.class);
      sqlSessionFactory = new SqlSessionFactoryBuilder().
      build(configuration);
      }
      catch (Exception e) {
      throw new RuntimeException(e);
      }
      return sqlSessionFactory;
      }
      
      • 缺点:将Mapper.xml的sql语句的配置信息写死了,降低了代码的灵活性
  • 自定义MyBatis日志

  • MyBatis使用其内部LogFactory作为真正的日志类库使用的门面。其内部的LaggerFactory会将日志记录任务委托给如下的所示某一个日志实现,日志记录优先级由上到下顺序递减:

    1. SLF4J

    2. Apache Commons Logging

    3. Log4j2

    4. Log4j

    5. JDK logging

      注意:查看org.apache.ibatis.logging.LogFactory源码可知

  • 如果MyBatis未发现上述日志记录实现,则MyBatis的日志记录功能无效,如果你的运行环境中,在classpath中有多个可用的日志类库,并且你希望MyBaits使用某个特定的日志实现,你可以在代码中通过调用以下其中一个方法:

    org.apache.ibatis.logging.LogFactory.useSlf4jLogging();
    org.apache.ibatis.logging.LogFactory.useLog4JLogging();
    org.apache.ibatis.logging.LogFactory.useLog4J2Logging();
    org.apache.ibatis.logging.LogFactory.useJdkLogging();
    org.apache.ibatis.logging.LogFactory.useCommonsLogging();
    org.apache.ibatis.logging.LogFactory.useStdOutLogging();
    
  • 注:如果你想自定义MyBatis日志记录,你应该在调用任何其它方法之前调用以上的其中一个方法

二、映射配置文件Mapper.xml

  • Sql语句调用方式有两种:需要配置映射文件StudentMapper.xml和XxxMapper.java映射接口

    • 第一种:通过按照sql语句需求根据SqlSession中的对应方法,传入方法的参数(全包名限定+映射xml的 sql标签id,参数),执行sql语句
      • 使用字符串形式调用sql语句,即使接口中没有对应方法名,也不影响执行SQL语句
    • 第二种:通过动态代理,有SqlSession的DefaultSQLSession实现类通过层层调用,反射newInstance创建出映射接口对象,调用接口对应xml(CURD标签的id和方法名相同)文件中,操作数据库
  • 第一种方式:映射接口全包名,调用SQLSession中sql方法

  • 映射文件StudentMapper.xml中有id为"findStudentById"的SQL语句,代码如下:

    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.briup.mappers.StudentMapper">
    <select id="findStudentById" parameterType="int" resultType="Student">
    select stud_id as studId, name, email, dob
    from students where stud_id=#{studId}
    </select>
    </mapper>
    通过字符串,调用映射文件中的SQL语句
    字符串形式为:
    映射文件的namespace + sql语句的id
    例如:
    SqlSession sqlSession = MyBatisSqlSessionFactory.openSession();
    try{
    Student student = sqlSession.selectOne("com.briup.mappers.StudentMapper.findStudentById", 1);
    System.out.println(student);
    }
    finally {
    sqlSession.close();
    }
    这种方式容易出错
    因为需要自己编写字符串,我们需要检查映射文件中namespace,
    sql语句定义中对参数和返回值的要求,以保证输入的参数类型和结果返回类型是有效的。
    
  • 第二种:MyBatis中还可以通过使用映射接口Mapper,调用映射文件中的sql

    • 对应的规范:

      1. sql映射文件中的namespace和映射接口的全限定名要保持一致。

      2. sql映射文件中的sql语句id值和映射接口中的方法名要保持一致。

      3. sql语句配置的parameterType属性和映射接口中对应的方法的参数类型保持一致。

      4. sql语句配置的returnType属性和映射接口中对应的方法的返回值类型保持一致。

        例如:映射接口StudentMapper.java
        package com.briup.mappers;
        public interface StudentMapper{
        Student findStudentById(Integer id);
        }
        通过映射接口,调用映射文件中的SQL语句。
        select查询语句要注意
        代码如下:
        SqlSession sqlSession = MyBatisSqlSessionFactory.openSession();
        try {
        StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
        Student stu = studentMapper.findStudentById(1);
        }
        finally {
        sqlSession.close();
        }
        
  • 映射语句的类型:MyBatis提供了不同的标签来配置不同类型的sql语句,如SELECT,INSERT,UPDATE,DELETE。

    1. INSERT 插入语句:一个INSERT语句可以在< insert>标签元素中进行配置,如下所示:

      <insert id="insertStudent" parameterType="Student">
      INSERT INTO STUDENTS(STUD_ID,NAME,EMAIL,PHONE) VALUES(#{studId},#{name},#{email},#{phone})
      </insert>
      ID属性为insertStudent,
      可以在当前xml文件中的名空间 com.briup.mappers.StudentMapper.insertStudent中唯一标识该sql语句。
      parameterType 属性是一个完全限定类名或者是一个类型别名alias。
      #{stuId},与insertStudent方法中参数类表中的Student对象的属性名对应
      可以如下调用这个sql语句:
      int count =
      sqlSession.insert("com.briup.mappers.StudentMapper.insertStudent", student);
      sqlSession.insert() 方法返回执行 INSERT 语句后所影响的行数。
      或者使用映射接口Mapper来调用:
      public interface Student Mapper{
      int insertStudent(Student student);
      }
      StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
      int count = mapper.insertStudent(student);
      Sqlsession.commit();
      自动生成主键:
      在INSERT语句中,可以自动生成主键列 STUD_ID 的值。
      使用useGeneratedKeys和keyProperty属性让数据库生成auto_increment列的值,并将生成的值设置到其中一个输入对象属性内,如下所示:
      <insert id="insertStudent" parameterType="Student" useGeneratedKeys="true" keyProperty="studId">
      INSERT INTO STUDENTS(NAME, EMAIL, PHONE) VALUES(#{name},#{email},#{phone})
      </insert>
      这里STUD_ID列值将会被数据库自动生成(如mysql),并且生成的值会被设置到student对象的studId属性上。
      注意:
      有些数据库,如oracle,并不支持AUTO_INCREMENT列,但是oracle中可以使用序列来生成主键值。
      例如:使用序列my_seq来生成SUTD_ID主键值。使用如下代码来生成主键:
      drop sequence my_seq;
      create sequence my_seq;
      <insert id="insertStudent" parameterType="Student">
      <selectKey keyProperty="studId" resultType="int" order="BEFORE">
      SELECT my_seq.nextval FROM DUAL
      </selectKey>
      INSERT INTO STUDENTS(STUD_ID,NAME,EMAIL, PHONE)
      VALUES(#{studId},#{name},#{email},#{phone})
      </insert>
      这里使用了<selectKey>标签来获取主键值,并将值保存到Student对象的studId 属性上。
      属性order="before" 表示,MyBatis将取得序列的下一个值作为主键值,并且在执行INSERT语句之前将值设置到studId属性上。
      
    2. UPDATE语句:在< update>标签元素中进行配置,如下所示:

      <update id="updateStudent" parameterType="Student">
      UPDATE STUDENTS
      SET NAME=#{name}, EMAIL=#{email}, PHONE=#{phone}
      WHERE STUD_ID=#{studId}
      </update>
      可以如下调用这个sql语句:
      int updateCount = sqlSession.update("com.briup.mappers.StudentMapper.updateStudent", student);
      sqlSession.update()方法返回执行UPDATE语句之后影响的行数。
      或者使用映射接口Mapper来调用:
      public interface StudentMapper{
      int updateStudent(Student student);
      }
      StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
      int updateCount = mapper.updateStudent(student);
      sqlSession.commit();
      
    3. DELETE语句:DELETE语句可以在标签元素中进行配置,如下所示:

      <delete id="deleteStudent" parameterType="int">
      DELETE
      FROM STUDENTS
      WHERE STUD_ID=#{id}
      </delete>
      可以如下调用这个sql语句:
      int deleteCount = sqlSession.delete("com.briup.mappers.StudentMapper.deleteStudent", 1);
      sqlSession.delete()方法返回 delete 语句执行后影响的行数。
      或者使用映射接口Mapper来调用:
      public interface StudentMapper{
      int deleteStudent(int studId);
      }
      StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
      int deleteCount = mapper.deleteStudent(studId);
      sqlSession.commit();
      
    4. SELECT 查询语句:MyBatis真正强大的功能,在于映射SELECT查询结果到java的各种类型上。

      一个简单的select查询配置,如下所示:
      <select id="findStudentById" parameterType="int"
      resultType="Student">
      SELECT STUD_ID, NAME, EMAIL, PHONE
      FROM STUDENTS
      WHERE STUD_ID=#{studId}
      </select>
      第一种:调用sql语句
      Student student = sqlSession.selectOne("com.briup.mappers. StudentMapper.findStudentById", 1);
      第二种:使用映射接口Mapper来调用:
      public interface StudentMapper{
      Student findStudentById(Integer studId);
      }
      StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
      Student student = mapper.findStudentById(studId);
      注意,这时候Student对象的studId属性值为空,但是其他属性的值都有。
      因为数据库表中的字段为stud_id即查询结果字段名也为stud_id,类中属性名为studId,所以property调用对应的setStudId方法时候,studId为null。
      这时给stud_id列起一个别名为studId,和类中属性名保持一致即可。如下所示:
      <select id="findStudentById" parameterType="int"
      resultType="Student">
      SELECT STUD_ID AS studId, NAME,EMAIL, PHONE
      FROM STUDENTS
      WHERE STUD_ID=#{studId}
      </select>
      
    5. MyBatis执行返回多条结果的SELECT语句查询,如下所示:

      <select id="findAllStudents" resultType="Student">
      SELECT STUD_ID AS studId, NAME,EMAIL, PHONE
      FROM STUDENTS
      </select>
      第一种:可以如下调用这个sql语句:
      List<Student> students =
      sqlSession.selectList("com.briup.mappers.StudentMapper.findAllStudents");
      第二种:或者使用映射接口Mapper来调用:
      public interface StudentMapper{
      List<Student> findAllStudents();
      }
      StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
      List<Student> students = mapper.findAllStudents();
      注意,除了List集合类型,也可以使用其他类型的集合类,如Set,Map等。
      yBatis会根据集合的类型,采用适当的集合实现,如下所示:
      对于List,Collection,Iterable类型,
      MyBatis将返回java.util.ArrayList
      对于Map类型,
      MyBatis 将返回java.util.HashMap 
      对于Set类型,
      MyBatis 将返回java.util.HashSet
      对于SortedSet类型
      MyBatis将返回java.util.TreeSet
      
  • 结果集映射 :被用来将SELECT语句的结果集映射到java对象的属性中。

  • 在xml映射文件中,先定义出结果集映射resultMap,然后SELECT语句上引用这个resultMap。

  • MyBatis的结果集映射resultMap非常强大,可以使用它指定sql查询出的结果集,会被怎么处理并封装成对象,也可以使用它完成复杂查询的映射,例如一对一、一对多关系的SELECT语句。

  • 简单ResultMap

    • 定义一个resultMap,代码如下:

      <resultMap id="StudentResult" type="com.briup.pojo.Student">
      <id property="studId" column="stud_id" />
      <result property="name" column="name" />
      <result property="email" column="email" />
      <result property="phone" column="phone" />
      </resultMap>
      <select id="findAllStudents" resultMap="StudentResult">
      SELECT *
      FROM
      STUDENTS
      </select>
      <select id="findStudentById" parameterType="int" resultMap="StudentResult">
      SELECT *
      FROM STUDENTS
      WHERE STUD_ID=#{studId}
      </select>
      resultMap:标签中的属性:
      id:属性值在当前名空间内是唯一的。
      type:属性值是指定类型的全限定名或者是别名。
      resultMap标签中的子标签:
      <result>子标签
      用来将一个result列查询结果集映射到对象的一个属性中。
      <id>子标签
      和<result>标签功能相同,但是<id>用来映射的是表中的主键。
      注意1,在<select>标签中,使用的是resultMap属性,而不是resultType属性。
      当<select>标签中配置了resutlMap属性,MyBatis会根据resutlMap标签中定义的列名与对象属性名的 【对应关系】 来自动填充对象中的属性值。
      注意2,resultType和resultMap二者只能用其一,不能同时使用。
      resultType属性指的是结果集将自动封装成什么类型。这时候默认表中列的名字(查询结果的列名)和类中属性名字一致。
      resultMap 属性指的是结果集将按照<resultMap>标签中定义的 【对应关系】 来封装数据。
      
    • select查询的一些其他情况

      • 查询结果列名和列名结果,按照k=v形式存储到map集合
      <select>中如何将查询【一条】数据填充到HashMap中?
      <select id="findStudentById" parameterType="int" resultType="map">
      SELECT * FROM STUDENTS WHERE STUD_ID=#{studId}
      </select>
      在上述的<select>语句中,将resultType配置成map,
      结果集的【列名】将会作为Map中的key值
      而【列值】将作为Map的value值。
      HashMap<String,Object> studentMap = sqlSession.selectOne("com.briup.mappers.StudentMapper.findStudentById", studId);
      studentMap.foreach((k,v)->System.out.println(k+" = "+v));
      
      • 查询结果每一条数据结果,按照k=v进行存储到map集合,然后将多行数据存储到List集合中,每一行数据的列名和列名值存储到map集合中,再讲每一行数据封装成的map集合添加到List集合中
      <select>中如何将查询【多条】数据填充到HashMap中?
      <select id="findAllStudents" resultType="map">
      SELECT STUD_ID, NAME, EMAIL, PHONE FROM STUDENTS
      </select>
      由于resultType="map",以及结果集为多行,最终返回的数据类型默认是List<Map<String,Object>>,如下所示:
      List<Map<String, Object>> studentMapList = sqlSession.selectList("com.briup.mappers.StudentMapper.findAllStudents");
      for(Map<String, Object> studentMap : studentMapList) {
      studentMap.foreach((k,v)->System.out.println(k+" = "+v));
      System.out.println("----------------");
      }
      
      • 该映射文件对应的映射接口中:映射接口中的抽象方法的返回类型可以随便定为常见的集合类型,Mybatis会按照我们方法中声明的集合类型来进行自动封装。

        其他实例1:
        < select id="findAllStudents_student" resultType="Student">
        SELECT STUD_ID AS STUDID,NAME,EMAIL,DOB
        FROM STUDENTS
        </select>
        但是要注意使用SortedSet的时候,Student类需要实现Comparable接口,否则是不能进行排序的
        例如:
        public List<Student> findAllStudents_List();
        或者
        public Set<Student> findAllStudents_Set();
        或者
        public SortedSet<Student> findAllStudents_SortedSet();
        其他实例2:
        < select id="findAllName_list" resultType="String">
        SELECT NAME
        FROM STUDENTS
        </select>
        在该映射文件对应的映射接口中:
        把查询到所有名字都放到List集合中并返回
        public List<String> findAllName_list();
        其他实例3:
        <select id="findCount_int" resultType="int">
        SELECT count(*)
        FROM STUDENTS
        </select>
        在该映射文件对应的映射接口中:
        把查询到的这个值直接返回
        public int findCount_int();
        
  • resultMap之间的继承 (了解)

    • (注:这个可以在下面的一对一映射中进行测试,因为这里需要建立一对一关系的表结构)

      • 在sql映射文件中,可以让一个其继承另一个,这样,第一个中定义的对应关系,就可以被第二个继承过来,例如:

        <!-- 第一个resultMap -->
        <resultMap type="Student" id="StudentResult">
        <id property="stud Id" column="stud_id" />
        <result property="name" column="name" />
        <result property="email" column="email" />
        <result property="phone" column="phone" />
        </resultMap>
        假设新增了一个新的实体类Address,该类中有多个属性,分别和数据库中ADDRESSES表对应。
        在Student类中又新增加了一个属性Address。
        <!-- 第二个resultMap,这里面的address.addrId是按照Student对象中的Address类型的属性在调用address对象的setXxx方法,进行查询结果和对象属性映射封装 -->
        <resultMap type="Student" id="StudentWithAddressResult" extends="StudentResult">
        <result property="address.addrId" column="addr_id" />
        <result property="address.street" column="street" />
        <result property="address.city" column="city" />
        <result property="address.state" column="state" />
        <result property="address.zip" column="zip" />
        <result property="address.country" column="country" />
        </resultMap>
        
      • 其中id为StudentWithAddressResult的resultMap拓展了id为StudentResult的resultMap

      • 查询结果不包含address地址信息,就只映射Student数据,你可以使用id为StudentResult的resultMap,如下所示:

        查询结果映射student对象的属性不包括address属性
        <select id="findStudentById" parameterType="int"
        resultMap="StudentResult">
        SELECT * FROM STUDENTS WHERE STUD_ID=#{stud Id}
        </select>
        
  • 查询全部,映射Student数据和Address数据,你可以使用id为StudentWithAddressResult的 resultMap:

    xml
    查询结果包含address数据,将student的成员变量通过查询结果,全部进行初始化
    涉及多表查询:要注意查询两张表的字段有冲突的地方需要设置别名,否则进行数据封装到对象会出现数据错乱(student的id可能会封装到address的id中)
    <select id="selectStudentWithAddress" parameterType="int"
    resultMap="StudentWithAddressResult">
    SELECT
    STUD_ID, NAME, EMAIL, PHONE,
    A.ADDR_ID, STREET, CITY, STATE, ZIP, COUNTRY
    FROM
    STUDENTS S
    LEFT OUTER JOIN
    ADDRESSES A
    ON
    S.ADDR_ID=A.ADDR_ID
    WHERE
    STUD_ID=#{studId}
    </select>
    注:该sql语句使用了连接查询中的外连接,也可以使用等值连接
    

最后

以上就是舒心机器猫为你收集整理的Mybatis-XxxMapper.xml配置文件一、了解内容二、映射配置文件Mapper.xml的全部内容,希望文章能够帮你解决Mybatis-XxxMapper.xml配置文件一、了解内容二、映射配置文件Mapper.xml所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(46)

评论列表共有 0 条评论

立即
投稿
返回
顶部