百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT技术 > 正文

15 个 MyBatis 技巧,赶紧收藏吧

wptr33 2025-01-10 17:39 20 浏览

MyBatis 作为一款 ORM 框架,在行业内有广泛的应用。mapper xml 的配置有一些技巧,本文整理一下,方便查阅。

模糊查询

MySQL 模糊查询一般是使用 like 条件,我们经常使用传入的变量作为 like 的条件。在 MyBatis 里面,like 使用变量需要用到 ${} 或者 concat。建议使用 concat,#{} 可以防止 SQL 注入。

like '%${value}%'
like concat('%',#{value},'%')


自动创建表

不建议在 MyBatis 里面建表,原则上数据表要由数据库管理员创建。但是对于一些小应用,可能开发者集多个角色于一身,自动建表反而利大于弊。如下的语句在 <select> 标签内使用了 CREATE TABLE IF NOT EXISTS 语法,可以在无表时自动建表,有表时会跳过执行。

<select id="createTable">
  CREATE TABLE IF NOT EXISTS `demo` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `path` varchar(128) NOT NULL COMMENT '路径'
  ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
</select>


自动判断更新或插入

数据不存在则插入,数据已存在则更新,可以使用 MySQL on duplicate key update 来实现。当 primary key 或者 unique key 重复时会自动执行 update。

insert into `webVisit`(`date`,`ip`, uri, `count`)
values(#{date},#{ip},#{uri}, 1)
ON DUPLICATE KEY
update `count` = `count` + 1


自动忽略重复插入

数据不存在则插入,数据已存在则忽略,可以使用 MySQL ignore 来实现。当 primary key 或者 unique key 重复时会自动忽略本次插入操作。

insert ignore into `webVisit`(`ip`) values(#{ip})


自动替换重复数据

数据不存在则插入,数据已存在则替换,可以使用 MySQL replace into 来实现。当 primary key 或者 unique key 重复时会自动替换已存在的数据。实际上是先删除原有数据,然后插入新数据。

replace into `webVisit`(`date`,`ip`, uri, `count`)
values(#{date},#{ip},#{uri}, 1)


使用缓存

使用缓存能够极大提升应用的性能。二级缓存的开启方式是

<cache flushInterval="60000"></cache>


新增、更新数据不刷新缓存

缓存在新增、更新数据时会自动失效,对于部分影响不大的操作可以设置不刷新缓存,方法是在语句 xml 上设置 flushCache=false。

<update id="demo" flushCache="false"></update>


获取生成的自增id

使用自增 id 有很多好处,可以通过配置 selectKey 实现 insert 执行后返回生成的自增 id,以用于后续流程。

<insert id="insert" parameterType="demo">
  <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Long">
    SELECT LAST_INSERT_ID()
  </selectKey>
  insert into `demo`(demo) values(#{demo})
</insert>


只更新部分字段

使用 <if> <set> 标签配合,可以实现只更新部分数据。一般是传入 null 不更新,非 null 则更新。

<if> 标签支持 test 配置一个表达式,表达式返回 true 时 <if> 内部的 SQL 片段会生效,否则不会生效。<set> 标签能够自动生成 set 片段,并处理去除首尾多余的字符。

<update id="updateById" parameterType="UserDO">
  update `user`
  <set>
    <if test="nick != null">
      nick = #{nick},
    </if>
    <if test="avatar != null">
      avatar = #{avatar},
    </if>
  </set>
  where userId = #{userId}
</update>


动态查询条件

使用 <if> <where> 标签配合,可以实现动态查询条件。<if> 标签能够实现条件判断。<where> 标签能够自动组装 where 片段,去除首尾的非法字符。

<select id="select" resultMap="resultMap">
  SELECT * FROM demo
  <where>
    <if test="userId != null">
      userId = #{userId}
    </if>
    <if test="nick != null">
      and nick = #{nick}
    </if>
  </where>
</select>


设置 SQL 超时时间

通过 timeout 属性可以设置超时时间,也就是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。

<update id="demo" timeout="100"></update>


复用 SQL 片段

用 sql 标签可以定义 SQL 片段,用于 SQL 语句复用。

<sql id="Base_Column_List">
  userId, email
</sql>
<select id="selectById" parameterType="java.lang.Long" resultMap="ResultMap">
  select
  <include refid="Base_Column_List" />
  from `user`
  where userId = #{userId}
</select>


批量插入数据

批量插入数据能够极大提升性能,曾经测试过多条数据插入时间从分钟级降低到秒级完成。批量插入主要用到 forEach 标签,把批量数据转换成 values 语句。

foreach 标签的属性主要有 item,index,collection,open,separator,close。

  • item:集合中元素迭代时的别名;
  • index:集合中元素迭代时的索引;
  • open:常用语where语句中,表示以什么开始,比如以'('开始;
  • separator:表示在每次进行迭代时的分隔符;
  • close 常用语where语句中,表示以什么结束;
  • collection:集合值;
<insert id="batchInsert" parameterType="java.util.List">
  insert into `demo`(userId,`url`)
  values
  <foreach collection="list" item="item" separator=",">
    (#{item.userId}, #{item.url})
  </foreach>
</insert>


匹配多个值

使用 forEach 构建查询条件集合,where 语句使用 in 即可实现匹配多个值。

<select id="queryById" resultMap="BaseReslutMap" >
  select * FROM entity
  where id in 
  <foreach collection="userids" item="userid" index="index" open="(" separator="," close=")">
    #{userid}
  </foreach>
</select>


条件语句

java 可以很方便地使用 if 或 switch 实现分支功能。MyBatis 的 choose 标签可以实现条件分支。如下的配置中,传入 id 时使用 id,不传则使用其他条件。

choose 标签是按顺序判断其内部when标签中的test条件出否成立,如果有一个成立,则 choose 结束。当 choose 中所有 when 的条件都不满则时,则执行 otherwise 中的sql。类似于Java 的 switch 语句,choose 为 switch,when 为 case,otherwise 则为 default。

<update id="update" parameterType="Config">
  update `config` set `content` = #{content}
  <where>
    <choose>
      <when test="id != null">
        id = #{id}
      </when>
      <otherwise>
        appName = #{appName} and t = #{t} and x = #{x}
      </otherwise>
    </choose>
  </where>
</update>

你的工资被倒挂了吗

终于知道 Java agent 怎么重写字节码了

每天的工作,你腻了吗?

10 分钟轻松学会 Jackson 反序列化自动适配子类

SpringMVC异步处理的 5 种方式

相关推荐

威信Chronosonic XVX全新旗舰全球首发 设计特点彻底公开

第一眼看到WilsonAudio新推出的ChronosonicXVX音箱,相信大家都会直觉认为它是两年前超级旗舰WAMMMasterChronosonic的缩小版,不过这个推测并不完全正确。C...

C#高精度Timer和Delay以及时间测量

在PCHMI7.0后在工具箱里会多一个MsTimer,以及Delay和Microsecond两个类。...

python教程从基础到精通,第9课—日期与时间

Hello,小伙伴们,祝大家五.一玩得快乐!刚学习完了七大数据类型,今天咱们来学习日期与时间的表示方法。Python标准库中提供了时间和日期的支持:calendar:日历相关;time、datetim...

软件测试|教你轻松玩转Python日期时间

Python基础之日期时间处理...

Go语言中互斥锁与读写锁,你知多少?

简述Golang中的锁机制主要包含互斥锁和读写锁互斥锁互斥锁是传统并发程序对共享资源进行控制访问的主要手段。在Go中主要使用sync.Mutex的结构体表示。一个简单的示例:funcmutex()...

变形金刚动画大电影——经典台词赏析

YOURDAYSARENUMBEREDNOW,DECEPTI-CREEPS你们活不了多久了,霸天虎小子。-{铁皮说的话,体现了铁皮的嫉恶如仇,可是后来铁皮在飞船上遇袭身亡,可谓是出师未捷身先...

Python时间日期模块使用教程(python3日期)

1.时间日期处理概述在日常编程中,时间日期处理是非常常见的需求,比如:记录日志时间...

亚马逊介绍AWS“无服务器”云服务改进:数据库可线上扩充容量等

IT之家11月29日消息,在今天于美国拉斯维加斯展开的亚马逊“AWSre:Invent2023”活动中,亚马逊计算部门资深副总裁PeterDeSantis,介绍了旗下三款云端服务,IT...

2.日期格式 datetime(日期时间显示格式)

fromdatetimeimportdatetime1.获取当前日期和时间now=datetime.now()#2025-05-3110:56:01.4687822.格式化日期...

【科普】时间单位大盘点(时间单位都有哪些?)

时间单位,是7种基本单位之一,长度、时间、质量、物质的量、光照度、电流和(热力学)温度是七种基本单位。本词条中时间单位以时间从大到小列。今天我们来盘点下时间的单位换算...

基于PHP的Laravel框架,盘点Github高星Web管理后台,效率为王!

在Web开发工作中,选择一个高效、稳定的后台管理系统是提高开发效率的关键。虽然PHP在近些年中的热度有所减退,但其上手简单、开源、灵活且被广泛应用的特点,仍然使其在编程语言排行榜中保持前十的位置。这表...

如何使用PHP编写一个简单的留言板?

留言板是一个常见的Web应用程序,允许用户在网站上发布和查看留言。在本文中,我们将使用PHP编写一个简单的留言板,介绍构建过程中的关键步骤和技巧。一、准备工作在开始编写留言板之前,我们需要准备好以下工...

产品经理提需求时要考虑的 15 个隐性需求

虽然世界充满未知的变化,但是有一些大的方向还是可以把握的,本文跟大家谈谈产品经理提需求时要考虑的15个隐性需求,enjoy~俗话说,计划赶不上变化快,无论需求文档做得如何细致,考虑得如何周全,总会...

关于 PHP 启动 MongoDb 找不到指定模块问题

前言:最近有一个小demo,需要通过PHP将用户行为记录储存到MongoDB,再用Spark做协同过滤。由于以前处理跨语言交互是通过消息中间件,这次本地使用MongoDB却弄出了几个问...

PHP程序员老鸟面试经历(php程序员怎么样)

在任何时代找任何工作都有面试这么一说的。特别是高端技术类的工种对技术理论和技术实操能力要求很严格。大部分公司招收技术员工的要求也越来愈高。至于PHP程序员也是如此,我估计大多数PHP老鸟已经不在意所...