第七个Mybatis程序-动态SQL

动态sql就是根据不同的条件生成不同的sql语句
但是为什么要使用它?原因很简单,当我们百度的时候,输入一个人名,可能会出现多个人,但是如果知道他的演员,我们在输入的人名后面加上演员,就可以直接搜索到,不需要再去筛选。
实际在这里就使用了动态SQL,当我们只输入人名的时候,sql语句可能是

select * from table where name=#{name}

如果再加入演员的话,sql语句可能变成

select * from table where name=#{name} and job=#{actor}

在这里,我们的sql语句都使用了动态拼接。

name=#{name} 
name=#{name} and job=#{job}

在Mybatis中,动态SQL已经成为了它最强大的特性之一,而Mybatis3中采用了功能强大的OGNL表达式来完成动态sql

简单了解OGNL表达式:
对象导航图语言(Object Graph Navigation Language),简称OGNL,是应用于Java中的一个开源的表达式语言(Expression Language),它被集成在Struts2等框架中,作用是对数据进行访问,它拥有类型转换、访问对象方法、操作集合对象等功能。

知识点主要如下:(每个元素都有<>包裹,csdn打不出来)

  • if:判断语句,用于单条件分支判断
  • choose(when、otherwise):用于多条件分支判断
  • where、trim、set:辅助元素,用于处理SQL拼接、特殊字段问题
  • foreach:循环语句,常用于in语句等列举条件中
  • bind:从OGNL表达式中创建一个变量,且绑定到上下文,常用于模糊查询的SQL中

一、if

在Mybatis中,if元素是常用的判断语句,主要用于实现简单的条件选择。在实际应用中,我们可能通过多个条件来精确地查询某个数据。

如何使用:

1、搭建一个数据库
在这里插入图片描述

2、搭建配置文件

<!--加入日志工厂设置-->
	<settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>

3、编写工具类
4、创建实体类

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Book {
    private int id;
    private String name;
    private double price;
    private int bookCount;
    private String author;
}

5、创建dao接口

public interface BookMapper {
    //if查询
    List<Book> query(Book book);
    //choose查询
    List<Book> query2(Book book);
    //where+if
    List<Book> query3(Book book);
    //where+trim
    List<Book> query4(Book book);
    //update
    int set(Book book);
    //foreach遍历
    List<Book> query5(List list);
    //bind
    List<Book> query6(Book book);
}

实现接口

<select id="query" parameterType="book" resultType="book">
        select *
        from mydatabase.book 
        where 1=1
        <if test="name!=null and name!=''">
            and name=#{name}<!--也可以加入like %name%模糊查询-->
        </if>
        <if test="price!=null and price!=''">
            and price=#{price}
        </if>
        <if test="bookCount!=null and bookCount!=''">
            and bookCount=#{bookCount}
        </if>
        <if test="author!=null and author!=''">
            and author=#{author}
        </if>
    </select>

6、注册Mapper

	<mappers>
        <mapper class="com.dao.BookMapper"/>
    </mappers>

7、测试
在这里插入图片描述
通过实体类的set方法,去传入我们要查询的值,这样可以精确查找
在这里插入图片描述

二、choose、when、otherwise

为什么使用它们?

在使用if元素时,只要test属性中的表达式为true,就会执行元素中的条件语句,但是在实际应用当中,有时只需要从多个选项中选择一个执行。
例如:

  • 如果name不为空,则值根据name进行筛选;
  • 如果name为空,price不为空,则只根据price进行筛选;
  • 如果name和price和其他的属性字段都为空,则要求查询出所有的信息!
