前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >动态sql

动态sql

作者头像
桑鱼
修改2023-09-21 14:52:36
7430
修改2023-09-21 14:52:36
举报

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();
    }
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • if判断
  • where查询条件
  • Trim标签
  • choose分支选择(when ,otherwise)
  • set和if结合的动态更新
  • foreach 遍历集合
  • foreach 批量保存
  • bind 绑定
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档