MyBatis的mapper接口的映射配置文件的解析与深入了解

本文为作者自己做的笔记,如果有什么地方写错了,望指出


我们在了解MyBatis接口的映射文件之前,先来看一下,什么是MyBatis?

        MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(实体类)映射成数据库中的记录。
        每个MyBatis应用程序主要都是使用SqlSessionFactory实例的,一个SqlSessionFactory实例可以通过SqlSessionFactoryBuilder获得。SqlSessionFactoryBuilder可以从一个xml配置文件或者一个预定义的配置类的实例获得。
        MyBatis有许多优点:
        简单易学:本身很小且简单,没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
        灵活:mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql语句可以满足操作数据库的所有需求。
        解除sql与程序代码的耦合:通过提供DAO层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。
        提供映射标签,支持对象与数据库的orm字段关系映射
        提供对象关系映射标签,支持对象关系组建维护
        提供xml标签,支持编写动态sql。


接下来解析配置文件,如下代码:

POJO实体类:

package cn.xhc.springboot.model;

import java.io.Serializable;
import java.math.BigDecimal;

public class User implements Serializable {
    private Integer id;

    private String userName;

    private String userCard;

    private Integer userAge;

    private String userEmail;

    private String userCompany;

    private BigDecimal userWages;

    private String userAddress;

    private static final long serialVersionUID = 1L;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getUserCard() {
        return userCard;
    }

    public void setUserCard(String userCard) {
        this.userCard = userCard;
    }

    public Integer getUserAge() {
        return userAge;
    }

    public void setUserAge(Integer userAge) {
        this.userAge = userAge;
    }

    public String getUserEmail() {
        return userEmail;
    }

    public void setUserEmail(String userEmail) {
        this.userEmail = userEmail;
    }

    public String getUserCompany() {
        return userCompany;
    }

    public void setUserCompany(String userCompany) {
        this.userCompany = userCompany;
    }

    public BigDecimal getUserWages() {
        return userWages;
    }

    public void setUserWages(BigDecimal userWages) {
        this.userWages = userWages;
    }

    public String getUserAddress() {
        return userAddress;
    }

    public void setUserAddress(String userAddress) {
        this.userAddress = userAddress;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(getClass().getSimpleName());
        sb.append(" [");
        sb.append("Hash = ").append(hashCode());
        sb.append(", id=").append(id);
        sb.append(", userName=").append(userName);
        sb.append(", userCard=").append(userCard);
        sb.append(", userAge=").append(userAge);
        sb.append(", userEmail=").append(userEmail);
        sb.append(", userCompany=").append(userCompany);
        sb.append(", userWages=").append(userWages);
        sb.append(", userAddress=").append(userAddress);
        sb.append(", serialVersionUID=").append(serialVersionUID);
        sb.append("]");
        return sb.toString();
    }
}

user数据库表:
在这里插入图片描述
Mapper接口层接口:

package cn.xhc.springboot.mapper;

import cn.xhc.springboot.model.User;
import cn.xhc.springboot.model.UserExample;
import java.util.List;
import org.apache.ibatis.annotations.Param;

public interface UserMapper {
    long countByExample(UserExample example);

    int deleteByExample(UserExample example);

    int deleteByPrimaryKey(Integer id);

    int insert(User record);

    int insertSelective(User record);

    List<User> selectByExample(UserExample example);

    User selectByPrimaryKey(Integer id);

    int updateByExampleSelective(@Param("record") User record, @Param("example") UserExample example);

    int updateByExample(@Param("record") User record, @Param("example") UserExample example);

    int updateByPrimaryKeySelective(User record);

    int updateByPrimaryKey(User record);
}

配置文件及解析:

<?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:用来使与之对应的Java关于数据库的操作的接口做联系。
	
	属性:
	namespace:接口所在的位置
