hincky的主页 hincky的主页
  • 学习笔记

    • Vue笔记
    • Vuepress
    • nginx
  • 语言类

    • java
    • go
    • python
    • 设计模式
  • 框架类

    • Spring
    • Spring Security
    • Mybatis
  • 容器技术

    • docker
    • k8s
    • helm
    • prometheus
    • grafana
    • jenkins
  • 命令集合

    • linux命令
    • docker命令
    • git命令
    • vim命令
    • k8s命令
  • 数据库

    • sql
    • mysql
  • 协议

    • 网络模型
    • http/1.1
    • WebSocket
    • http/2
    • TLS/SSL
    • tcp
    • IP
    • tcpdump抓包命令
    • wireshark抓包工具
  • 通用

    • Git
  • 技术分享

    • git push/pull总是超时怎么办
    • idea debug技巧
    • postman使用
    • 问题总结
    • idea使用技巧
  • Oauth2

    • Oauth2原理
  • 项目列表

    • redis项目
    • 微服务项目
  • 分类
  • 标签
  • 归档
  • 随笔
GitHub (opens new window)

Hincky

当有趣的人,做想做的事
  • 学习笔记

    • Vue笔记
    • Vuepress
    • nginx
  • 语言类

    • java
    • go
    • python
    • 设计模式
  • 框架类

    • Spring
    • Spring Security
    • Mybatis
  • 容器技术

    • docker
    • k8s
    • helm
    • prometheus
    • grafana
    • jenkins
  • 命令集合

    • linux命令
    • docker命令
    • git命令
    • vim命令
    • k8s命令
  • 数据库

    • sql
    • mysql
  • 协议

    • 网络模型
    • http/1.1
    • WebSocket
    • http/2
    • TLS/SSL
    • tcp
    • IP
    • tcpdump抓包命令
    • wireshark抓包工具
  • 通用

    • Git
  • 技术分享

    • git push/pull总是超时怎么办
    • idea debug技巧
    • postman使用
    • 问题总结
    • idea使用技巧
  • Oauth2

    • Oauth2原理
  • 项目列表

    • redis项目
    • 微服务项目
  • 分类
  • 标签
  • 归档
  • 随笔
GitHub (opens new window)
  • java

  • python

  • Spring

  • SpringMVC

  • SpringSecurity

  • Mybatis

    • mybatis介绍
      • mybatis简单操作实践
      • idea创建maven工程
    • 快速入门
      • 框架
      • 快速入门
      • 3.9 高效编程
        • 3.9.1 配置代码模板
        • 3.9.2 Mybatis插件
      • 4. 参数获取
        • 4.1 一个参数
        • 4.1.1 基本参数
        • 4.1.2 POJO
        • 4.1.3 Map
        • 4.2 多个参数
        • 4.3 总结
      • 5. 核心类
        • 5.1 SqlSessionFactory
        • 5.2 SqlSession
      • 6.Mybatis实现增删改查
        • 6.1 新增
        • 6.2 删除
        • 6.3 修改
        • 6.4 根据id查询
        • 6.5 查询所有
      • 7. 配置文件详解
        • 7.1 properties
        • 7.2 settings
        • 7.3 typeAliases
        • 7.4 environments
        • 7.5 mappers
      • 8. 打印日志
      • 9.获取参数时 #{}和${}的区别
    • 动态sql
      • 1. 注解开发
        • 1.1 步骤
      • 2.动态SQL
        • 2.1 if
        • 2.2 trim
        • 2.2.1 prefixOverrides属性
        • 2.2.2 suffixOverrides属性
        • 2.2.3 prefix属性
        • 2.2.4 suffix属性
        • 2.2.5 动态添加前缀where 并且消除前缀and或者or
        • 2.2 where
        • 2.3 set
        • 2.4 foreach
        • 2.5 choose、when、otherwise
      • 3. SQL片段抽取
    • 案例实践
      • 0. 案例环境
        • 0.1 案例数据初始化sql
        • 0.2 实体类
        • 0.2.1 User.java
        • 0.2.2 Order.java
        • 0.2.3 Role.java
      • 1. ResultMap
        • 1.1 基本使用
        • 1.2 自动映射
        • 1.3 继承映射关系
      • 2. 多表查询
        • 2.1 多表关联查询
        • 2.1.1 一对一关系
        • 2.1.1.1 使用ResultMap对所有字段进行映射
        • 2.1.1.2 使用ResultMap中的association
        • 2.1.2 一对多关系
        • 2.1.2.1 使用ResultMap中的collection
        • 2.2 分步查询
        • 2.2.1实现步骤
        • ①定义查询方法
        • ②配置分步查询
        • 2.2.2 设置按需加载
      • 3.分页查询-PageHelper
        • 3.1 实现步骤
        • ①定义方法查询方法以及生成对应标签
        • ② 引入依赖
        • ③ 配置Mybatis核心配置文件使用分页插件
        • ④ 开始分页查询
        • 3.2 一对多多表查询分页问题
      • 4.Mybatis缓存
        • 4.1 一级缓存
        • 4.2 二级缓存
        • 4.2.1 开启二级缓存
        • 4.2.2 使用建议
      • 5.Mybatis原理-单独专题讲解
  • 设计模式

  • Go

  • 后端
  • Mybatis
