MyBatis常用标签以及使用技巧总结

作者:weixin_45747080 时间:2022-02-27 20:52:14 

前言

MyBatis常用标签及标签使用技巧

MyBatis的常用标签有很多,比如

<sql id="">:预定义可以复用的sql语句

<include refid="">:根据id引用定义的sql语句

<trim>:空白补全,配合<if>标签使用

<if test="">:条件判断,该语句返回的true,则该标签内的语句就生效

<bind name="" value="">:创建一个变量,并且可以绑定到上下文

1、统一的增删改

通过我暂时的开发经验来说,我认为对一张表增删改操作,起码包括:增加一条记录、删除一条记录、修改一条记录。所以一张表的操作起码包括:增删改。

增加一条是主键id自增,删除一条记录是根据主键id删除,修改一条记录是根据主键id修改,返回值都是Integer类型的成功增删改的记录条数。以User对象为例:

UserMapper.java:


@Mapper
@Repository
public interface UserMapper {

/**
    * 增加一条记录
    * @param user 用户对象
    * @return 增加成功的记录数
    */
   Integer insertOne(User user);

/**
    * 删除一条记录
    * @param user 用户对象
    * @return 删除成功的记录数
    */
   Integer deleteOne(User user);

/**
    * 修改用户
    * @param user 用户对象
    * @return 修改成功的记录数
    */
   Integer updateOne(User user);
}

则对应的UserMapper.xml:


