【MyBatis】如何使用“动态SQL”(超详解)

目录

前言

动态标签用法

一、if标签

二、where标签

三、trim标签

四、set标签

五、foreach标签

六、choose、when、otherwise标签

七、bind标签

八、include标签


前言

        MyBatis提供了10种动态SQL标签:trim、where、set、foreach、if、choose、when、otherwise、bind、include;其执行原理为,使用OGNL从SQL参数对象中计算表达式的值,根据表达式的值动态拼接SQL,以此来完成动态SQL的功能。

动态标签用法

一、if标签

        通过test属性中的表达式去判断内容是否有效,有效则将if中的sql片段拼接执行。

例如:在人员信息表,根据姓名,年龄,地址,性别等条件查询人员信息。

dao层:

    User sqlUse(@Param("name") String name, @Param("age") int age,
            @Param("address") String address, @Param("sex") String sex);

xml(注释已在代码):

操作日志:

        问题:若是上述条件都不满足会出现select * from where...的情况,亦或name条件不满足则会出现select * from where and...的语法错误,导致sql报错无法进行,那么该如何修改sql?

        解释:只需要在where语句后加上1=1的恒成立条件,并且在每个if的sql前面加上and即可;但是接下来介绍的标签是最优解。

二、where标签

        where标签特性:

  1. 只有if标签有内容的情况下才会拼接where字句;
  2. 若子句的开通为"and"或"or",where标签会将它替换去除。

        需要注意的是:where标签只会智能的去除首个满足条件语句的前缀,所以建议在使用where标签时,每个语句都最好写上 and 前缀或者 or 前缀。否则会出现以下问题:

    

        生成的sql语句如下:

select * from user WHERE name = ? age = ? sex = ?

        很明显,sql语法是有问题的,所以在使用where标签时,建议将所有条件都添加上and或or;正确的使用方法如下:

例如:在人员信息表,根据姓名,年龄,地址,性别等条件查询人员信息。

三、trim标签

        trim标签参数说明:

  1. prefix:给trim标签内sql语句加上前缀
  2. suffix:给trim标签内sql语句加上后缀
  3. prefixOverrides:去除多余的前缀内容,如:prefixOverrides=“OR”,去除trim标签内sql语句多余的前缀"OR"
  4. suffixOverrides:去除多余的后缀内容,如:suffixOverrides=",",去除trim标签内sql语句多余的后缀","

例如:在人员信息表,根据姓名,年龄,地址,性别等条件查询人员信息。

        使用prefix增加前缀(where),prefixOverrides去除多余前缀(and | or)实现查询功能

	

