Mybatis框架学习之使用篇二:标签语法

文章目录
  1. Mybatis框架学习之使用篇二:标签语法
    1. I. 结构标签
      1. 1. 结构说明
      2. 2. sql片段定义
      3. 3. 常见标签
    2. II. 内部标签
      1. 1. where
        1. a. case1 无查询条件
        2. b. case2 最前or最后的连接条件
        3. c. trim标签
      2. 2. foreach
      3. 3. Choose
      4. 4. if
      5. 5. set标签
      6. 6. bind
    3. III. 参数替换
      1. 1. map传递
      2. 2. 参数位置替换
      3. 3. 注解指定方式
      4. 4. $#区别
    4. IV. 其他
      1. 项目工程
      2. 个人博客: 一灰灰Blog
      3. 声明
      4. 扫描关注

Mybatis框架学习之使用篇二:标签语法

常用标签的使用姿势小结及参数绑定的三种方式

  • select
  • update
  • delete
  • insert
  • choose, when, otherwise
  • if
  • bind
  • foreach
  • trim
  • set
  • where

I. 结构标签

xml中,一般常见的写法如下

1
2
3
<select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.String" >  
selext * from xxx where ...
</select>

1. 结构说明

分析上面的demo,三个参数比较重要

  • id:与dao层接口中定义的方法对应,不允许出现相同id的case
  • resultMap: 出参
  • resultType: 出参类型
  • parameterType:传参类型

2. sql片段定义

一般我们查询时,大多不建议直接使用 select * 的方式,而是具体的写上查询的列,然后一个问题就来了,每个查询都得写上一遍,不仅麻烦,对于后续表结构标定时,需要改的地方要多,所以就有了sql片段定义

  • :通过该标签可定义能复用的sql语句片段,在执行sql语句标签中直接引用即可。这样既可以提高编码效率,还能有效简化代码,提高可读性

实际case

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<sql id="poetryEntity">
id, title, author, content, `explain`, `type`, `tag`, `theme`, `is_deleted` as isDeleted,
UNIX_TIMESTAMP(`created_at`) as created,
UNIX_TIMESTAMP(`updated_at`) as updated
</sql>

<!-- 引用方式 -->
<select id="queryPoetryById" parameterType="long" resultType="com.git.hui.demo.mybatis.entity.PoetryEntity">
select
<include refid="poetryEntity"/>
from
poetry
where
id=#{id}
</select>

3. 常见标签

1
2
3
4
- <select>  表示这是一个查询sql
- <update> 更新sql
- <delete> 删除sql
- <insert> 插入sql

II. 内部标签

1. where

通常sql中,所有的where都可以被<where>替换,而这个标签的主要作用是为了防止sql可能出现的异常状况,如以下几种case

a. case1 无查询条件

1
2
3
4
select * from table where
<if test="id != null">
id = #{id}
</if>

当id不存在时,导致上面的sql被解析为 select * from table where, 显然这是一个非法sql

b. case2 最前or最后的连接条件

1
2
3
4
5
6
7
select * from table where
<if test='id != null'>
id = #{id}
</if>
<if test='uname != null'>
and uname=#{uname}
</if>

当id不存在,uname存在时,上面的sql被解析为 select * from table where and uname=#{uname, 显然也是非法sql

所以,这种场景下,用<where>标签优势就很明显了,在解析时,会根据实际的sql,来决定是否有where,是否去掉前面和后面非法的and/or

c. trim标签

除了直接使用where标签之外,更常见的一个就是标签了,

  • prefix:前缀
  • suffix:后缀
  • prefixOverrides:忽略第一个指定分隔符
  • suffixOverrides:会略最后一个分隔符
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<select id="user" parameterType="user" resultType="User">
select * from user
<trim prefix="WHERE" prefixoverride="and | or">
    <if test="id!=null and id!=''">
       id=#{id}
    </if>
    <if test="name!=null and name!=''">
       and name=#{name}
    </if>
    <if test="gender!=null and gender!=''">
       and gender=#{gender}
</if>
</trim>
</select>

2. foreach

用于循环的场景,如常见的 xxx in (xxx, xxx) ,通常就是foreach来使用

  • collection:迭代的参数,一般是个列表or数组,值一般直接为参数名
  • index: 迭代过程中,元素的别称
  • open: 开始符号 如(
  • close: 结束符号,如)
  • separator:分割符号

一个实际case如下

接口为:

1
List<PoetryEntity> queryPoetryByIds(@Param("ids") List<Long> ids);

对应的sql为

1
2
3
4
5
6
7
8
9
10
11
12
<select id="queryPoetryByIds" resultType="com.git.hui.demo.mybatis.entity.PoetryEntity">
select
<include refid="poetryEntity"/>
from
poetry
where
id IN
<foreach collection="ids" index="index" item="id" open="(" separator="," close=")">
#{id}
</foreach>
limit 500
</select>

