java代码中组装where条件然后拼接到mybatis xml中的sql后面

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java代码中组装where条件然后拼接到mybatis xml中的sql后面相关的知识,希望对你有一定的参考价值。

现在有数据权限需求,需要动态的组装where条件sql,然后拼接到mybatis配置的sql后面。
例如:用户A角色为admin,角色admin具有表TB1中类型为A++的操作权限,现在A要访问TB1,我应当如何把 <类型=“A++”> 的条件动态的拼接到mybatis中的查询语句中去。
在java中组装条件然后拼接到mybatis语句中,不能写死在xml中。

参考技术A 这个应该先在java中把条件确定,然后把条件作为参数传进去
比如 where 1=1 and $condition
不过要考虑sql注入
参考技术B 可以啊,用if控制就行了。 现在遇到了什么困难追问

其实就是做数据权限,我计划提出一个工具类,后台在做数据访问的时候,必须先调用工具类,根据配置的用户数据权限,动态的拼接出一个条件语句,然后将条件语句拼接到已经准备好的mybagtis sql的后面,从而做到限制用户的数据访问权限。并不是传统的跟条件,这个条件是可配置的,有可能是这个条件也可能是别的,想要写死语句然后依靠做不可能吧

MyBatis学习笔记 —— 动态SQL

10、动态SQL

MyBatis框架的动态SQL技术是一种根据特定条件动态拼装SQL语句的功能,它存在的意义是为了解决拼接SQL语句字符串的痛点问题。

动态SQL:

1、if 标签:通过test属性中的表达式判断标签中的内容是否有效(是否会拼接到sql中)

2、where 标签:

​ a.若where标签中有条件成立,会自动生成where关键字

​ b.会自动将where标签中内容前多余的and去掉,但是其中内容后多余的and无法去掉

​ c.若where标签中没有任何一个条件成立,则where没有任何功能

3、trim 标签

​ prefix、suffix: 在标签中内容前面或后面添加指定内容

​ prefixOverrides、suffixOverrides: 在标签中内容前面或后面去掉指定内容

4、choose、when、otherwise

​ 相当于java中的if…else if…else

5、foreach 标签

collection: 设置要循环的数据或集合

item: 用一个字符串表示数组或集合中的每一个数据

separator: 设置每次循环的数据之间的分隔符

open: 循环的所有内容以什么开始

close: 循环的所有内容以什么结束

6、可以记录一段sql,在需要用的地方使用include标签进行引用。

10.1、if 标签

if标签可通过test属性的表达式进行判断,判断标签中的内容是否有效(是否会拼接到sql中),若表达式的结果为true,这标签中的内容会执行;反之标签中的内容不会执行

Emp.java

package com.fan.mybatis.pojo;

/**
 * @Date: 2023/03/01
 * @Author: fan
 * @Description:
 */
public class Emp 
    private Integer empId;

    private String empName;

    private Integer age;

    private String gender;

    public Emp() 
    

    public Emp(Integer empId, String empName, Integer age, String gender) 
        this.empId = empId;
        this.empName = empName;
        this.age = age;
        this.gender = gender;
    

    public Integer getEmpId() 
        return empId;
    

    public void setEmpId(Integer empId) 
        this.empId = empId;
    

    public String getEmpName() 
        return empName;
    

    public void setEmpName(String empName) 
        this.empName = empName;
    

    public Integer getAge() 
        return age;
    

    public void setAge(Integer age) 
        this.age = age;
    

    public String getGender() 
        return gender;
    

    public void setGender(String gender) 
        this.gender = gender;
    

    @Override
    public String toString() 
        return "Emp" +
                "empId=" + empId +
                ", empName='" + empName + '\\'' +
                ", age=" + age +
                ", gender='" + gender + '\\'' +
                '';
    

DynamicSQLMapper.java

package com.fan.mybatis.mapper;

import com.fan.mybatis.pojo.Emp;

import java.util.List;

/**
 * @Date: 2023/03/01
 * @Author: fan
 * @Description:
 */