<!--choose-->
    <select id="query2" resultType="book" parameterType="book">
        select *
        from mydatabase.book
        where 1=1
        <choose>
            <when test="name!=null and name!=''">
                and name like concat('%',#{name},'%')
            </when>
            <when test="price!=null and price!=''">
                and price=#{price}
            </when>
            <when test="author!=null and author!=''">
                and author like  concat('%',#{author},'%')
            </when>
            <otherwise>
                and bookCount is not null
            </otherwise>
        </choose>
	</select>

测试:

@Test
    public void test2(){
        BookMapper mapper = MybatisUtil.getSqlSession().getMapper(BookMapper.class);
        Book book = new Book();
        book.setAuthor("白");
        for (Book book1 : mapper.query2(book)) {
            System.out.println(book1);
        }
    }

在这里插入图片描述

@Test
    public void test2(){
        BookMapper mapper = MybatisUtil.getSqlSession().getMapper(BookMapper.class);
        Book book = new Book();
        book.setAuthor("白");
        book.setName("无");
        for (Book book1 : mapper.query2(book)) {
            System.out.println(book1);
        }
    }

结果:
在这里插入图片描述
可以观察得出,choose是选择其中的一个sql字段去查询,而不是像if元素一样,只要在set中传入了值,就将传入值的if元素中的sql字段全部拼接在一起,达到精确查询。
在上述代码中,使用了choose元素进行sql拼接,
如果第一个when元素中的条件为真,则只动态拼接第一个when元素内的sql片段,否则继续向下判断。
如果前面所有when元素中的条件都不为真,则只拼接otherwise元素内的sql片段。

三、where、trim

前面的查询中,映射文件中编写的sql后面都加入了1=1的条件判断语句,是为了保证当条件不成立时拼接起来的sql语句在执行时不报错,即 使得sql不出现语法错误。
那么在Mybatis中,有没有办法不用加入1=1这样的条件呢?针对这种情况,Mybatis中提供了where元素

1、where+if

<!--where+if-->
    <select id="query3" parameterType="book" resultType="book">
        select *
        from mydatabase.book
        <where>
            <if test="name!=null and name!=''">
                and name=#{name}
            </if>
            <if test="author!=null and author!=''">
                and author=#{author}
            </if>
        </where>
    </select>
@Test
    public void test3(){
        BookMapper mapper = MybatisUtil.getSqlSession().getMapper(BookMapper.class);
        Book book = new Book();
        book.setName("无题");
        book.setAuthor("李白");
        for (Book book1 : mapper.query3(book)) {
            System.out.println(book1);
        }
    }

结果:
在这里插入图片描述

2、where+trim(重点)

<trim prefix="str1" prefixOverrides="str2"/> 

trim中的prefix="str1"表示,语句的前缀,它会在拼接的时候,str1自动加到if中的sql语句前面
prefixOverrides="str2"表示,去除语句的等于str2的特殊字符串,在拼接的sql语句的时候,将str2去除。
这个元素,一般是用来定制查询的作用!

<!--where+trim-->
    <select id="query4" resultType="book" parameterType="book">
        select *
        from mydatabase.book
        <where>
            <trim prefix="where" prefixOverrides="and"/>
            <if test="name!=null and name!=''">
                and name=#{name}
            </if>
            <if test="author!=null and author!=''">
                and author=#{author}
            </if>
        </where>
    </select>
@Test
    public void test4(){
        BookMapper mapper = MybatisUtil.getSqlSession().getMapper(BookMapper.class);
        Book book = new Book();
        book.setName("无题");
        book.setAuthor("李白");
        for (Book book1 : mapper.query4(book)) {
            System.out.println(book1);
        }
    }

结果:
在这里插入图片描述
1=1,where+if,where+trim的查询结果均相同,什么时候该用什么,全看自己的选择了,一般用where+trim比较好,它可以定制sql语句,但是1=1一般比较简单,全看自己的取舍了。

四、set

一般,我们在数据库的操作中,总是需要更改一些信息,Mybatis给我们提供了set元素,可以动态的拼接更新信息的操作

foreach:

  • item:循环中当前的元素
  • index:当前元素在集合中的位置下标
  • collection:可以是一个array、list、collection、map集合的键、pojo包装类中的数组或集合类型的属性名
  • open和close:以什么符号将这些元素包装起来
  • separator:各个元素的间隔符
	<update id="set" parameterType="book">
        update mydatabase.book
        <set>
            <if test="name!=null and name!=''">
                name=#{name},
            </if>
            <if test="price!=null and price!=''">
                price=#{price},
            </if>
            <if test="bookCount!=null and bookCount!=''">
                bookCount=#{bookCount},
            </if>
            <if test="author!=null and author!=''">
                author=#{author},
            </if>
        </set>
        where id=#{id}
    </update>
@Test
    public void test5(){
        BookMapper mapper = MybatisUtil.getSqlSession().getMapper(BookMapper.class);
        Book book = new Book();
        book.setAuthor("张若虚");
        book.setName("春江花月夜");
        book.setId(2);
        mapper.set(book);
        for (Book book1 : mapper.query(new Book())) {
            System.out.println(book1);
        }
    }

结果:
在这里插入图片描述
Mybatis中的set元素,主要作用是动态的包含sql语句前输出一个set关键字,并且将sql语句中的最后一个多余的逗号去除!
在编写sql语句的时候,记得在所有的sql语句后面加入逗号’,’,如果不加会报错
而且在传入值的时候,不能都为空,如果全为空,也会报错。

五、foreach

foreach元素一般用来遍历数组和集合,假设有上千条数据,我们可以可以用foreach全部查询出来

<!--foreach-->
    <select id="query5" parameterType="list" resultType="book">
        select * from mydatabase.book where id in
        <foreach collection="list" index="index" item="id" open="(" separator="," close=")">
            #{id}
        </foreach>
    </select>
@Test
    public void test6(){
        BookMapper mapper = MybatisUtil.getSqlSession().getMapper(BookMapper.class);
        ArrayList<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        for (Book book : mapper.query5(list)) {
            System.out.println(book);
        }
    }

结果:在这里插入图片描述

注意:

collection属性:

  • 如果传入的是单参数且参数类型是一个数组或者List的时候,collection属性值分别为array、list(或collection)
  • 如果传入的参数有多个,就需要把它们封装成一个Map,单参数也可以封装成Map集合,这是collection的属性值就为Map的键
  • 如果传入的参数是pojo包装类,collection属性值就为该包装类中需要遍历的数组或集合的属性名

六、bind(了解即可)

在进行模糊查询的时候
如果使用${}进行字符串拼接,则无法防止sql注入问题
如果使用concat函数进行拼接,则只针对mysql数据库有效,对别的数据库无效。
映射文件中的sql就要根据不同的情况提供不同形式的实现,显然是不可能的,非常的麻烦,且不利于项目的移植。
所以,Mybatis提供了bind元素来解决这个问题,完全不需要使用数据库语言,只要使用Mybatis的语言即可与所需参数连接!

<!--bind-->
    <select id="query6" resultType="book" parameterType="book">
        <bind name="_name" value="'%'+name+'%'"/>
        select *
        from mydatabase.book
        where name like #{_name}
    </select>
 @Test
    public void test7(){
        BookMapper mapper = MybatisUtil.getSqlSession().getMapper(BookMapper.class);
        Book book = new Book();
        book.setName("春");
        for (Book book1 : mapper.query6(book)) {
            System.out.println(book1);
        }
    }

结果:
在这里插入图片描述
bind实际就是运用了一个ref(引用),将sql语段拼接进去

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MyBatis 目录(?)[-] mybatis实战教程mybatis in action之一开发环境搭建 mybatis实战教程mybatis in action之二以接口的方式编程 mybatis实战教程mybatis in action之三实现数据的增删改查 mybatis实战教程mybatis in action之四实现关联数据的查询 mybatis实战教程mybatis in action之五与spring3集成附源码 mybatis实战教程mybatis in action之六与Spring MVC 的集成 mybatis实战教程mybatis in action之七实现mybatis分页源码下载 mybatis实战教程mybatis in action之八mybatis 动态sql语句 mybatis实战教程mybatis in action之九mybatis 代码生成工具的使用 mybatis SqlSessionDaoSupport的使用附代码下载 转自:http://www.yihaomen.com/article/java/302.htm (读者注:其实这个应该叫做很基础的入门一下下,如果你看过Hibernate了那这个就非常的简单) (再加一条,其实大家可以看官方的教程更好些:http://mybatis.github.io/mybatis-3/,而且如果英文不是很好的那就看中文的:http://mybatis.github.io/mybatis-3/zh/sqlmap-xml.html) 写在这个系列前面的话: 以前曾经用过ibatis,这是mybatis的前身,当时在做项目时,感觉很不错,比hibernate灵活。性能也比hibernate好。而且也比较轻量级,因为当时在项目中,没来的及做很很多笔记。后来项目结束了,我也没写总结文档。已经过去好久了。但最近突然又对这个ORM 工具感兴趣。因为接下来自己的项目中很有可能采用这个ORM工具。所以在此重新温习了一下 mybatis, 因此就有了这个系列的 mybatis 教程. 什么是mybatis MyBatis是支持普通SQL查询,存储过程和高级映射的优秀持久层框架。MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索。MyBatis使用简单的XML或注解用于配置和原始映射,将接口和Java的POJOs(Plan Old Java Objects,普通的Java对象)映射成数据库中的记录. orm工具的基本思想 无论是用过的hibernate,mybatis,你都可以法相他们有一个共同点: 1. 从配置文件(通常是XML配置文件中)得到 sessionfactory. 2. 由sessionfactory 产生 session 3. 在session 中完成对数据的增删改查和事务提交等. 4. 在用完之后关闭session 。 5. 在java 对象和 数据库之间有做mapping 的配置文件,也通常是xml 文件。 mybatis实战教程(mybatis in action)之一:开发环境搭建 mybatis 的开发环境搭建,选择: eclipse j2ee 版本,mysql 5.1 ,jdk 1.7,mybatis3.2.0.jar包。这些软件工具均可以到各自的官方网站上下载。 首先建立一个名字为 MyBaits 的 dynamic web project 1. 现阶段,你可以直接建立java 工程,但一般都是开发web项目,这个系列教程最后也是web的,所以一开始就建立web工程。 2. 将 mybatis-3.2.0-SNAPSHOT.jar,mysql-connector-java-5.1.22-bin.jar 拷贝到 web工程的lib目录. 3. 创建mysql 测试数据库和用户表,注意,这里采用的是 utf-8 编码 创建用户表,并插入一条测试数据 程序代码 程序代码 Create TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `userName` varchar(50) DEFAULT NULL, `userAge` int(11) DEFAULT NULL, `userAddress` varchar(200) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; Insert INTO `user` VALUES ('1', 'summer', '100', 'shanghai,pudong'

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值