动态Sql

我们都可以从一些网站上看到这样的进行查询的方式:

在进行查询的时候,可以对每一个字段进行单选或者多选,作为程序员的我们可以知道,每一次进行查询的时候都需要一个SQL语句对应,但是对于我们上面的这种大规模的查询,条件众多,如果对每一个查询都对应一个SQL语句的话,代码量是很庞大的。而且如果上面的条件进行变更,项目的维护难度是十分大的。

所以Mybatis有一种动态SQL技术,可以把SQL语句通过条件选择,一条语句能够对应很多种的查询,极大地提高了效率。


动态Sql

动态SQL有以上四种标签供我们使用。

If

添加mapper接口中方法:

List<Emp> query(Emp emp);

mapper配置文件SQL语句:

使用方法看注释:

<select id="query" parameterType="Emp" resultMap="useResultMap" >
            <!-- 下面这里是介绍if的使用方式
                if的作用就是判断这个字段是否为空,来进行多条件动态查询,如果有这个条件就加上,如果这个条件为空就不带
                这里设计的方法就是 利用 1 = 1 来保证这次查询不用考虑最后那个where的问题,如果后面一个条件都不满足
                那么多出一个where,查询语句就会报错,然后后面让每一个条件成为一个单独模块
                就可以进行多个条件用一个语句就可以查询出来。
                这里不仅可以用and,对or同样适用-->
            select e_id,e_name,e_age,e_birthday,e_salary from emp where 1 = 1
            <if test="name != null">
                and e_name = #{name}
            </if>
            <if test="age != null">
                and e_age = #{age}
            </if>
        </select>

service实现类

    @Override
    public List<Emp> query(Emp emp) {
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
        List<Emp> list = mapper.query(emp);
        return list;
    }

 测试1:

    @Test
    public void testQuery(){
        EmpService service = new EmpServiceImpl();

        Emp emp = new Emp();
        emp.setName("佐助");
        emp.setAge(13);
        List<Emp> list = service.query(emp);
        for(Emp e : list){
            System.out.println(e);
        }
    }

测试2:

@Test
    public void testQuery(){
        EmpService service = new EmpServiceImpl();

        Emp emp = new Emp();
        emp.setName("佐助");
        //emp.setAge(13);
        List<Emp> list = service.query(emp);
        for(Emp e : list){
            System.out.println(e);
        }
    }

测试3

@Test
    public void testQuery(){
        EmpService service = new EmpServiceImpl();

        Emp emp = new Emp();
        //emp.setName("佐助");
        //emp.setAge(13);
        List<Emp> list = service.query(emp);
        for(Emp e : list){
            System.out.println(e);
        }
    }


choose, when, otherwise

我们一定碰到过这样的需求,比如像文章顶部的房子信息,如果什么信息都不传入,那么就会查询所有,那么数据库中所有的数据都会查询出来,这样会造成很大的数据传输,对服务器有着很大的压力,不如如果什么信息都不传入的话,那么就展示一个特定的条件下的内容。

这个标签类似于JSP中的C标签,原理类似于连续的if else 语句。进行连续判断。

只需修改上面例子中的查询语句:

<select id="query" parameterType="Emp" resultMap="useResultMap" >
            <!-- where后面的 1=1 还是除去没有条件的时候消除where的影响
             这里没有条件的时候会默认使用后面的条件,也消除了后面and的影响-->
            select e_id,e_name,e_age,e_birthday,e_salary from emp where 1 = 1
            <!-- 这里三个标签配置使用,choose在外层,包裹住所有条件
                里面的when标签可以设置多个.
                就像是一个接一个if{}
                            else if{}
                            else if{}
                            else{}
              第一个when标签是我们的第一个if,后面的每一个when都相当于是else if
              最后的otherwise就相当于我们最后一个else{}
              -->
            <choose>

                <when test=" age != null and name !=null">
                    and e_age = #{age} and e_name = #{name}
                </when>
                <when test=" name != null">
                    and e_name = #{name}
                </when>
                <when test=" age != null">
                    and e_age = #{age}
                </when>
                <otherwise>
                    and e_age = 13 and e_name = '小樱'
                </otherwise>
            </choose>
        </select>

测试1:

@Test
    public void testQuery(){
        EmpService service = new EmpServiceImpl();
        Emp emp = new Emp();
        emp.setName("佐助");
        emp.setAge(13);
        List<Emp> list = service.query(emp);
        for(Emp e : list){
            System.out.println(e);
        }
    }

把年龄输入注释掉,进行测试:

两个都注释掉:

 


trim, where, set

这三个标签作用类似,where在SQL语句需要使用where时使用,set标签是针对update操作时使用,trim是一个公共的方法,既可以实现where的功能,也可以实现set的功能。

我们首先从where进行介绍:

我们在前面使用where进行查询的时候,为了避免and和where关键字的影响,一直使用一个1=1来规避影响,但是这种做法是不太好的。

我们的数据库进行存储的时候,每一列的相同的值会进行整合,只存储一个相同的值,然后这个相同的值后面后存储所有等于这个值的数据的地址,进行查询的时候,会根据查询的条件,针对第一个条件做一个二分查找,然后找到后面跟的所有满足这个条件的数据的地址,然后再在所有满足第一个条件的数据里进行第二个数据的查找,如果有第三个条件以此类推,如果到最后没有条件了,会把后面跟的所有数据进行返回,这样会提高查询的效率,但是我们前面有一个1=1,就会从数据库里进行一个一个的查找,降低了我们查找的效率,所以需要把这个给规避掉。这里就需要使用where标签。