3. Choose

选择标签,类似java中的switch,一旦其中一个条件匹配,整个choose块结束

一个xml如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<select id="getUserList_choose" resultMap="resultMap_user" parameterType="com.yiibai.pojo.User">  
SELECT *
FROM User u
<where>
<choose>
<when test="username !=null ">
u.username LIKE CONCAT(CONCAT('%', #{username, jdbcType=VARCHAR}),'%')
</when >
<when test="sex != null and sex != '' ">
AND u.sex = #{sex, jdbcType=INTEGER}
</when >
<when test="birthday != null ">
AND u.birthday = #{birthday, jdbcType=DATE}
</when >
<otherwise>
limit 10
</otherwise>
</choose>
</where>
</select>

mybatis的这个选择,基本上和我们的switch语句一样, 对应关系如下

1
2
3
4
5
6
7
<choose>                 ---- switch

<when></when> ---- case cond1
<when></when> ---- case cond2

<otherwise></otherwise> ---- default
</choose>

4. if

条件判断,在拼装sql时,最常见的就是为了防止传入null的参数,导致拼出一个业务逻辑有问题的sql,用if标签就很有用了

使用姿势也比较简单了,主要是内部的test条件判断

1
2
3
<if test="sex != null and sex != ''"> 
and sex=#{sex}
</if>

5. set标签

更新的时候使用,同样是为了解决拼装成的sql中,最前面or最后面的英文逗号

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<update id="userUpdate" parameterType="user">
  update user
  <set>
   <if test="id!=null and id!=''">
   id=#{id},
   </if>
   <if test="name!=null and name!=''">
    name=#{name},
</if>
   <if test="gender!=null and gender!=''">
    gender=#{gender},
   </if>
  </set>
</update>

6. bind

bind 元素可以从 OGNL 表达式中创建一个变量并将其绑定到上下文

比如对于like查询,需要在参数的前面or后面加上 %, 就可以这么玩:

1
2
3
4
5
6
7
8
9
<select id="queryPoetryByContent" resultType="com.git.hui.demo.mybatis.entity.PoetryEntity">
<bind name="pattern" value="'%' + content + '%'" />
select
<include refid="poetryEntity"/>
from
poetry
where content LIKE #{pattern}
limit 10
</select>

上面的也可以使用concat来做,如下

1
2
3
4
5
6
7
8
<select id="queryPoetryByContent" resultType="com.git.hui.demo.mybatis.entity.PoetryEntity">
select
<include refid="poetryEntity"/>
from
poetry
where content LIKE CONCAT(CONCAT('%', #{content}), '%')
limit 10
</select>

III. 参数替换

dao层的参数,是如何传入到xml中的sql语句的呢?

1. map传递

dao层接口参数为map,xml中可以直接通过map中的key,来绑定参数

1
public User selectUser(Map paramMap);

假设传入的参数为两个,uname, password

对应的xml为

1
2
3
<select id=" selectUser" resultMap="BaseResultMap">
select * from users where uname = #{uname,jdbcType=VARCHAR} and password=#{password,jdbcType=VARCHAR}
</select>

2. 参数位置替换

这种是直接根据参数的索引位置来绑定, {0} 表示第一个参数, {1} 表示第二个参数

1
public User selectUser(String uname, String password);

对应的xml

1
2
3
<select id=" selectUser" resultMap="BaseResultMap">
select * from users where uname = #{0} and password=#{1}
</select>

3. 注解指定方式

通过 @Param注解,直接指定name,在sql中即可通过name方式引用

1
public User selectUser(@Param("uname") String uname, @Param("password") String password);

对应的sql为

1
2
3
<select id=" selectUser" resultMap="BaseResultMap">
select * from users where uname = #{uname,jdbcType=VARCHAR} and password=#{password,jdbcType=VARCHAR}
</select>

4. $#区别

使用#传入参数是,sql语句解析是会加上””,

比如 select * from table where name = #{name} ,传入的name为小李,那么最后打印出来的就是

select * from table where name = "小李",就是会当成字符串来解析

因此在动态排序时,比如 order by column,这个时候务必要用${},因为如果你使用了#{}

区别

  • #将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号
  • $将传入的数据直接显示生成在sql中
  • #方式能够很大程度防止sql注入
  • $方式无法防止Sql注入
  • $方式一般用于传入数据库对象,例如传入表名,列名

简单来说,两者区别: $ 是sql替换,直接拼成一条可执行sql; # 是参数替换

IV. 其他

项目工程

个人博客: 一灰灰Blog

基于hexo + github pages搭建的个人博客,记录所有学习和工作中的博文,欢迎大家前去逛逛

声明

尽信书则不如,已上内容,纯属一家之言,因本人能力一般,见识有限,如发现bug或者有更好的建议,随时欢迎批评指正

扫描关注

QrCode

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×