0
点赞
收藏
分享

微信扫一扫

【MyBatis】动态SQL

鱼满舱 2022-08-25 阅读 57
本文已收录于专栏
⭐️ 《MyBatis》⭐️

学习指南:

MyBatis

MyBatis 是一款优秀的持久层框架

MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集的过程

MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 实体类 【Plain Old Java Objects,普通的 Java对象】映射成数据库中的记录。

映射文件概述

在这里插入图片描述

常用配置

environments标签

数据源环境配置标签

数据库环境的配置,支持多环境配置

事务管理器(transactionManager)类型有两种:

    • JDBC:这个配置就是直接使用了JDBC 的提交和回滚设置,它依赖于从数据源得到的连接来管理事务作用域。

• MANAGED:这个配置几乎没做什么。它从来不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如JEE 应用服务器的上下文)。 默认情况下它会关闭连接,然而一些容器并不希望这样,因此需要将 closeConnection 属性设置 为 false 来阻止它默认的关闭行为。

数据源(dataSource)类型有三种:

    • UNPOOLED:这个数据源的实现只是每次被请求时打开和关闭连接。

• POOLED:这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来。

• JNDI:这个数据源的实现是为了能在如 EJB 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置 一个 JNDI 上下文的引用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3FQINKqN-1660785250531)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20220815093834929.png)]

mapper标签

加载映射配置

该标签的作用是加载映射的,加载方式有如下几种:

• 使用相对于类路径的资源引用,例如:

<mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
• 使用完全限定资源定位符(URL),例如:

<mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
• 使用映射器接口实现类的完全限定类名,例如:

<mapper class="org.mybatis.builder.AuthorMapper"/>
• 将包内的映射器接口实现全部注册为映射器,例如:

<package name="org.mybatis.builder"/>

Properties标签

该标签可以加载外部的properties文件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JgLr5W5g-1660785250532)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20220815094208642.png)]

typeAliases标签

设置类型别名

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5wHsPHCm-1660785250533)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20220815094057280.png)]

代理开发

采用 Mybatis 的代理开发方式实现 DAO 层的开发,这种方式是我们后面进入企业的主流。 Mapper 接口开发方法只需要程序员编写Mapper 接口(相当于Dao 接口),由Mybatis 框架根据接口定义创建接 口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法。

Mapper 接口开发需要遵循以下规范:

    1、 Mapper.xml文件中的namespace与mapper接口的全限定名相同

2、 Mapper接口方法名和Mapper.xml中定义的每个statement的id相同

3、 Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql的parameterType的类型相同

4、 Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同

对应关系图解

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ycZTwNNZ-1660785250534)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20220815094516358.png)]

开发步骤

①编写BrandMapper接口

②进行mapper文件的相应配置(要遵守规范)

③测试用例

①编写BrandMapper接口

public interface BrandMapper {
   //实现操作:查询所有
   List<Brand> selectAll();
}

②进行mapper文件的相应配置(要遵守规范)

<?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 = "com.spellbind.mapper.BrandMapper">
    <!--
    映射:resultMap
    在<select>标签中,使用 resultMap属性 替换 resultType 属性。
    映射其实就是指 给数据库表格中的字段取别名。
    id: 完成主键字段的映射。
    property:实体类的属性名。
        result:完成一般字段的映射。
        column:表的列名。
    -->
    <resultMap id="brandResultMap" type="brand">
        <result column="brand_name" property="brandName"></result>
        <result column="company_name" property="companyName"></result>
    </resultMap>

    <!--SQL操作:查询所有-->
    <select id="selectAll" resultMap="brandResultMap">
        select * from tb_brand;
    </select>

</mapper>

③测试代理方式:

@Test//查看所有
public void testSelectAll() throws Exception {
    //1.加载mybatis的核心配置文件,获取 SqlSessionFactory
    String resource = "mybatis-config.xml";
    InputStream inputStream = Resources.getResourceAsStream(resource);
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    //2.获取Sqlsession对象
    SqlSession sqlSession = sqlSessionFactory.openSession();
    //3.获取Mapper 接口的代理对象
    BrandMapper brandmapper = sqlSession.getMapper(BrandMapper.class);
    //4.执行方法
    List<Brand> brands = brandmapper.selectAll();

    System.out.println(brands);
    //5.关闭资源
    sqlSession.close();
}
* 参数占位符: 
1.#{}:会将其替换为 ?,为了防止SQL注入
2.${}:直接拼接 sql,存在SQL注入问题
3.使用时机:
* 参数传递时:#{}
* 表名或者列名不固定的情况下:${}会存在SQL注入问题

