动态sql

作者: 桑鱼nicoo | 来源:发表于2020-03-13 14:18 被阅读0次

    if判断

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

    mapper 接口

    public interface EmployMapperDynamicSQL {
        // 携带了哪个字段查询条件就带上这个字段的值
        public List<Employee> getEmpsByConditionIf(Employee employee);
    }
    

    mapper.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">
    <!--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标签,

    <?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

    <?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结合的动态更新

    <?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决定属性值的内容

    <!--   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 批量保存

    // mapper接口定义
    public interface EmployMapperDynamicSQL {
        public void addEmps(@Param("emps") List<Employee> emps);
    }
    
    <!--批量保存 -->
    <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的批量保存

    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
    
    <!--    使用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 绑定

    <!--    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>
    

    执行测试代码

    @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();
        }
    }
    

    我的博客即将同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=3e3yxq742w2so

    相关文章

      网友评论

          本文标题:动态sql

          本文链接:https://www.haomeiwen.com/subject/nbzcjhtx.html