详解Mybatis之动态sql问题(上)

简介: 详解Mybatis之动态sql问题(上)

编译软件:IntelliJ IDEA 2019.2.4 x64

操作系统:win10 x64 位 家庭版

Maven版本:apache-maven-3.6.3

Mybatis版本:3.5.6


一. 在sql映射文件中如何写注释?

关于XXXMapper接口对应的映射文件里SQL中的注释

👉语法

①方式一

//mysql的注释  
-- 1=1

②方式二

//xml的注释
<!-- 1=1  -->

使用这两种注释方式各有什么不同呢?

👉请看如下测试

代码示例如下:

①使用第一种注释

<!--  根据查询条件查找对应的员工信息(条件不确定) 即采用动态的sql去查询  -->
    <select id="selectEmpByopr" resultType="employee">
        SELECT
            `id`,
            `last_name`,
            `email`,
            `salary`,
            `dept_id`
        FROM
            `tbl_employee`
        WHERE
            -- 1=1
            <if test="id !=null">
               and id=#{id}
            </if>
            <if test="lastName != null">
               and last_name=#{lastName}
            </if>
            <if test="email != null">
                and email=#{email}
            </if>
            <if test="salary != null">
                and last_name=#{salary}
            </if>
    </select>

②使用第二种注释

<!--  根据查询条件查找对应的员工信息(条件不确定) 即采用动态的sql去查询  -->
    <select id="selectEmpByopr" resultType="employee">
        SELECT
            `id`,
            `last_name`,
            `email`,
            `salary`,
            `dept_id`
        FROM
            `tbl_employee`
        WHERE
<!--             1=1-->
            <if test="id !=null">
               and id=#{id}
            </if>
            <if test="lastName != null">
               and last_name=#{lastName}
            </if>
            <if test="email != null">
                and email=#{email}
            </if>
            <if test="salary != null">
                and last_name=#{salary}
            </if>
    </select>

💡结论

通过以上二者运行测试结果对比,所以在需要使用注释时,推荐使用第二种注释方式


二. 什么是动态sql?

👉定义

  1. 动态sql指的是sql语句可动态化
  2. Mybatis的动态sql中支持OGNL表达式语言,OGNL(Object Graph Navigation
    Language)是对象图导航语言

❗注意

👉用法案例

不指定查询条件,查询对应员工信息,即当你传入id,程序就根据id去查,传入什么条件,就去根据此条件去查(多个条件不确定)

代码示例如下

①在EmployeeMapper接口下书写相应的方法

//动态的sql方式,即不指定查询条件,查询对应员工信息
public List<Employee> selectEmpByopr(Employee employee);

②在EmployeeMapper接口相应的sql

<!--  根据查询条件查找对应的员工信息(条件不确定) 即采用动态的sql去查询  -->
    <select id="selectEmpByopr" resultType="employee">
        SELECT
            `id`,
            `last_name`,
            `email`,
            `salary`,
            `dept_id`
        FROM
            `tbl_employee`
        WHERE
            <if test="id !=null">
               and id=#{id}
            </if>
            <if test="lastName != null">
               and last_name=#{lastName}
            </if>
            <if test="email != null">
                and email=#{email}
            </if>
            <if test="salary != null">
                and last_name=#{salary}
            </if>
    </select>

③测试