public interface DynamicSQLMapper 

    /**
     * 根据条件查询员工信息
     * @param emp
     * @return
     */
    List<Emp> getEmpByCondition(Emp emp);

DynamicSQLMapper.xml

<?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.fan.mybatis.mapper.DynamicSQLMapper">

  <select id="getEmpByCondition" resultType="Emp">
    select * from t_emp where
    <if test="empName !=null and empName != ''">
      emp_name = #empName
    </if>
    <if test="age != null and age != ''">
      and age = #age
    </if>
    <if test="gender != null and gender != ''">
      and gender = #gender
    </if>
  </select>
</mapper>

DynamicSQLMapperTest.java

package com.fan.mybatis.test;

import com.fan.mybatis.mapper.DynamicSQLMapper;
import com.fan.mybatis.pojo.Emp;
import com.fan.mybatis.utils.SqlSessionUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.util.List;

public class DynamicMapperTest 

    @Test
    public void testGetEmpByCondition()
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        DynamicSQLMapper mapper = sqlSession.getMapper(DynamicSQLMapper.class);
        Emp emp = new Emp(null,"张三",23,"男");
        List<Emp> list = mapper.getEmpByCondition(emp);
        list.forEach(System.out::println);
    

运行测试:

10.2、where 标签

where和if一般结合使用:

a>若where标签中的if条件都不满足,则where标签没有任何功能,即不会添加where关键字

b>若where标签中的if条件满足,则where标签会自动添加where关键字,并将条件最前方多余的

and去掉

注意:where标签不能去掉条件最后多余的and

where标签主要是解决多条件查询拼接的问题。

@Test
public void testGetEmpByCondition()
    SqlSession sqlSession = SqlSessionUtils.getSqlSession();
    DynamicSQLMapper mapper = sqlSession.getMapper(DynamicSQLMapper.class);
    Emp emp = new Emp(null,"",null,"");
    List<Emp> list = mapper.getEmpByCondition(emp);
    list.forEach(System.out::println);

第一种方式:添加恒成立的条件 1=1

<?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.fan.mybatis.mapper.DynamicSQLMapper">

  <select id="getEmpByCondition" resultType="Emp">
    select * from t_emp where 1=1
    <if test="empName !=null and empName != ''">
      and emp_name = #empName
    </if>
    <if test="age != null and age != ''">
      and age = #age
    </if>
    <if test="gender != null and gender != ''">
      and gender = #gender
    </if>
  </select>
</mapper>

第二种方式:where标签选择动态生成where关键字

<select id="getEmpByCondition" resultType="Emp">
  select * from t_emp
  <where>
    <if test="empName !=null and empName != ''">
      emp_name = #empName
    </if>
    <if test="age != null and age != ''">
      and age = #age
    </if>
    <if test="gender != null and gender != ''">
      and gender = #gender
    </if>
  </where>
</select>

10.3、trim 标签

trim用于去掉或添加标签中的内容

常用属性:

prefix:在trim标签中的内容的前面添加某些内容

prefixOverrides:在trim标签中的内容的前面去掉某些内容

suffix:在trim标签中的内容的后面添加某些内容

suffixOverrides:在trim标签中的内容的后面去掉某些内容

<select id="getEmpByCondition" resultType="Emp">
  select * from t_emp
  <trim prefix="where" suffixOverrides="and">
    <if test="empName !=null and empName != ''">
      emp_name = #empName
    </if>
    <if test="age != null and age != ''">
      and age = #age
    </if>
    <if test="gender != null and gender != ''">
      and gender = #gender
    </if>
  </trim>
</select>

运行测试:

10.4、choose、when、otherwise 标签

choose、when、otherwise

相当于java中的if…else if…else

when 至少设置一个,otherwise最多设置一个

