MyBatis映射文件Mapper.xml详解

我就是我 2023-07-24 09:19 3阅读 0赞

映射文件是 MyBatis 框架中十分重要的文件 可以说, MyBatis 框架的强大之处就体现在映射文件的编写上。在映射文件中,<mapper>元素是映射文件的根元素,其他元素都是它的子元素。
在这里插入图片描述
Select元素
<select>元素用来映射查询语句,它可以帮助我们从数据库中读取出数据。如下代码所示:

  1. <select id="findCustomerById" parameterType="Integer"
  2. resultType="com.lzq.po.Customer">
  3. select * from t_customer where id = #{ id}
  4. </select>

select元素属性详情见下表:


















































属性 说明
id 表示命名空间中的唯一标识符, 常与命名空间组合起来使用。组合后如果不唯一, MyBatis 会抛出异常
parameter Type 该属性表示传入SQL语句的参数类的全限定名或者别名。它是一个可选属性,因为MyBatis可以通过TypeHandler推断出具体传入语句的参数。其默认值是unset (依赖于驱动)
resultType 从SQL语句中返回的类型的类的全限定名或者别名。如果是集合类型,那么返回的应该是集合可以包含的类型,而不是集合本身。返回时可以使用resultType或resultMtap之一
resultMap 表示外部resultMap的命名引用。返回时可以使用resultType或resultMap之一
flushCache 表示在调用SQL语句之后,是否需要MyBatis清空之前查询的本地缓存和二级缓存。其值为布尔类型( truelfalse),默认值为false.如果设置为true,则任何时候只要SQL语句被调用,都会清空本地缓存和二级缓存
useCache 用于控制二级缓存的开启和关闭。其值为布尔类型( truelfalse),默认值为true,表示将查询结果存入二级缓存中
timeout 用于设置超时参数,单位为秒。超时时将抛出异常
fetchSize 获取记录的总条数设定,其默认值是unset (依赖于驱动)
statementType 用于设置MyBatis使用哪个JDBC的Statement工作,其值为STATEMENT.PREPARED(默认值)或CALLABLE,分别对应JDBC中的Statement、 PreparedStatement和CallableStatement
resultSetType 表示结果集的类型,其值可设置为FORWARD ONLY、SCROLL SENSITIVE 或SCROLL INSENSITIVE,它的默认值是unset (依赖于驱动)

Insert元素
元素用于映射插入语句,在执行完元素中定义的SQL语句后,会返回一个表示插入记录数的整数。如下代码所示:

  1. <insert id="addCustomer" parameterType="com.itheima.po.Customer" flushCache="true"
  2. statementType="PREPARED" keyProperty="" keyColumn="" useGeneratedKeys="" timeout="20">

其中<insert>元素的属性与<select>元素的属性大部分相同,但还包含了3个特有属性,这3个属性的描述如下表所示:






















属性 说明
keyProperty (仅对insert和update有用)此属性的作用是将插入或更新操作时的返回值赋值给PO类的某个属性,通常会设置为主键对应的属性。如果需要设置联合主键,可以在多个值之间用逗号隔开
keyColumn (仅对insert和update有用)此属性用于设置第几列是主键,当主键列不是表中的第一列时需要设置。在需要主键联合时,值可以用逗号隔开
useGeneratedKeys (仅对insert和update有用)此属性会使MyBatis使用JDBC的getGeneratedKeys()方法来获取由数据库内部生产的主键,如MySQL和SQL Server等自动递增的字段,其默认值为false

