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

    科技2024-06-28  68

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

    我们在了解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>

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

    Processed: 0.152, SQL: 8