动态SQL

在传统的JDBC的操作中书写SQL语句是非常容易出错的,而Mybatis的动态SQL的出现则很巧妙的解决了这一问题。

其通过 if, choose, when, otherwise, trim, where, set, foreach 标签,可组合成非常灵活的SQL语句,从而大大提高开发效率。

if

Mybatis提供了 if 标签,可以实现针对多个参数进行可选搜索。

test:填入的是能否进行下面SQL语句的判断表达式

<select id="findUserById" resultType="users">
    select * from users 
    where 
        <if test="id != null">
               id > #{id}
        </if>
    	<if test="name != null">
        AND name like #{title}
</select>

执行的SQL语句是:

select * from users where id > 'xx' and name like 'xxx'

但这样会出现一系列语法问题。

当 id 为空时,and 会直接与 where相连

select * from users where and name like 'xxx'

当 id 和 age 都为空时,where 后面就没有了语句。

select * from users where

很显然,这样会造成运行错误

那么,如何解决上面所说的问题呢?mybatis给出了**<where>**元素。

where

<select id="findUserById" resultType="users">
    select * from users 
    <where>
        <if test="id != null">
               id > #{id}
        </if>
    	<if test="name != null">
        AND name like #{name}
    </where>
</select>

where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。

而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。

set

<update id="updateUser" parameterType="com.dy.entity.User">
    update user set 
        <if test="name != null">
            name = #{name},
        </if> 
        <if test="password != null">
            password = #{password},
        </if> 
        <if test="age != null">
            age = #{age}
        </if> 
        <where>
            <if test="id != null">
                id = #{id}
            </if>
            and deleteFlag = 0;
        </where>
</update>

从上面这里我们可以发现,如果只有 name 不为空时,SQL语句则变为:

update set name = #{name}, where deleteFlag = 0;

此时 name 后面的逗号 则会导致语法错误。

我们需要用mybatis为我们提供的set 标签来解决这个问题。

<update id="updateUser" parameterType="com.dy.entity.User">
    update user
        <set>
            <if test="name != null">name = #{name},</if> 
            <if test="password != null">password = #{password},</if> 
            <if test="age != null">age = #{age},</if> 
        </set>
        <where>
            <if test="id != null">
                id = #{id}
            </if>
            and deleteFlag = 0;
        </where>
</update>

foreach

当接收多个参数时,一个一个写显然过于麻烦,mybatis中的foreach标签可以帮助我们直接遍历数组.

动态 SQL 的另一个常见使用场景是对集合进行遍历(尤其是在构建 IN 条件语句的时候)。

属性描述
collection表示集合的名称,默认名为 array,可以使用@Param注解指定, 该参数为必选
item表示本次迭代获取的元素,若collection为List、Set或者数组,则表示其中的元素;若collection为map,则代表key-value的value,该参数为必选
open表示该语句以什么开始,最常用的是左括弧’(’,注意:mybatis会将该字符拼接到整体的sql语句之前,并且只拼接一次,该参数为可选项
close表示该语句以什么结束,最常用的是右括弧’)’,注意:mybatis会将该字符拼接到整体的sql语句之后,该参数为可选项
separatormybatis会在每次迭代后给sql语句append上separator属性指定的字符,该参数为可选项
index在list、Set和数组中,index表示当前迭代的位置,在map中,index代指是元素的key,该参数是可选项。
<select id="getBlogListByIds" parameterType="map" resultType="com.company.org.pojo.Blog">
    select * from blog
    <where>
        id in
        <foreach collection="ids" item="id" open="(" separator="," close=")">
           #{id}
        </foreach>
    </where>
</select>

上面这个例子的作用是,查询id在ids(列表)中的博客。

相当于sql语句:

select * from blog where id IN (116012859,117374430,118058442)

完结散花

ok以上就是对 动态SQL 的全部讲解啦,很感谢你能看到这儿。如果有遗漏、错误或者有更加通俗易懂的讲解,欢迎小伙伴私信我,我后期再补充完善。

参考文献

https://blog.csdn.net/qq_33369905

举报

相关推荐

0 条评论