执行插入操作后,很多时候我们会需要返回插入成功的数据生成的主键值,此时就可以通过上面讲的3个属性来实现。如果使用的数据库支持主键自动增长(如MySQL ),那么可以通过keyProperty属性指定PO类的某个属性接收主键返回值(通常会设置到id属性上),然后将useGeneratedKeys的属性值设置为true,其使用示例如下。

  1. <insert id="addCustomer" parameterType="com.lzq.po.Customer"
  2. keyProperty="id" useGeneratedKeys="true">
  3. insert into t_customer (username, jobs, phone) values (#(username),#(jobs},#{ phone})
  4. </insert>

Updata 和 Delete元素
<update><delete>元素的使用比较简单,它们的属性配置也基本相同。如下代码所示:

  1. <update id="updateCustomer" parameterType="com.lzq.po.Customer">
  2. update t_customer
  3. set username=#{ username},jobs=#{ jobs},phone=#{ phone}
  4. where id=#{ id}
  5. </update>
  6. <delete id="deleteCustomer" parameterType="Integer">
  7. delete from t_customer where id=#{ id}
  8. </delete>

在配置update和delete元素的配置基本和insert元素差不了多少,在使用这俩个元素时,也会返回一个表示有多少航受到影响的参数,

Sql元素
在一个映射文件中,通常需要定义多条SQL语句,这些SQL语句的组成可能有一部分是相同的(如多条select语句中都查询相同的id、username、jobs字段),如果每一个SQL语句都重写一遍相同的部分,势必会增加代码量,导致映射文件过于臃肿。那么有没有什么办法将这些SQL语句中相同的组成部分抽取出来,然后在需要的地方引用呢?这个时候就需要使用到sql元素了。
<sql>元素的作用就是定义可重用的SQL代码片段,然后在其他语句中引用这一代码片段。

比如:定义一个包含id、username、jobs和phone字段的代码片段如下:给sql加上一个ID

  1. <sql id="customerColumns">id,username,jobs,phone</sql>

上述代码片段可以包含在其他语句中直接使用,使用方法如下:在select查询语句当中使用include的refid属性进行引入sql

  1. <select id="findCustomerById" parameterType="Integer"resultType="com.lzq.po.Customer">
  2. select <include refid="customerColumns"/>
  3. from t_customer
  4. where id = #{ id}
  5. </select>

当然除了这种简单的sql进行引入还有比较复杂的引入:如下图所示:(相同效果)
在这里插入图片描述
代码如下所示:分别是对查询语句进行了分割成一个很小的小块,方便后续的查询可以直接调用sql元素。

  1. <sql id="tablename">${ prefix} customer</sql>
  2. <sql id="someinclude">from<include refid="${include_target}" /></sql>
  3. <sql id="customerColumns">id,username,jobs,phone</sql>
  4. <select id="findCustomerById" parameterType="Integer"
  5. resultType="com.lzq.po.Customer">
  6. select
  7. <include refid="customerColumns" />
  8. <include refid="someinclude">
  9. <property name="prefix" value="t_" />
  10. <property name="include_target" value="tablename" />
  11. </include>
  12. where id = #{ id}
  13. </select>

resultMap 元素
<resultMap>元素表示结果映射集,是MyBatis中最重要也是最强大的元素。它的主要作用是定义映射规则、级联的更新以及定义类型转化器等。
<resultMap>元素中包含了一些子元素,它的元素结构如下代码段所示:

  1. <resultMap type="" id="">
  2. <constructor> <!-- 类在实例化时,用来注入结果到构造方法中-->
  3. <idArg/> <!-- ID参数;标记结果作为ID-->
  4. <arg/> <!-- 注入到构造方法的一个普通结果-->
  5. </constructor>
  6. <id/> <!-- 用于表示哪个列是主键-->
  7. <result/> <!-- 注入到字段或JavaBean属性的普通结果-->
  8. <association property="" /> <!-- 用于一对一关联 -->
  9. <collection property="" /> <!-- 用于一对多关联 -->
  10. <discriminator javaType=""> <!-- 使用结果值来决定使用哪个结果映射-->
  11. <case value="" /> <!-- 基于某些值的结果映射 -->
  12. </discriminator>
  13. </resultMap>

<resultMap>元素的type属性表示需要映射的POJO,id属性是这个resultMap的唯一标识。它的子元素<constructor>用于配置构造方法(当一个POJO中未定义无参的构造方法时,就可以使用<constructor>元素进行配置)。子元素<id>用于表示哪个列是主键,而<result> 用于表示POJO和数据表中普通列的映射关系。<association><collection>用于处理多表时的关联关系,而<discriminator>元素主要用于处理一个单独的数据库查询返回很多不同数据类型结果集的情况。

在默认情况下,MyBatis程序在运行时会自动地将查询到的数据与需要返回的对象的属性进行匹配赋值(需要表中的列名与对象的属性名称完全一致 )。然而实际开发时,数据表中的列和需要返回的对象的属性可能不会完全一致, 这种情况下MyBatis是不会自动赋值的。此时,就可以使用<resultMap>元素进行处理。

resultMap元素的使用
首先创建一个表t_user:并且插入几条数据用于测试:代码如下

  1. CREATE TABLE t_user(
  2. t_id INT PRIMARY KEY AUTO_INCREMENT,
  3. t_name VARCHAR(50),
  4. t_age INT
  5. )
  6. INSERT INTO t_user(t_name,t_age) VALUES('tom' , 25);
  7. INSERT INTO t_user(t_name , t_age) VALUES('Lili' , 20);
  8. INSERT INTO t_user(t_name , t_age) VALUES('Jim' , 20);

随后在 com.lzq.po 包中,创建持久化类 User ,并在类中定义 id name age 属性,以及其 getter/setter 方法和 toString()方法,代码如下所示:(省略getset方法)

  1. package com.lzq.po;
  2. public class User {
  3. private Integer id;
  4. private String name;
  5. private Integer age;
  6. @Override
  7. public String toString() {
  8. return "User[id=" + id + ", name=" + name + ", age=" + age + ")]";
  9. }
  10. }

创建映射文件UserMapper.xml文件代码如下所示:
<resultMap>的子元素<id><result>的property属性表示User类的属名,column属性表示数据表t _user 的列名。<select> 元素的resultMap属性表示引用上面定的resultMap。

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  3. <mapper namespace="com.lzq.mapper.UserMapper">
  4. <resultMap type="com.lzq.po.User" id="resultMap">
  5. <id property="id" column="t_id" />
  6. <result property="name" column="t_name" />
  7. <result property="age" column="t_age" />
  8. </resultMap>
  9. <select id="findAllUser" resultMap="resultMap">
  10. select * from t_user
  11. </select>
  12. </mapper>

再在mybatis-config.xml文件当中引入配置文件:如下代码所示:

  1. <mappers>
  2. <mapper resource="com/lzq/mapper/UserMapper.xml" />
  3. </mappers>

在使用公共类MybatisUtils,该类将加载mybatis的配置文件和创建sqlSession的工厂的代码进行抽离出来:代码如下所示:

  1. package com.lzq.utils;
  2. import java.io.Reader;
  3. import org.apache.ibatis.io.Resources;
  4. import org.apache.ibatis.session.SqlSession;
  5. import org.apache.ibatis.session.SqlSessionFactory;
  6. import org.apache.ibatis.session.SqlSessionFactoryBuilder;
  7. public class MybatisUtils {
  8. private static SqlSessionFactory sqlSessionFactory = null;
  9. // 初始化SqlSessionFactory对象
  10. static {
  11. try {
  12. // 使用MyBatis提供的Resources类加载mybatis的配置文件
  13. Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
  14. // 构建sqlSession的工厂
  15. sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
  16. } catch (Exception e) {
  17. e.printStackTrace();
  18. }
  19. }
  20. // 获取SqlSession对象的静态方法
  21. public static SqlSession getSession() {
  22. return sqlSessionFactory.openSession();
  23. }
  24. }

最后使用一个测试类进行测试:测试方法如下所示:

  1. public void findAllUserTest() {
  2. // 获取SqlSession
  3. SqlSession sqlSession = MybatisUtils.getSession();
  4. // SqlSession执行映射文件中定义的SQL,并返回映射结果
  5. List<User> list = sqlSession.selectList
  6. ("com.lzq.mapper.UserMapper.findAllUser");
  7. for (User user : list) {
  8. System.out.println(user);
  9. }
  10. sqlSession.close();
  11. }

在最后看下效果图,可以看到执行select * from t_user表会返回表当中所有的数据:
在这里插入图片描述

发表评论

表情:
评论列表 (有 0 条评论,3人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Mybatis映射详解

    Mybatis映射详解 在最近的工作中,碰到一个比较复杂的返回结果,发现简单映射已经解决不了这个问题了,只好去求助百度,学习mybatis复杂映射应该怎么写,将学习笔记结

    相关 Mybatis-映射文件

    Mybatis-映射文件(二) Mybatis的真正强大在于它的映射语句,也是它的魔力所在。由于它的异常强大,映射器XML文件就显得相对简单。如果拿他跟具有相同功能的JD