动态sql

2023-09-21 14:52:36 浏览数 (1)

if判断

查询时携带了哪个字段where条件就按照什么来查询

mapper 接口

代码语言:javascript复制
public interface EmployMapperDynamicSQL {
    // 携带了哪个字段查询条件就带上这个字段的值
    public List<Employee> getEmpsByConditionIf(Employee employee);
}

mapper.xml

代码语言:javascript复制
<?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">
<!--namespace:名称空间,对应mapper接口-->
<mapper namespace="com.sangyu.mapper.EmployMapperDynamicSQL">
    <!--查询员工,要求,携带了哪个字段查询条件在查询的时候就带上这个字段的值-->
    <select id="getEmpsByConditionIf" resultType="com.sangyu.bean.Employee">
        select * from tbl_employee
        where
        <if test="id!=null">
            id=#{id}
        </if>
        <if test="lastName!=null &amp;&amp; lastName!= &quot;&quot;">
            and last_name like #{lastName}
        </if>
        <if test="email != null and email.trim() != &quot;&quot;">
            and email = #{email}
        </if>
        <if test="gender==0 or gender == 1">
           and gender = #{gender}
        </if>
    </select>
</mapper>

where查询条件

前面的例子中通过if 条件增加判断where按照什么条件去查询,但是会有一个问题,当传递的参数中前面的没有值where条件 也会在前面加上and

针对上面的问题,可以查询条件中增加 where 1= 1,剩余的if判断语句中都用and

还有一种方式就是使用where标签,mybatis将所有的查询条件拼装sql,多出来的and或者or去掉(只会去掉第一个多出来的and或者or)

Trim标签

使用where条件只会去掉第一个多出来的and或者or,如果后面多出的and或者or,使用where并不能解决。mybatis提供了Trim标签,

代码语言:javascript复制
<?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">
<!--namespace:名称空间,对应mapper接口-->
<mapper namespace="com.sangyu.mapper.EmployMapperDynamicSQL">
    <!--查询员工,要求,携带了哪个字段查询条件在查询的时候就带上这个字段的值-->
    <select id="getEmpsByConditionIf" resultType="com.sangyu.bean.Employee">
        select * from tbl_employee
        -- where 1 = 1
        <!--        <where>-->
--         prefix = "" 前缀,trim标签体中是整个字符串拼串后的结果,prefix给拼串后的整个字符串加上一个前缀
--         prefixOverrides = "" 前缀覆盖,去掉整个字符串前面多余的字符
--         suffix = "" 后缀 给拼串后的整个字符串加一个后缀
--         suffixOverrides = "" 后缀覆盖 ,去掉整个字符串后多余的字符
        <trim prefix="where" suffixOverrides="and">
            <if test="id!=null">
                id=#{id} and
            </if>
            <if test="lastName!=null &amp;&amp; lastName!= &quot;&quot;">
                last_name like #{lastName} and
            </if>
            <if test="email != null and email.trim() != &quot;&quot;">
                email = #{email} and
            </if>

            <if test="gender==0 or gender == 1">
                gender = #{gender} and
            </if>
        </trim>
        <!--        </where>-->
    </select>
</mapper>

choose分支选择(when ,otherwise)

mybaits中的分支选择相当于java中的switch-case

代码语言:javascript复制
<?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">
<!--namespace:名称空间,对应mapper接口-->
<mapper namespace="com.sangyu.mapper.EmployMapperDynamicSQL">
    <select id="getEmpsByConditionChoose" resultType="com.sangyu.bean.Employee">
        select * from tbl_employee
        -- 如果带了id就用id查,如果带了lastName就用lastName查,只会进入其中一个
        -- 当所有条件都不满足的时候就输出 otherwise 中的内容
        <where>
            <choose>
                <when test="id!=null">
                    id=#{id}
                </when>
                <when test="lastName!=null">
                    last_name like #{lastName}
                </when>
                <when test="email!=null">
                    email = #{email}
                </when>
                <otherwise>
                    gender = 0
                </otherwise>
            </choose>
        </where>
    </select>
</mapper>

set和if结合的动态更新

