目录

MyBatis使用技巧

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

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

1
<update id="demo" flushCache="flase"></update>

模糊查询

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

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

使用缓存

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

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

自动创建表

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

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

设置SQL超时时间

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

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

获取生成的自增长id

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

1
2
3
4
5
6
<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>

匹配多个值

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

1
2
3
4
5
6
7
<select id="querybyId" resultType="BaseResultMap">
	select * from entity
    where id in
    <forEach collection="userids" item="userid" index="index" open="(" seperator="," close=")">
    	#{userid}
    </forEach>
</select>

只更新部分字段

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

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<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片段,去除首尾的非法字符。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<select id="select" resultType="resultMap">
	SELECT * FROM demo
    <where>
    	<if test="userId != null">
        	userId = #{userId}
        </if>
        <if test="nick != null">
        	and nick= #{nick}
        </if>
    </where>
</select>

批量插入数据

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

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

item:集合中元素迭代时的别名;

index:集合中元素迭代时的索引;

open:常用于where语句中,表示以什么开始,比如以’(‘开始;

close:常用于where语句中,表示以什么结束;

collection:集合值;

1
2
3
4
5
6
7
<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>

条件语句

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

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<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>

复用SQL片段

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

1
2
3
4
5
6
7
8
9
<sql id="Base_Column_List">
	userid, email
</sql>
<select id="selectById" parameter="java.lang.Long" resultMap="ResultMap">
	select
    <include refid="Base_Column_List" />
    from `user`
    where userId = #{userId}
</select>