-->
<mapper namespace="cn.xhc.springboot.mapper.UserMapper">
  <!-- 
  	标签:
  	resultMap:用来配置数据库中指定表的字段与自己的POJO(实体)属性的联系的 
  	
  	属性:
  	id:resultMap的标识符
  	type:POJO(实体类)所在的路径
  -->
  <resultMap id="BaseResultMap" type="cn.xhc.springboot.model.User">
    <!-- 
    	标签:
    	id:是为了配置数据库中表的主键标识符与自己的POJO属性的关联
    	result:是为了配置数据库中表的字段与自己的POJO属性的关联
    	
    	属性:
    	column:数据库中表的字段名
    	jdbcType:数据库库中表的字段的类型
    	property:POJO中属性的名字
    -->
    <id column="id" jdbcType="INTEGER" property="id" />
    <result column="user_name" jdbcType="VARCHAR" property="userName" />
    <result column="user_card" jdbcType="VARCHAR" property="userCard" />
    <result column="user_age" jdbcType="INTEGER" property="userAge" />
    <result column="user_email" jdbcType="VARCHAR" property="userEmail" />
    <result column="user_company" jdbcType="VARCHAR" property="userCompany" />
    <result column="user_wages" jdbcType="DECIMAL" property="userWages" />
    <result column="user_address" jdbcType="VARCHAR" property="userAddress" />
  </resultMap>
  
  <!-- Sql -->
  <sql id="Example_Where_Clause">
  	<!-- 
  		where 元素知道只有在一个以上的if条件有值的情况下才去插入“WHERE”子句。
  		而且,若最后的内容是“AND”或“OR”开头的,where 元素也知道如何将他们去除。
  	-->
    <where>
    
      <!-- 
      	标签:
      	foreach:当传入参数为数组或者集合时需要通过<foreach></foreach>标签进行遍历 
      	
      	属性:
      	collection:指定输入对象中的集合属性名
      	item:每次遍历生成的对象名
      	separator:表示在每次进行迭代之后以什么符号作为分隔符(查出来一个数据应该以此作为分隔符,才能开始下一项查询)
      -->
      <foreach collection="oredCriteria" item="criteria" separator="or">
        <if test="criteria.valid">
          <!-- 
          	标签:
          	trim
          	
          	属性:
          	prefix="(":前缀为左括号
          	prefixOverrides="and":去掉sql语句的第一个AND连接符
          	suffix=")":后缀为右括号
          	open:值为开始遍历时候拼接的字符串
          	close:值为结束遍历时拼接的字符串
          -->
          <trim prefix="(" prefixOverrides="and" suffix=")">
            <foreach collection="criteria.criteria" item="criterion">
              <!-- 
              	choose和when标签相当于Java中的Switch case标签,就是说那个when的标签成立,
              	就执行此when标签中的sql语句。
              	
              	属性:
              	test:相当与Java中每个case中的条件
              -->
              <choose>
                <when test="criterion.noValue">
                  and ${criterion.condition}
                </when>
                <when test="criterion.singleValue">
                  and ${criterion.condition} #{criterion.value}
                </when>
                <when test="criterion.betweenValue">
                  and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
                </when>
                <when test="criterion.listValue">
                  and ${criterion.condition}
                  <foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
                    #{listItem}
                  </foreach>
                </when>
              </choose>
            </foreach>
          </trim>
        </if>
      </foreach>
    </where>
  </sql>
  <sql id="Update_By_Example_Where_Clause">
    <where>
      <foreach collection="example.oredCriteria" item="criteria" separator="or">
        <if test="criteria.valid">
          <trim prefix="(" prefixOverrides="and" suffix=")">
            <foreach collection="criteria.criteria" item="criterion">
              <choose>
                <when test="criterion.noValue">
                  and ${criterion.condition}
                </when>
                <when test="criterion.singleValue">
                  and ${criterion.condition} #{criterion.value}
                </when>
                <when test="criterion.betweenValue">
                  and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
                </when>
                <when test="criterion.listValue">
                  and ${criterion.condition}
                  <foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
                    #{listItem}
                  </foreach>
                </when>
              </choose>
            </foreach>
          </trim>
        </if>
      </foreach>
    </where>
  </sql>
  
  <!-- 
  	标签:
  	sql:是用来将数据库中表的字段封装起来,以便以后使用的时候直接引用就行。
  	
  	属性:
  	id:sql标签的标识符,以便于以后根据标识符来引用。
  -->
  <sql id="Base_Column_List">
    id, user_name, user_card, user_age, user_email, user_company, user_wages, user_address
  </sql>
  
  <!-- 
  	标签:
  	select:用来根据条件对数据库中表数据的查询操作
 
  	属性:
  	id:要与Java程序数据库接口层的方法名称保持一致
  	parameterType:是Java程序数据库接口层方法的参数类型
  	resultMap:是Java程序数据库接口层方法的返回值类型,该值为我们的resultMap标签的id值
  -->
  <select id="selectByExample" parameterType="cn.xhc.springboot.model.UserExample" resultMap="BaseResultMap">
    select
    <!-- 
    	标签:
    	if:该标签是用来判断的条件是否成立的,如果条件成立(true),则执行if标签内的sql语句
    	
    	属性:
    	test:是if标签的判断条件
    -->
    <if test="distinct">
      distinct
    </if>
    
    <!-- 
    	标签:
    	include:是用来引用sql标签所封装的数据库表的字段
    	
    	属性:
    	refid:该值与sql标签的id值应保持一致。
    -->
    <include refid="Base_Column_List" />
    from user
    <if test="_parameter != null">
      <include refid="Example_Where_Clause" />
    </if>
    <if test="orderByClause != null">
      order by ${orderByClause}
    </if>
  </select>
  <select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
    select 
    <include refid="Base_Column_List" />
    from user
    <!-- 
    	#{id,jdbcType=INTEGER}
    	id:是Java程序的接口层方法的参数名字
    	jdbcType:是数据库中表对应该参数的字段的数据类型
    -->
    where id = #{id,jdbcType=INTEGER}
  </select>
  
  <!-- 
  	标签:
  	delete:用来对数据库中表数据的删除操作
  	
  	属性:
  	id:要与Java程序数据库接口层的方法名称保持一致
  	parameterType:是Java程序数据库接口层方法的参数类型
  -->
  <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
    delete from user
    where id = #{id,jdbcType=INTEGER}
  </delete>
  <delete id="deleteByExample" parameterType="cn.xhc.springboot.model.UserExample">
    delete from user
    <if test="_parameter != null">
      <include refid="Example_Where_Clause" />
    </if>
  </delete>
  
  <!-- 
  	标签:
  	insert:用来对数据库中表数据的新增操作
  	
  	属性:
  	id:要与Java程序数据库接口层的方法名称保持一致
  	parameterType:是Java程序数据库接口层方法的参数类型
  -->
  <insert id="insert" parameterType="cn.xhc.springboot.model.User">
  	<!-- 
  		数据库主键包括自增和非自增,有时候新增一条数据不仅仅知道成功就行了,
  		后边的逻辑可能还需要这个新增的主键,这时候再查询数据库就有点耗时耗力,
  		我们可以采用selectKey标签来帮助我们获取新增的主键。
  		
  		标签:
  		selectKey:该标签的作用是将 LAST_INSERT_ID() 的结果放到我们的POJO(实体类)的主键里面。
  		
  		属性:
  		keyProperty:对应POJO里的主键的属性名,这里对应我们User的id属性。
  		order:
  			AFTER:表示 SELECT LAST_INSERT_ID() 是在insert(插入数据)之后执行,多用于自增主键。
  			BEFORE:表示 SELECT LAST_INSERT_ID () 是在insert(插入数据)之前执行,但是就拿不到主键了,这种用于主键不是增的类型。
  		resultType:表示POJO中与数据库中表的主键对应的属性类型。
  	-->
    <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
      SELECT LAST_INSERT_ID()
    </selectKey>
    insert into user (user_name, user_card, user_age, 
      user_email, user_company, user_wages, 
      user_address)
    values (#{userName,jdbcType=VARCHAR}, #{userCard,jdbcType=VARCHAR}, #{userAge,jdbcType=INTEGER}, 
      #{userEmail,jdbcType=VARCHAR}, #{userCompany,jdbcType=VARCHAR}, #{userWages,jdbcType=DECIMAL}, 
      #{userAddress,jdbcType=VARCHAR})
  </insert>
  <insert id="insertSelective" parameterType="cn.xhc.springboot.model.User">
    <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
      SELECT LAST_INSERT_ID()
    </selectKey>
    insert into user
    
    <!-- 
    	标签:
    	trim:
    	
    	属性:
    	prefix="(":前缀左括号
    	suffix=")":后缀右括号
    	suffixOverrides=",":去掉sql语句的最后一个逗号
    	prefixOverrides="AND":去掉sql语句的第一个AND连接符
    -->
    <trim prefix="(" suffix=")" suffixOverrides=",">
      <if test="userName != null">
        user_name,
      </if>
      <if test="userCard != null">
        user_card,
      </if>
      <if test="userAge != null">
        user_age,
      </if>
      <if test="userEmail != null">
        user_email,
      </if>
      <if test="userCompany != null">
        user_company,
      </if>
      <if test="userWages != null">
        user_wages,
      </if>
      <if test="userAddress != null">
        user_address,
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides=",">
      <if test="userName != null">
        #{userName,jdbcType=VARCHAR},
      </if>
      <if test="userCard != null">
        #{userCard,jdbcType=VARCHAR},
      </if>
      <if test="userAge != null">
        #{userAge,jdbcType=INTEGER},
      </if>
      <if test="userEmail != null">
        #{userEmail,jdbcType=VARCHAR},
      </if>
      <if test="userCompany != null">
        #{userCompany,jdbcType=VARCHAR},
      </if>
      <if test="userWages != null">
        #{userWages,jdbcType=DECIMAL},
      </if>
      <if test="userAddress != null">
        #{userAddress,jdbcType=VARCHAR},
      </if>
    </trim>
  </insert>
  
  <!-- 
  	我们有时候会纠结select标签中的属性是resultMap还是resultType:
  	只要我们记住,Java程序数据库接口层方法的返回值如果是一个POJO,就用resultMap属性,
  	如果Java程序数据库接口层方法的返回值是其他类型(包括基本类型),就用resultType属性。
  -->
  <select id="countByExample" parameterType="cn.xhc.springboot.model.UserExample" resultType="java.lang.Long">
    select count(*) from user
    <!-- _parameter可以用来代表Java程序数据库接口层方法的参数,但是有一个局限性,就是方法参数只能有一个。 -->
    <if test="_parameter != null">
      <include refid="Example_Where_Clause" />
    </if>
  </select>
  
  <!-- 
  	标签:
  	update:用来对数据库中表数据的部分修改操作。
  	
  	属性:
  	id:要与Java程序数据库接口层的方法名称保持一致
  	parameterType:是Java程序数据库接口层方法的参数类型(我们可以使用简略模式,就像下面的map一样,也可以使用全路径java.util.Map)
  -->
  <update id="updateByExampleSelective" parameterType="map">
    update user
    <!-- 
    	set 标签元素主要是用在更新操作的时候,它的主要功能和 where 标签其实是差不多的,
    	主要是在包含的语句前输出一个 set,然后如果包含的sql语句是以逗号结束的话将会把该逗号忽略,
    	如果 set 包含的内容为空的话则会出错。有了 set 元素就可以动态的更新那些修改了的字段。
    -->
    <set>
      <!-- record是该方法的实体类参数,record.id是用来获取该实体类的id-->
      <if test="record.id != null">
        id = #{record.id,jdbcType=INTEGER},
      </if>
      <if test="record.userName != null">
        user_name = #{record.userName,jdbcType=VARCHAR},
      </if>
      <if test="record.userCard != null">
        user_card = #{record.userCard,jdbcType=VARCHAR},
      </if>
      <if test="record.userAge != null">
        user_age = #{record.userAge,jdbcType=INTEGER},
      </if>
      <if test="record.userEmail != null">
        user_email = #{record.userEmail,jdbcType=VARCHAR},
      </if>
      <if test="record.userCompany != null">
        user_company = #{record.userCompany,jdbcType=VARCHAR},
      </if>
      <if test="record.userWages != null">
        user_wages = #{record.userWages,jdbcType=DECIMAL},
      </if>
      <if test="record.userAddress != null">
        user_address = #{record.userAddress,jdbcType=VARCHAR},
      </if>
    </set>
    <if test="_parameter != null">
      <include refid="Update_By_Example_Where_Clause" />
    </if>
  </update>
  
  <!-- 
  	标签:
  	update:用来对数据库中表数据的全部修改操作。
  	
  	属性:
  	id:要与Java程序数据库接口层的方法名称保持一致
  	parameterType:是Java程序数据库接口层方法的参数类型(我们可以使用简略模式,就像下面的map一样,也可以使用全路径java.util.Map)
  -->
  <update id="updateByExample" parameterType="map">
    update user
    set id = #{record.id,jdbcType=INTEGER},
      user_name = #{record.userName,jdbcType=VARCHAR},
      user_card = #{record.userCard,jdbcType=VARCHAR},
      user_age = #{record.userAge,jdbcType=INTEGER},
      user_email = #{record.userEmail,jdbcType=VARCHAR},
      user_company = #{record.userCompany,jdbcType=VARCHAR},
      user_wages = #{record.userWages,jdbcType=DECIMAL},
      user_address = #{record.userAddress,jdbcType=VARCHAR}
    <if test="_parameter != null">
      <include refid="Update_By_Example_Where_Clause" />
    </if>
  </update>
  
  <!-- 
  	标签:
  	update:根据主键来对数据库中表数据的部分修改操作。
  	
  	属性:
  	id:要与Java程序数据库接口层的方法名称保持一致
  	parameterType:是Java程序数据库接口层方法的参数类型
  -->
  <update id="updateByPrimaryKeySelective" parameterType="cn.xhc.springboot.model.User">
    update user
    <set>
      <if test="userName != null">
        user_name = #{userName,jdbcType=VARCHAR},
      </if>
      <if test="userCard != null">
        user_card = #{userCard,jdbcType=VARCHAR},
      </if>
      <if test="userAge != null">
        user_age = #{userAge,jdbcType=INTEGER},
      </if>
      <if test="userEmail != null">
        user_email = #{userEmail,jdbcType=VARCHAR},
      </if>
      <if test="userCompany != null">
        user_company = #{userCompany,jdbcType=VARCHAR},
      </if>
      <if test="userWages != null">
        user_wages = #{userWages,jdbcType=DECIMAL},
      </if>
      <if test="userAddress != null">
        user_address = #{userAddress,jdbcType=VARCHAR},
      </if>
    </set>
    where id = #{id,jdbcType=INTEGER}
  </update>
  
  <!-- 
  	标签:
  	update:根据主键来对数据库中表数据的全部修改操作。
  	
  	属性:
  	id:要与Java程序数据库接口层的方法名称保持一致
  	parameterType:是Java程序数据库接口层方法的参数类型)
  -->
  <update id="updateByPrimaryKey" parameterType="cn.xhc.springboot.model.User">
    update user
    set user_name = #{userName,jdbcType=VARCHAR},
      user_card = #{userCard,jdbcType=VARCHAR},
      user_age = #{userAge,jdbcType=INTEGER},
      user_email = #{userEmail,jdbcType=VARCHAR},
      user_company = #{userCompany,jdbcType=VARCHAR},
      user_wages = #{userWages,jdbcType=DECIMAL},
      user_address = #{userAddress,jdbcType=VARCHAR}
    where id = #{id,jdbcType=INTEGER}
  </update>
</mapper>

配置文件标签解析都在配置文件代码中!

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值