@Test
public void test01(){
    try {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //通过SqlSessionFactory对象调用openSession();
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //获取EmployeeMapper的代理对象
        EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
        //动态参数(无参会报错,没有第一个参数也会报错)
        Employee employee=new Employee();
        List<Employee> employees = employeeMapper.selectEmpByopr(employee);
        //遍历集合employees
        for (Employee employee1 : employees) {
            System.out.println(employee1);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

❓但是这样会出现一个问题,即不传参会报错,没有第一个参数也会报错

💡原因分析

不传参时,mybatis解析sql的过程中走到where的部分,无参,会进入where里,但不会执行里面的任意if判断,where后没有任何赋值表达式,此sql为非法sql,故报错。没有第一个参数时也会报类似的问题。

👉解决方案

①在第二步中的where里加上 1=1,作为条件恒等式(老版本的解决措施)

②使用where标签

代码示例如下:

<!--  根据查询条件查找对应的员工信息(条件不确定) 即采用动态的sql去查询  -->
    <select id="selectEmpByopr" resultType="employee">
        SELECT
            `id`,
            `last_name`,
            `email`,
            `salary`,
            `dept_id`
        FROM
            `tbl_employee`
         <where>
            <if test="id !=null">
               and id=#{id}
            </if>
            <if test="lastName != null">
               and last_name=#{lastName}
            </if>
            <if test="email != null">
                and email=#{email}
            </if>
            <if test="salary != null">
                and last_name=#{salary}
            </if>
         </where>
    </select>


三. 动态sql常用标签有哪些?

3.1 if标签

👉功能

用于完成简单的判断

示例代码如下:

//如果属性id不为空,就将传入的参数id赋值给sql中的字段id
 <if test="id !=null">
      id=#{id}
 </if>

3.2 where标签

👉功能:

用于解决where关键字及where后第一个and或or的问题

示例代码如下:

<where>
   <if test="id !=null">
      and id=#{id}
   </if>
   <if test="lastName != null">
      and last_name=#{lastName}
   </if>
   <if test="email != null">
       and email=#{email}
   </if>
   <if test="salary != null">
       and last_name=#{salary}
   </if>
</where>

3.3 trim标签

👉功能

可以在条件判断完的SQL语句前后添加或者去掉指定的字符

👉属性

  • prefix添加前缀
  • prefixOverrides去掉前缀
  • suffix添加后缀
  • suffixOverrides去掉后缀

👉用法案例

不指定查询条件,查询对应员工信息(trim标签优化版)

代码示例如下:

①在EmployeeMapper接口定义相应的方法

//不指定查询条件,查询对应员工信息
public List<Employee> selectEmpByEmpTrim(Employee employee);

②在EmployeeMapper接口对应的映射文件中定义相应的sql

<!--  根据查询条件查找对应的员工信息(条件不确定) 动态的sql(trim标签优化版)  -->
<select id="selectEmpByEmpTrim" resultType="employee">
    SELECT
        `id`,
        `last_name`,
        `email`,
        `salary`,
        `dept_id`
    FROM
        `tbl_employee`
    <!--  给下面的sql语句加上前缀 where,去掉后缀and      -->
    <trim prefix="where" suffixOverrides="and">
        <if test="id !=null">
            id=#{id} and
        </if>
        <if test="lastName != null">
           last_name=#{lastName}  and
        </if>
        <if test="email != null">
            email=#{email}  and
        </if>
        <if test="salary != null">
            salary=#{salary}   and
        </if>
    </trim>
</select>

③测试

@Test
    public void test02(){
        try {
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            //通过SqlSessionFactory对象调用openSession();
            SqlSession sqlSession = sqlSessionFactory.openSession();
            //获取EmployeeMapper的代理对象
            EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
            //动态参数
            Employee employee=new Employee();
          /*  employee.setLastName("jack");
            employee.setSalary(5600.0);
*/
            List<Employee> employees = employeeMapper.selectEmpByEmpTrim(employee);
            //遍历集合employees
            for (Employee employee1 : employees) {
                System.out.println(employee1);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

trim标签运行流程详解

相关文章
|
4天前
|
SQL Java 测试技术
3、Mybatis-Plus 自定义sql语句
这篇文章介绍了如何在Mybatis-Plus框架中使用自定义SQL语句进行数据库操作。内容包括文档结构、编写mapper文件、mapper.xml文件的解释说明、在mapper接口中定义方法、在mapper.xml文件中实现接口方法的SQL语句,以及如何在单元测试中测试自定义的SQL语句,并展示了测试结果。
3、Mybatis-Plus 自定义sql语句
|
23天前
|
SQL Java 数据库连接
idea中配置mybatis 映射文件模版及 mybatis plus 自定义sql
idea中配置mybatis 映射文件模版及 mybatis plus 自定义sql
38 3
|
1月前
|
SQL Java 数据库连接
mybatis动态SQL常用语法总结
MyBatis 使用 OGNL 表达式语言处理动态SQL,如 `if` 标签进行条件判断,`choose`、`when`、`otherwise` 实现多条件选择,`where`、`set` 管理SQL关键字,`trim` 提供通用修剪功能,`foreach` 遍历集合数据。`sql` 和 `include` 用于代码重用,`selectKey` 处理插入后的返回值。参数传递支持匿名、具名、列表、Map、Java Bean和JSON方式。注意SQL转义及使用合适的jdbcType映射Java类型。
50 7
|
2月前
|
SQL Java 数据库连接
深入探索MyBatis Dynamic SQL:发展、原理与应用
深入探索MyBatis Dynamic SQL:发展、原理与应用
|
2月前
|
SQL 缓存 Java
Java框架之MyBatis 07-动态SQL-缓存机制-逆向工程-分页插件
Java框架之MyBatis 07-动态SQL-缓存机制-逆向工程-分页插件
|
2月前
|
SQL Java 数据库连接
MyBatis动态SQL
MyBatis动态SQL
35 0
|
2月前
|
SQL Java 数据库连接
Mybatis日志SQL解析
Mybatis日志SQL解析
31 0
|
27天前
|
SQL 存储 监控
SQL Server的并行实施如何优化?
【7月更文挑战第23天】SQL Server的并行实施如何优化?
45 13