hincky
2022-11-08
目录

动态sql

# 1. 注解开发

​我们也可以使用注解的形式来进行开发,用注解来替换掉xml。 使用注解来映射简单语句会使代码显得更加简洁,但对于稍微复杂一点的语句,Java 注解不仅力不从心,还会让你本就复杂的 SQL 语句更加混乱不堪。 所以我们在实际企业开发中一般都是使用XML的形式。

# 1.1 步骤

①在核心配置文件中配置mapper接口所在的包名

    <mappers>
        <package name="com.sangeng.dao"></package>
    </mappers>
1
2
3

②在接口对应方法上使用注解来配置需要执行的sql

public interface UserDao {
    @Select("select * from user")
    List<User> findAll();

    @Insert("insert into user values(null,#{username},#{age},#{address})")
    void insertUser(User user);

    @Update("UPDATE USER SET age = #{age} , username = #{username},address = #{address} WHERE id = #{id}")
    void updateUser(User user);

    @Delete("delete from user where id = #{id}")
    void deleteById(Integer id);
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14

③和之前的一样获取Mapper调用方法即可

public static void main(String[] args) throws IOException {
    //定义mybatis配置文件的路径
    String resource = "mybatis-config.xml";
    InputStream inputStream = Resources.getResourceAsStream(resource);
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    //获取Sqlsession对象
    SqlSession sqlSession = sqlSessionFactory.openSession();
    //获取UserDao实现类对象
    UserDao userDao = sqlSession.getMapper(UserDao.class);
    //调用方法测试
    List<User> userList = userDao.findAll();
    System.out.println(userList);
    //释放资源
    sqlSession.close();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 2.动态SQL

​ 在实际开发中的SQL语句没有之前的这么简单,很多时候需要根据传入的参数情况动态的生成SQL语句。Mybatis提供了动态SQL相关的标签让我们使用。

# 2.1 if

​ 可以使用if标签进行条件判断,条件成立才会把if标签中的内容拼接进sql语句中。

例如:

<select id="findByCondition" resultType="com.sangeng.pojo.User">
        select * from user
        where  id = #{id}
    <if test="username!=null">
        and username = #{username}
    </if>
</select>
1
2
3
4
5
6
7

如果参数username为null则执行的sql为:select * from user where id = ?

如果参数username不为null则执行的sql为:select * from user where id = ? and username = ?

注意:在test属性中表示参数的时候不需要写#{},写了会出问题。

# 2.2 trim

​可以使用该标签动态的添加前缀或后缀,也可以使用该标签动态的消除前缀。

# 2.2.1 prefixOverrides属性

​ 用来设置需要被清除的前缀,多个值可以用|分隔,注意|前后不要有空格。例如: and|or

例如:

<select id="findByCondition" resultType="com.sangeng.pojo.User">
    select * from user
    <trim prefixOverrides="and|or" >
        and
    </trim>
</select>
1
2
3
4
5
6

最终执行的sql为: select * from user

# 2.2.2 suffixOverrides属性

​ 用来设置需要被清除的后缀,多个值可以用|分隔,注意|前后不要有空格。例如: and|or

例如:

    <select id="findByCondition" resultType="com.sangeng.pojo.User">
        select * from user
        <trim suffixOverrides="like|and" >
            where 1=1 like
        </trim>
    </select>
1
2
3
4
5
6

最终执行的sql为: select * from user 去掉了后缀like

# 2.2.3 prefix属性

​ 用来设置动态添加的前缀,如果标签中有内容就会添加上设置的前缀

例如:

    <select id="findByCondition" resultType="com.sangeng.pojo.User">
        select * from user
        <trim prefix="where" >
           1=1
        </trim>
    </select>
1
2
3
4
5
6

最终执行的sql为:select * from user where 1=1 动态增加了前缀where

# 2.2.4 suffix属性

​ 用来设置动态添加的后缀,如果标签中有内容就会添加上设置的后缀

    <select id="findByCondition" resultType="com.sangeng.pojo.User">
        select * from user
        <trim suffix="1=1" >
           where
        </trim>
    </select>
1
2
3
4
5
6

最终执行的sql为:select * from user where 1=1 动态增加了后缀1=1

# 2.2.5 动态添加前缀where 并且消除前缀and或者or

User findByCondition(@Param("id") Integer id,@Param("username") String username);
1
    <select id="findByCondition" resultType="com.sangeng.pojo.User">
        select * from user
        <trim prefix="where" prefixOverrides="and|or" >
            <if test="id!=null">
                id = #{id}
            </if>
            <if test="username!=null">
                and username = #{username}
            </if>
        </trim>
    </select>
1
2
3
4
5
6
7
8
9
10
11

调用方法时如果传入的id和username为null则执行的SQL为:select * from user

调用方法时如果传入的id为null,username不为null,则执行的SQL为:select * from user where username = ?

# 2.2 where

​ where标签等价于:

<trim prefix="where" prefixOverrides="and|or" ></trim>
1

​ 可以使用where标签动态的拼接where并且去除前缀的and或者or。

例如:

    <select id="findByCondition" resultType="com.sangeng.pojo.User">
        select * from user
        <where>
            <if test="id!=null">
                id = #{id}
            </if>
            <if test="username!=null">
                and username = #{username}
            </if>
        </where>
    </select>
1
2
3
4
5
6
7
8
9
10
11

如果id和username都为null,则执行的sql为:**select * from user **

如果id为null,username不为null,则执行的sql为:**select * from user where username = ? **

# 2.3 set

​ set标签等价于

<trim prefix="set" suffixOverrides="," ></trim>
1

​ 可以使用set标签动态的拼接set并且去除后缀的逗号。

例如:

    <update id="updateUser">
        UPDATE USER
        <set>
            <if test="username!=null">
                username = #{username},
            </if>
            <if test="age!=null">
                age = #{age},
            </if>
            <if test="address!=null">
                address = #{address},
            </if>
        </set>
        where id = #{id}
    </update>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

如果调用方法时传入的User对象的id为2,username不为null,其他属性都为null则最终执行的sql为:UPDATE USER SET username = ? where id = ?

# 2.4 foreach

​ 可以使用foreach标签遍历集合或者数组类型的参数,获取其中的元素拿来动态的拼接SQL语句。

例如:

方法定义如下

List<User> findByIds(@Param("ids") Integer[] ids);
1

如果期望动态的根据实际传入的数组的长度拼接SQL语句。例如传入长度为4个数组最终执行的SQL为:

select * from User WHERE id in( ? , ? , ? , ?, ? ) 
1

则在xml映射文件中可以使用以下写法

	<select id="findByIds" resultType="com.sangeng.pojo.User">
        select * from User
        <where>
            <foreach collection="ids" open="id in(" close=")" item="id" separator=",">
                #{id}
            </foreach>
        </where>
    </select>
1
2
3
4
5
6
7
8

collection:表示要遍历的参数。

open:表示遍历开始时拼接的语句

item:表示给当前遍历到的元素的取的名字

separator:表示每遍历完一次拼接的分隔符

close:表示最后一次遍历完拼接的语句

注意:如果方法参数是数组类型,默认的参数名是array,如果方法参数是list集合默认的参数名是list。建议遇到数组或者集合类型的参数统一使用@Param注解进行命名。

# 2.5 choose、when、otherwise

​ 当我们不想使用所有的条件,而只是想从多个条件中选择一个使用时。可以使用choose系列标签。类似于java中的switch。

例如:

接口中方法定义如下

List<User> selectChose(User user);
1

期望:

​ 如果user对象的id不为空时就通过id查询。

​ 如果id为null,username不为null就通过username查询。

​ 如果id和username都会null就查询id为3的用户

xml映射文件如下

 	<select id="selectChose" resultType="com.sangeng.pojo.User">
        select * from user
        <where>
            <choose>
                <when test="id!=null">
                    id = #{id}
                </when>
                <when test="username!=null">
                    username = #{username}
                </when>
                <otherwise>
                    id = 3
                </otherwise>
            </choose>
        </where>
    </select>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  • choose类似于java中的switch

  • when类似于java中的case

  • otherwise类似于java中的dufault

​ 一个choose标签中最多只会有一个when中的判断成立。从上到下去进行判断。如果成立了就把标签体的内容拼接到sql中,并且不会进行其它when的判断和拼接。如果所有的when都不成立则拼接otherwise中的语句。

# 3. SQL片段抽取

​ 我们在xml映射文件中编写SQL语句的时候可能会遇到重复的SQL片段。这种SQL片段我们可以使用sql标签来进行抽取。然后在需要使用的时候使用include标签进行使用。

例如:

    <sql id="baseSelect" >id,username,age,address</sql>
    <select id="findAll" resultType="com.sangeng.pojo.User">
        select <include refid="baseSelect"/>  from user
    </select>
1
2
3
4

最终执行的sql为: select id,username,age,address from user

编辑 (opens new window)
#Mybatis
快速入门
案例实践

← 快速入门 案例实践→

最近更新
01
人生前期重要的能力
05-17
02
防火墙命令
04-11
03
docker-compose部署mysql主从集群
03-22
更多文章>
Theme by Vdoing | Copyright © 2022-2023 Hincky | MIT License | 粤ICP备2022120427号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式