代码语言:javascript复制
<?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">
<!--namespace:名称空间,对应mapper接口-->
<mapper namespace="com.sangyu.mapper.EmployMapperDynamicSQL">
    <select id="updateEmp">
        update tbl_employee
        <set>
            <if test="lastName!=null">
                last_name=#{lastName},
            </if>
            <if test="email != null">
                email = #{email},
            </if>
            <if test="gender!= null">
                gender = #{gender}
            </if>
            where id = #{id}
        </set>
    </select>
</mapper>

foreach 遍历集合

在foreach遍历集合时,如果集合传递的是List(就是在mapper中接口方法定义的参数类型)那么,mybatis会将List封装到map中,map的key默认是list,如果在定义方法的时候定义了@param那么key就是定义的参数名称。foreach标签中的collectin属性值根据是否定义@param决定属性值的内容

代码语言:javascript复制
<!--   collection : 执行要遍历的集合-->
    <!--   list类型的参数会特殊处理封装在map中,map的key就叫list-->
    <!--   item : 将当前遍历出的元素赋值给指定的变量-->
    <!--   separator : 每个元素之间的分隔符-->
    <!--   open : 遍历出所有结果拼接一个开始的字符-->
    <!--        遍历出所有结果拼接一个结束的字符-->
    <!--   索引,遍历list的时候index就是索引,item 就是当前值-->
    <!--        遍历map的时候index表示的就是map的key,item就是map的值-->
    <!--   #{变量名}就能取出变量的值也就是当前遍历出的元素-->
    <select id="getEmpsByConditionForeach" resultType="com.sangyu.bean.Employee">
        select * from tbl_employee
        <foreach collection="ids" item="item_id" separator=","
                 open="where id in(" close=")">
            #{item_id}
        </foreach>
    </select>

foreach 批量保存

代码语言:javascript复制
// mapper接口定义
public interface EmployMapperDynamicSQL {
    public void addEmps(@Param("emps") List<Employee> emps);
}
代码语言:javascript复制
<!--批量保存 -->
<select id="addEmps">
    insert into tbl_employee(last_name,email,gender,d_id)
    values
    <foreach collection="emps" item = "emp" separator=",">
        (#{emp.lastName},#{emp.email},#{emp.gender},#{emp.dept.id})
    </foreach>
</select>

image.png

另一种批量保存的方式

dbconfig.properties 修改数据库连接属性allowMultiQueries=true,使用Mysql的批量保存

代码语言:javascript复制
jdbc.driver = com.mysql.cj.jdbc.Driver
jdbc.url = jdbc:mysql://localhost:3306/mybatis?useUnicode=true&useSSL=false&allowMultiQueries=true
jdbc.username = root
jdbc.password = abcd123456
代码语言:javascript复制
<!--    使用Mysql的批量保存,可以foreach遍历,mysql支持value(),(),()语法-->
<select id="addEmps">
    <foreach collection="emps" item="emp" separator=";">
        insert into tbl_employee(last_name,email,gender,d_id) values
        (#{emp.lastName},#{emp.email},#{emp.gender},#{emp.dept.id})
    </foreach>
</select>

bind 绑定

代码语言:javascript复制
<!--    bind,可以将OGNL表达式的值绑定到一个变量中,方便后面引用这个变量的值,_parameter参数保存了com.sangyu.bean.Employee这个对象。
    所以可以通过OGNL表达式从_parameter参数中获取到Employee的对应属性值
    (也就是把_parameter看作了users的别名)。-->
<select id="getEmpsTestInnerParameter" resultType="com.sangyu.bean.Employee">
    <bind name="_lastName" value="'%'  lastName '%'"/>
        select * from tbl_employee
    <if test="_parameter != null">
        where last_name like #{_lastName}
  </if>
</select>

执行测试代码

代码语言:javascript复制
@Test
public void Test21() throws IOException {
    String resource = "mybatis-config.xml";
    InputStream inputStream = Resources.getResourceAsStream(resource);
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); 
    SqlSession session = sqlSessionFactory.openSession();
    try {
        EmployMapperDynamicSQL mapper = session.getMapper(EmployMapperDynamicSQL.class);
        Employee employee = new Employee();
        employee.setLastName("e");
        List<Employee> list = mapper.getEmpsTestInnerParameter(employee);
        for(Employee employee1 : list){
            System.out.println(employee1);
        }
    } finally {
        session.close();
    }
}

0 人点赞