修改上面的查询的SQL语句:

<select id="query" parameterType="Emp" resultMap="useResultMap" >
            select e_id,e_name,e_age,e_birthday,e_salary from emp
            <where>
                <if test="name != null">
                    and e_name = #{name}
                </if>
                <if test="age != null">
                    and e_age = #{age}
                </if>
            </where>
        </select>

where的作用是:

1.当where后面跟的条件都不为空的时候,会在语句拼接上where关键字

2.加入where后面跟的条件不为空的时候,后面第一个不为空的语句是以and或者or开头的,会把这个and或者or省略掉。

set

Sql语句:

<update id="updateEmp">
            update emp
            <set>
                <if test="name != null">
                    e_name = #{name},
                </if>
                <if test="age != null">
                    e_age = #{age},
                </if>
                <if test="birthday != null">
                    e_birthday = #{birthday},
                </if>
                <if test="salary != null">
                    e_salary = #{salary},
                </if>
            </set>
             where e_id = #{id}
        </update>

测试1:

    @Test
    public void testUpdateEmp(){
        Emp emp = new Emp(15,"佐助",13,new Date(),new BigDecimal(1000));
        EmpService service = new EmpServiceImpl();
        service.updateEmp(emp);
    }

测试2:

    @Test
    public void testUpdateEmp(){
        Emp emp = new Emp(17,"佐助",13,null,new BigDecimal(1000));
        EmpService service = new EmpServiceImpl();
        service.updateEmp(emp);
    }

set的作用是:

1.加入set标签中的语句不为空的时候,那么会拼接set关键字

2.如果里面的标签最后一个修改条件是逗号结尾的话,那么这个会被删除

trim

在trim标签有四个属性,作用分别是:

prefix:前缀,在返回的字符串之前添加什么内容

suffix:后缀,在返回的字符串之后添加什么内容

prefixOverrides:当字符串以其中什么内容开头的时候,该内容会被覆盖

suffixOberirdes:当字符串以其中什么内容结尾的时候,该内容会被覆盖

利用这四个特性,就可以完成where和set标签的功能:

替换where标签:

<select id="query" parameterType="Emp" resultMap="useResultMap" >
            select e_id,e_name,e_age,e_birthday,e_salary from emp
            <trim prefix="where" prefixOverrides="and||or">
                <if test="name != null">
                    and e_name = #{name}
                </if>
                <if test="age != null">
                    and e_age = #{age}
                </if>
            </trim>
        </select>

替换set标签:

<update id="updateEmp">
            update emp
            <trim prefix="set" suffixOverrides=",">
                <if test="name != null">
                    e_name = #{name},
                </if>
                <if test="age != null">
                    e_age = #{age},
                </if>
                <if test="birthday != null">
                    e_birthday = #{birthday},
                </if>
                <if test="salary != null">
                    e_salary = #{salary},
                </if>
            </trim>
             where e_id = #{id}
        </update>

foreach

我们之前的查询或者其他使用where关键字进行条件判断的时候,都是使用的单个条件,如果我们想要查询id值为1,3,4,5,19这些数据的时候,我们还是需要在SQL语句中使用in关键字,但是使用in关键字的时候,后面跟的一个括号,里面是各个条件值,我们该如果实现这个动态的查询呢,而动态SQL里面的foreach标签,就可以完成这个功能。

foreach的功能大部分都是配合in关键字来实现的,而in可以跟在任何使用where的环境下,为了更好的演示,这里使用一个批量删除的功能。

在数据中括号内的信息都是要单独写出来的,那么我们传入的一系列数据该怎么去传入呢,程序员一般都会用一个数据或者一个list来存储这些数据。

在mapper接口和service接口中写一个方法:

void deleteBatch(Integer[] ids);

编写SQL语句:

当接口中方法的参数是数组或者集合的时候,Mybatis会自动把参数封装到一个map集合中,这个元素的key值为参数类型,首字母小写

比如数组为array,集合为list,map的为map。

foreach一共有五个标签。功能分别为:

collection:取出封装到map中的key值,就是我们上面介绍的参数类型名

open:表示拼接的字符串是以什么开始

close:表示拼接的字符串是以什么结束

item:给集合中的每一个元素起的别名,和下面#{}中的参数名对应,比如这里是用id值,所以就起名为id,见名知义

separator;集合中元素的分隔符,比如这里是用逗号分隔,所以就用逗号

<delete id="deleteBatch">
        delete from emp where e_id in
        <foreach collection="array" open="(" close=")" item="id" separator=",">
            #{id}
        </foreach>
    </delete>

service实现类实现方法:

    @Override
    public void deleteBatch(Integer[] ids) {
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
        mapper.deleteBatch(ids);
        sqlSession.commit();
        sqlSession.close();
    }

测试:

    @Test
    public void testdeleteBatch(){
        Integer[] ids = {15,17,18,19};
        EmpService service = new EmpServiceImpl();
        service.deleteBatch(ids);
    }

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值