<mapper namespace="UserMapper">
   <!--update的条件sql(除了自增主键id)-->
   <sql id="updateCondition">
       <if test=" uuid!=null and uuid!='' ">
           uuid = #{uuid},
       </if>
       <if test=" username!=null and username!='' ">
           username = #{username},
       </if>
       <if test=" password!=null and password!='' ">
           password = #{password},
       </if>
   </sql>
   <!--新增一条-->
   <insert id="insertOne"
           keyProperty="id"
           useGeneratedKeys="true"
           parameterType="User">
       INSERT INTO
           user
           (uuid,username,password)
       VALUES
           (#{uuid},#{username},#{password})
   </insert>
   <!--删除一条-->
   <delete id="deleteOne"
           parameterType="User">
       DELETE FROM user WHERE id = #{id}
   </delete>
   <!--修改一条(根据id主键)-->
   <update id="updateOne"
           parameterType="User">
       UPDATE
           user
       <trim prefix="SET" suffixOverrides=",">
           <include refid="updateCondition"></include>
       </trim>
       WHERE
           id = #{id}
   </update>
</mapper>

由于一般修改语句是根据id,所以在<update>标签中,WHERE id = #{id}是写死了的。一般修改的话,是除了id可以修改其余都是可以修改的,所以一般字段会比较多,利用<sql>标签预定义好除了id的字段,并且利用<if>标签包裹起来,同时特别注意:最后要加上逗号。然后在<trim>标签中利用<include>标签引用预定义的修改语句的条件。<include>标签就相当于直接把该id的sql语句直接粘贴到这里,这里是为了看起整体排版比较舒服所以才这么做的。

2、统一的查询

通过我暂时的开发经验来说,我认为对一张表查询操作,起码包括:查询多条记录(可分页可条件)、查询一条记录(可条件),查询该表的总记录数。所以一张表的操作起码包括:三个查询。

查询列表、单个查询、查询该表的总记录数,同样是以User对象为例:

UserMapper.java:


@Mapper
@Repository
public interface UserMapper {

/**
    * 查询所有user集合(可分页,可多条件,可单条件)
    * @param user 用户对象
    * @return user集合
    */
   List<User> selectList(User user);

/**
    * 查询一条user记录(可多条件,可单条件)
    * @param user
    * @return  一条用户对象
    */
   User selectOne(User user);

/**
    * 查询记录数(可条件查询)
    * @param user  用户对象
    * @return  记录数
    */
   Long count(User user);

}

分别返回User集合、单个User对象以及记录数。

对应的UserMapper.xml:


<mapper namespace="UserMapper">
   <!--select的条件sql(全有)-->
   <sql id="selectCondition">
       <if test=" id!=null and id!='' ">
           AND u.id = #{id}
       </if>
       <if test=" uuid!=null and uuid!='' ">
           AND u.uuid = #{uuid}
       </if>
       <if test=" username!=null and username!='' ">
           AND u.username = #{username}
       </if>
       <if test=" password!=null and password!='' ">
           AND u.password = #{password}
       </if>
   </sql>
   <!--分页的条件sql(当前页,每页记录数)-->
   <sql id="limitCondition">
       <if test=" currentPage!=null and currentPage!='' and pageSize!=null and pageSize!='' ">
           <bind name="offset" value="pageSize*(currentPage-1)"/>
           <bind name="rows" value="pageSize"/>
           #{offset},#{rows}
       </if>
   </sql>
   <!--user表的别名-->
   <sql id="userAs">
       u.id                AS uId,
       u.uuid              AS uUuid,
       u.username          AS uUsername,
       u.password          AS uPassword
   </sql>
   <!--返回的结果集-->
   <resultMap id="userMap" type="User">
       <id column="uId" property="id"/>
       <result column="uUuid" property="uuid"/>
       <result column="uUsername" property="username"/>
       <result column="uPassword" property="password"/>
   </resultMap>
   <!--查询所有(可分页,可单条件,可多条件)-->
   <select id="selectList"
           parameterType="User"
           resultMap="userMap">
       SELECT
           <include refid="userAs"></include>
       FROM
           user u
       <trim prefix="WHERE" prefixOverrides="AND">
           <include refid="selectCondition"></include>
       </trim>
       ORDER BY
           u.id
       <trim prefix="LIMIT">
           <include refid="limitCondition"></include>
       </trim>
   </select>
   <!--查询一条(可单条件,可多条件)-->
   <select id="selectOne"
           parameterType="User"
           resultMap="userMap">
       SELECT
           <include refid="userAs"></include>
       FROM
           user u
       <trim prefix="WHERE" prefixOverrides="AND">
           <include refid="selectCondition"></include>
       </trim>
   </select>
   <!--查询记录数(可单条件,可多条件)-->
   <select id="count"
           parameterType="User"
           resultType="long">
       SELECT
           count(u.id)
       FROM
           user u
       <trim prefix="WHERE" prefixOverrides="AND">
           <include refid="selectCondition"></include>
       </trim>
   </select>
</mapper>

根据三个需求:查询全表、查询单个两个都可以用到条件查询,所以都可以用到同样的sql,所以就可以使用同样的<sql>标签来预定义然后复用。小结一下就是:

  • 查询全表:查询字段、可全条件、可分页

  • 查询单个:查询字段、可全条件

  • 查询记录数:可全条件

得益于<trim>标签和<if>标签的配合(if标签判断条件是否成立,如果成立则if标签内部语句生效,trim判断内部是否有语句,如果有则trim生效),没有条件传入就查询全表,没有分页传入的时候就不分页,做到了有条件则查条件,无条件则全查,有分页则查分页,无分页则全查。同时定义好结果集映射(column是查出来的列,property是Pojo对象的属性,需要对应好)以及配置好查询字段的别名(AS)。定义结果集和配置查询字段的别名是方便以后扩展。

条件查询的<sql>需要注意的是利用AND连接。

分页的<sql>需要注意的是利用<bind>标签来定义变量,注意变量的换算,一般采用的是传入当前页(currentPage)和每页记录数(pageSize),而数据库中limit语句的参数是limit offset,rows,offset(偏移量,也就是从表中的第几个元素开始,0是首位),rows(记录数,也就是返回多少个),总的来说就是从第几个开始,返回第条记录。然后利用简单的数学换算,将currentPage和pageSize转换为offset和rows。

<trim>标签的使用,利用<include>标签引入相应的sql语句后,再用<trim>标签包围,注意好prefix、suffix、prefixOverrides和suffixOverrides。

注意

SQL语句中各关键字的顺序

3、统一的增删改查

最后将增删改和查询总结合并起来就是:

UserMapper.java:


@Mapper
@Repository
public interface UserMapper {

/**
    * 增加一条记录
    * @param user 用户对象
    * @return 增加成功的记录数
    */
   Integer insertOne(User user);

/**
    * 删除一条记录
    * @param user 用户对象
    * @return 删除成功的记录数
    */
   Integer deleteOne(User user);

/**
    * 修改用户
    * @param user 用户对象
    * @return 修改成功的记录数
    */
   Integer updateOne(User user);

/**
    * 查询所有user集合(可分页,可多条件,可单条件)
    * @param user 用户对象
    * @return user集合
    */
   List<User> selectList(User user);

/**
    * 查询一条user记录(可多条件,可单条件)
    * @param user
    * @return  一条用户对象
    */
   User selectOne(User user);

/**
    * 查询记录数(可条件查询)
    * @param user  用户对象
    * @return  记录数
    */
   Long count(User user);

}

UserMapper.xml:


<mapper namespace="UserMapper">
   <!--select的条件sql(全有)-->
   <sql id="selectCondition">
       <if test=" id!=null and id!='' ">
           AND u.id = #{id}
       </if>
       <if test=" uuid!=null and uuid!='' ">
           AND u.uuid = #{uuid}
       </if>
       <if test=" username!=null and username!='' ">
           AND u.username = #{username}
       </if>
       <if test=" password!=null and password!='' ">
           AND u.password = #{password}
       </if>
   </sql>
   <!--update的条件sql(除了自增主键id)-->
   <sql id="updateCondition">
       <if test=" uuid!=null and uuid!='' ">
           uuid = #{uuid},
       </if>
       <if test=" username!=null and username!='' ">
           username = #{username},
       </if>
       <if test=" password!=null and password!='' ">
           password = #{password},
       </if>
   </sql>
   <!--分页的条件sql(当前页,每页记录数)-->
   <sql id="limitCondition">
       <if test=" currentPage!=null and currentPage!='' and pageSize!=null and pageSize!='' ">
           <bind name="offset" value="pageSize*(currentPage-1)"/>
           <bind name="rows" value="pageSize"/>
           #{offset},#{rows}
       </if>
   </sql>
   <!--user表的别名-->
   <sql id="userAs">
       u.id                AS uId,
       u.uuid              AS uUuid,
       u.username          AS uUsername,
       u.password          AS uPassword
   </sql>
   <!--返回的结果集-->
   <resultMap id="userMap" type="User">
       <id column="uId" property="id"/>
       <result column="uUuid" property="uuid"/>
       <result column="uUsername" property="username"/>
       <result column="uPassword" property="password"/>
   </resultMap>
   <!--新增一条-->
   <insert id="insertOne"
           keyProperty="id"
           useGeneratedKeys="true"
           parameterType="User">
       INSERT INTO
           user
           (uuid,username,password)
       VALUES
           (#{uuid},#{username},#{password})
   </insert>
   <!--删除一条-->
   <delete id="deleteOne"
           parameterType="User">
       DELETE FROM user WHERE id = #{id}
   </delete>
   <!--修改一条(根据id主键)-->
   <update id="updateOne"
           parameterType="User">
       UPDATE
           user
       <trim prefix="SET" suffixOverrides=",">
           <include refid="updateCondition"></include>
       </trim>
       WHERE
           id = #{id}
   </update>
   <!--查询所有(可分页,可单条件,可多条件)-->
   <select id="selectList"
           parameterType="User"
           resultMap="userMap">
       SELECT
           <include refid="userAs"></include>
           user u
           JOIN role r on u.roleId = r.id
       <trim prefix="WHERE" prefixOverrides="AND">
           <include refid="selectCondition"></include>
       </trim>
       ORDER BY
           u.id
       <trim prefix="LIMIT">
           <include refid="limitCondition"></include>
       </trim>
   </select>
   <!--查询一条(可单条件,可多条件)-->
   <select id="selectOne"
           parameterType="User"
           resultMap="userMap">
       SELECT
           <include refid="userAs"></include>
       FROM
           user u
       <trim prefix="WHERE" prefixOverrides="AND">
           <include refid="selectCondition"></include>
       </trim>
   </select>
   <!--查询记录数(可单条件,可多条件)-->
   <select id="count"
           parameterType="User"
           resultType="long">
       SELECT
           count(u.id)
       FROM
           user u
       <trim prefix="WHERE" prefixOverrides="AND">
           <include refid="selectCondition"></include>
       </trim>
   </select>
</mapper>

对一张表的操作最起码就应该包括以上:增加一条记录、删除一条记录、修改一条记录、查询列表(可条件、可分页)、查询一条(可条件)、查询记录数(可条件)。

4、利用IDEA的Code Templates自动生成

总结后观察到,每张表都有这6个操作,并且代码基本上都大致相同,差别只是对象的名字和表中字段不一样,那我每次创建Mapper文件都需要手敲吗?NoNoNo,可以利用IDEA的Code Templates功能,预先定义好Mapper Java和Mapper Xml的大致结构,然后利用传参传入对象名就可以了,这样每次就能自动生成大量代码,然后只需要修改极少部分代码就可以了。

Code Templates文件的创建:

打开IDEA,左上角依次点击:File->搜索template->找到File and Code Templates,在右侧创建新文件,输入文件名,扩展名Java:


#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "") package ${PACKAGE_NAME};#end

import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;

import java.util.List;
#parse("File Header.java")

@Mapper
@Repository
public interface ${NAME} {

/**
    * 增加一条记录
    * @param ${pojo} ${name}对象
    * @return 增加成功的记录数
    */
   Integer insertOne(${Pojo} ${pojo});

/**
    * 删除一条记录
    * @param ${pojo} ${name}对象
    * @return 删除成功的记录数
    */
   Integer deleteOne(${Pojo} ${pojo});

/**
    * 修改一条记录
    * @param ${pojo} ${name}对象
    * @return 修改成功的记录数
    */
   Integer updateOne(${Pojo} ${pojo});

/**
    * 查询所有集合(可分页,可多条件,可单条件)
    * @param ${pojo} ${name}对象
    * @return ${pojo}集合
    */
   List<${Pojo}> selectList(${Pojo} ${pojo});

/**
    * 查询一条${pojo}记录(可多条件,可单条件)
    * @param ${pojo} ${name}对象
    * @return  一条${name}对象
    */
   ${Pojo} selectOne(${Pojo} ${pojo});

/**
    * 查询记录数(可条件查询)
    * @param ${pojo}  ${name}对象
    * @return  记录数
    */
   Long count(${Pojo} ${pojo});

}

${Pojo}:Pojo对象的类名

${pojo}:Pojo对象的变量名

这样下次在新建Mapper.java文件的时候直接利用该template创建就可以了。

同样的,Mapper.xml:


<?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="${PRE}.mapper.${NAME}">
   <!--select的条件sql(全有)-->
   <sql id="selectCondition">
       <if test=" arg!=null and arg!='' ">
           AND arg = #{arg}
       </if>
   </sql>
   <!--update的条件sql(除了自增主键id)-->
   <sql id="updateCondition">
       <if test=" arg!=null and arg!='' ">
           arg = #{arg},
       </if>
   </sql>
   <!--分页的条件sql(当前页,每页记录数)-->
   <sql id="limitCondition">
       <if test=" currentPage!=null and currentPage!='' and pageSize!=null and pageSize!='' ">
           <bind name="offset" value="pageSize*(currentPage-1)"/>
           <bind name="rows" value="pageSize"/>
           #{offset},#{rows}
       </if>
   </sql>
   <!--返回的结果集-->
   <resultMap id="${Pojo}Map" type="${PRE}.pojo.${Pojo}">
       <id column="id" property="id"/>
       <result column="" property=""/>
   </resultMap>
   <!--新增一条记录-->
   <insert id="insertOne"
           keyProperty="id"
           useGeneratedKeys="true"
           parameterType="${PRE}.pojo.${Pojo}">
       INSERT INTO
           ${TABLE_NAME}
           ()
       VALUES
           ()
   </insert>
   <!--删除一条记录-->
   <delete id="deleteOne"
           parameterType="${PRE}.pojo.${Pojo}">
       DELETE FROM
           ${TABLE_NAME}
       WHERE
           id = #{id}
   </delete>
   <!--修改一条记录(根据id主键)-->
   <update id="updateOne"
           parameterType="${PRE}.pojo.${Pojo}">
       UPDATE
           ${TABLE_NAME}
       <trim prefix="SET" suffixOverrides=",">
           <include refid="updateCondition"></include>
       </trim>
       WHERE
           id = #{id}
   </update>
   <!--查询所有(可分页,可单条件,可多条件)-->
   <select id="selectList"
           parameterType="${PRE}.pojo.${Pojo}"
           resultMap="${Pojo}Map">
       SELECT
           *
       FROM
           ${TABLE_NAME}
       <trim prefix="WHERE" prefixOverrides="AND">
           <include refid="selectCondition"></include>
       </trim>
       ORDER BY
           id
       <trim prefix="LIMIT">
           <include refid="limitCondition"></include>
       </trim>
   </select>
   <!--查询一条(可单条件,可多条件)-->
   <select id="selectOne"
           parameterType="${PRE}.pojo.${Pojo}"
           resultMap="${Pojo}Map">
       SELECT
           *
       FROM
           ${TABLE_NAME}
       <trim prefix="WHERE" prefixOverrides="AND">
           <include refid="selectCondition"></include>
       </trim>
   </select>
   <!--根据主键id(效率高)查询记录数(可单条件,可多条件)-->
   <select id="count"
           parameterType="${PRE}.pojo.${Pojo}"
           resultType="long">
       SELECT
           count(id)
       FROM
           ${TABLE_NAME}
       <trim prefix="WHERE" prefixOverrides="AND">
           <include refid="selectCondition"></include>
       </trim>
   </select>
</mapper>

${PRE}:包的前缀

${Pojo}:对象的类名

${TABLE_NAME}:表名

即可以非常快速地生成Mapper.java和Mapper.xml了

5、连接关系表

因为Mybatis的特性,它可以连表查询。同样的,我们利用上述的方法创建好RoleMapper,如果想要在UserMapper中使用RoleMapper中定义好的sql,那么直接使用<include refid="包名+id">,下面是在UserMapper.xml中使用user表和role表连表查询列表举例:


<!--查询所有(可分页,可单条件,可多条件)-->
   <select id="selectList"
           parameterType="com.fangaoxs.userserver.pojo.User"
           resultMap="userMap">
       SELECT
           <include refid="userAs"></include>,
           <include refid="com.xxx.userserver.mapper.RoleMapper.roleAs"></include>
       FROM
           user u
           JOIN role r on u.roleId = r.id
       <trim prefix="WHERE" prefixOverrides="AND">
           <include refid="selectCondition"></include>
       </trim>
       ORDER BY
           u.id
       <trim prefix="LIMIT">
           <include refid="limitCondition"></include>
       </trim>
   </select>

那么,这样就实现了user表和role的联合查询,并且roleMapper.xml中的<sql>也在userMapper.xml中得到了复用。

总结

来源:https://blog.csdn.net/weixin_45747080/article/details/116605226

标签:mybatis,标签
0
投稿

猜你喜欢

  • Android Studio导入jar包过程详解

    2023-01-02 08:04:51
  • Java利用openoffice将doc、docx转为pdf实例代码

    2023-08-07 23:44:34
  • android编程实现sd卡读取数据库的方法

    2021-10-03 12:26:31
  • 解析如何在android中增加gsensor驱动(MMA7660)

    2023-05-22 22:03:24
  • Java实现循环体的过滤器的方法

    2023-11-22 09:35:33
  • Java判断用户名和密码是否符合要求过程详解

    2023-09-24 08:08:36
  • C#多线程中的互斥锁Mutex

    2022-04-26 06:11:55
  • Springboot通过谷歌Kaptcha 组件生成图形验证码功能

    2021-07-24 23:42:47
  • Java mybatis 开发自定义插件

    2022-11-26 03:29:24
  • C# XML序列化方法及常用特性总结分析

    2021-12-27 02:23:33
  • Java泛型中<?>和<T>的区别浅析

    2023-11-25 05:20:09
  • Java ExecutorService四种线程池使用详解

    2023-05-17 07:12:56
  • Android 九宫格的实现方法

    2022-08-19 01:07:09
  • Android编程使WebView支持HTML5 Video全屏播放的解决方法

    2022-04-11 08:25:15
  • 详解spring中的Aware接口功能

    2023-07-02 00:36:01
  • SpringBoot@DeleteMapping(/xxx/{id})请求报405的解决

    2022-06-13 14:00:48
  • 详解Java变量与常量

    2023-11-09 21:00:14
  • 详解MyBatis XML配置解析

    2023-11-23 13:02:09
  • Android 自定义view和属性动画实现充电进度条效果

    2023-08-24 00:18:37
  • C#中的委托使用

    2021-08-12 09:36:57
  • asp之家 软件编程 m.aspxhome.com