/**
* 使用choose查询员工信息
* @param emp
* @return
*/
List<Emp> getEmpByChoose(Emp emp);
<select id="getEmpByChoose" resultType="Emp">
  select * from t_emp
  <where>
    <choose>
      <when test="empName != null and empName != ''">
        emp_name = #empName
      </when>
      <when test="age != null and age != ''">
        age = #age
      </when>
      <when test="gender != null and gender != ''">
        gender = #gender
      </when>
    </choose>
  </where>
</select>

10.5、foreach 标签

foreach标签

collection: 设置要循环的数据或集合

item: 用一个字符串表示数组或集合中的每一个数据

separator: 设置每次循环的数据之间的分隔符

open: 循环的所有内容以什么开始

close: 循环的所有内容以什么结束

10.5.1、批量添加

DynamicSQLMapper.java

/**
* 批量添加员工信息
* @param emps
*/
void insertMoreEmp(@Param("emps") List<Emp> emps);

DynamicSQLMapper.xml

<insert id="insertMoreEmp">
  insert into t_emp values
  <foreach collection="emps" item="emp" separator=",">
    (null,#emp.empName,#emp.age,#emp.gender,null)
  </foreach>
</insert>

DynamicSQLMapperTest.java

@Test
public void testInsertMoreEmp()
    SqlSession sqlSession = SqlSessionUtils.getSqlSession();
    DynamicSQLMapper mapper = sqlSession.getMapper(DynamicSQLMapper.class);
    Emp emp1 = new Emp(null,"小明1",20,"男");
    Emp emp2 = new Emp(null,"小明2",20,"男");
    Emp emp3 = new Emp(null,"小明3",20,"男");
    List<Emp> list = Arrays.asList(emp1,emp2,emp3);
    mapper.insertMoreEmp(list);

运行测试,控制台输出结果如下:

查看数据库可以看到批量添加了3条数据

10.5.2、批量删除

DynamicSQLMapper.java

/**
* 批量删除
* @param empIds
*/
void deleteMoreEmp(@Param("empIds") Integer[] empIds);

DynamicSQLMapper.xml

批量删除的第一种写法:

<delete id="deleteMoreEmp">
  delete from t_emp where emp_id in
  (
  <foreach collection="empIds" item="empId" separator=",">
    #empId
  </foreach>
  )
</delete>

批量删除的第二种写法:

<delete id="deleteMoreEmp">
  delete from t_emp where emp_id in
  <foreach collection="empIds" item="empId" separator="," open="(" close=")">
    #empId
  </foreach>
</delete>

批量删除的第三种写法:

<delete id="deleteMoreEmp">
  delete from t_emp where
  <foreach collection="empIds" item="empId" separator="or">
    emp_id = #empId
  </foreach>
</delete>

DynamicSQLMapperTest.java

@Test
public void testDeleteMoreEmp() 
    SqlSession sqlSession = SqlSessionUtils.getSqlSession();
    DynamicSQLMapper mapper = sqlSession.getMapper(DynamicSQLMapper.class);
    Integer[] empIds = new Integer[]6,7;
    mapper.deleteMoreEmp(empIds);

运行测试,控制台输出如下

从数据库中可以看到批量删除了2条数据。

10.6、sql 标签

可以记录一段sql,在需要用的地方使用include标签进行引用。

<sql id="empColumns">
  emp_id,emp_name,age
</sql>

<select id="getEmpByCondition" resultType="Emp">
  select <include refid="empColumns"></include> from t_emp
  <trim prefix="where" suffixOverrides="and">
    <if test="empName !=null and empName != ''">
      emp_name = #empName
    </if>
    <if test="age != null and age != ''">
      and age = #age
    </if>
    <if test="gender != null and gender != ''">
      and gender = #gender
    </if>
  </trim>
</select>

以上是关于java代码中组装where条件然后拼接到mybatis xml中的sql后面的主要内容,如果未能解决你的问题,请参考以下文章

关于sql语句添加where条件问题,用java语句

Dapper 封装03-组装SQL-多条件

Lambda表达式动态组装查询条件

数据库多行拼接到一行Oracle和sqlServer

MyBatis学习笔记 —— 动态SQL

Java如何实现多选项搜索功能(查询数据库)?