例如:根据人员信息表主键id,更新人员姓名、年龄、地址、性别等信息。

        使用prefix增加前缀(set),suffixOverrides去除多余后缀(,),suffix增加后缀(where id = #{id})实现更新用户信息功能

    
        update user
        
            name= #{name},
            age= #{age},
            sex= #{sex},
            address= #{address},
        
    

例如:人员信息表插入数据。

        使用prefix增加前缀((),suffixOverrides去除多余后缀(,),suffix增加后缀()),实现插入用户信息功能。


        INSERT INTO user
        
            
                id,
            
            
                name,
            
            
                age,
            
            
                sex,
            
            
                address,
            
        
        
            
                #{id},
            
            
                #{name},
            
            
                #{age},
            
            
                #{sex},
            
            
                #{address},
            
        

四、set标签

        使用set标签可以动态配置SET关键字,和剔除追加到条件末尾的任何不相关的逗号。

例如:根据人员信息表主键id,更新人员姓名、年龄、地址、性别等信息。


    update user
    
        name= #{name},
        age= #{age},
        sex= #{sex},
        address= #{address},
    
    where id = #{id}

        通过控制台日志可以发现address后面的逗号被去除!

五、foreach标签

        foreach 标签属性主要有 item,index,open,separator,close,collection。

  1. item:集合中元素迭代时的别名,该参数为必选。
  2. index:在 list 和数组中,index 是元素序号;在 map 中,index 是元素 key。该参数可选。
  3. open:foreach 代码的开始符号,一般是 ”(“,和 close=“)” 合用。常用在 in(),values() 时。该参数可选。
  4. separator:元素之间的分隔符,例如在 in() 的时候,separator=“,” 会自动在元素中间用 “,“ 隔开,避免手动输入逗号导致 SQL 错误,如 in(1, 2,) 这样。该参数可选。
  5. close:foreach 代码的关闭符号,一般是 ”)“,和 open=“(” 合用。常用在 in(),values()时。该参数可选。
  6. collection:要被 foreach 标签循环解析的对象。

        foreach 标签的 collection 属性在接受参数名时,有两种情况:

              匿名参数

                当在 java 方法中没有通过 @Param 注解指定参数名时,列表类型默认参数名为 ”list“,数组类型默认参数名为 ”array“,Map 对象没有默认值。

              具名参数

                java 方法中使用了 @Param 注解指定了参数名称,则 foreach 中的 collection 属性必须为参数名。

例如:根据主键Id集合查询所有符合的人员信息。

dao层:

	//如下两种入参均可用selectAllUser语句
    List selectAllUser(@Param("ids") List ids);
	List selectAllUser(@Param("ids") String[] ids); 

xml:

        在使用foreach批量更新、插入数据时,mybatis 会根据XML文件配置,动态生成多条 SQL。而要让 mybatis 成功执行多条语句,须开启允许批量查询设置,即在 jdbc-url 连接信息中添加 &allowMultiQueries=true,否则无法批量执行sql语句!!!如下所示。

例如:批量更新人员信息。

dao层:

int updateAllUser(List users);

xml:

	
	    
	        update user
	        
	            name= #{user.name},
	            age= #{user.age},
	            sex= #{user.sex},
	            address= #{user.address},
	        
	        where id = #{user.id}
	    
	

例如:批量插入人员信息。

dao层:

int insertAllUser(List users);

xml:

	
	  INSERT INTO user (id, name, age, address, sex) VALUES
	  
	    (#{user.id}, #{user.name}, #{user.age}, #{user.address}, #{user.sex})
	  
	

        上述传参类型都是List、数组类型,如果入参类型是Map,那么foreach又该如何处理呢?

        Map集合在foreach由于没有默认键可用,故需要使用 @Param 注解手动指定一个标识,后面将在foreach中将其作为键使用。该标识任意指定即可,这里使用"maps"

	//dao层方法
	User selectAllUserByMap(@Param("maps") Map maps);

        传入参数为集合时,映射文件的sql标签parameterType属性可省略。由于是Map集合,index、item属性分别表示为该Map集合中的key、value,故可以分别用${k},#{v}来获取该Map集合中的key、value。

    Map maps = new HashMap<>();
  	maps.put("name","萨摩耶");
	maps.put("sex","1");
	User user = animalInformationDao.selectAllUserByMap(maps);

	//xml层方法
	

操作日志如下:

六、choose、when、otherwise标签

        MyBatis 中动态语句 choose-when-otherwise 类似于 Java 中的 switch-case-default 语句。由于 MyBatis 并没有为 if 提供对应的 else 标签,如果想要达到...... 的效果,可以借助 来实现。

	//dao层
	List selectUserInfo(User user);

    //xml
	

七、bind标签

        bind标签可以从OGNL(对象图导航语言)表达式中创建一个变量并将其绑定到上下文
Mybatis中使用Mysql的模糊查询字符串拼接(like) 中也涉及到bind的使用。

	//dao层
	List findUser(@Param("name") String name);

    //xml
	

八、include标签

        include标签引用,可以复用SQL片段,sql标签中id属性对应include标签中的refid属性,通过include标签将sql片段和原sql片段进行拼接成一个完整的sql语句进行执行。

	
	    id,name,age,address,sex
	
        
	
	    user
	
        
	
	
	等同于:
	

你可能感兴趣的:(Java基础,mybatis,sql,数据库)