java--MyBatis dynamic SQL

MyBatis Dynamic SQL

One of the powerful features of MyBatis is its dynamic SQL. If you have experience with JDBC or other similar frameworks, you can appreciate how painful it is to concatenate SQL statements based on different conditions. When splicing, make sure not to forget the necessary spaces, and also pay attention to omitting the comma at the end of the column name list. Using the feature of dynamic SQL can completely get rid of this pain.
Usually using dynamic SQL cannot be a standalone part, MyBatis certainly improves this situation by using a powerful dynamic SQL language which can be used in any SQL mapped statement.
Dynamic SQL elements are similar to using JSTL or other similar XML-based text processors. In previous versions of MyBatis, there were many elements to understand. MyBatis 3 greatly improves them, and now uses less than half the original elements. MyBatis uses powerful OGNL-based expressions to eliminate other elements.


  • if
  • choose (when, otherwise)
  • trim (where, set)
  • foreach


if

What dynamic SQL usually does is conditionally include part of a where clause.

<select id="findStudentNameById" parameterType="int" resultType="StudentInfo">
        select * from student
        <where>
            <trim suffix="" suffixOverrides="and">
                <if test="classId!=null">
                    classId=#{
    
    classId}
                </if>
                <if test="studentName!=null and studentName!=''">
                   and studentName like concat(concat('%',#{
    
    studentName}),'%')
                </if>
            </trim>
        </where>
    </select>
  • suffix:在trim标签内sql语句加上后缀
  • prefix:在trim标签内sql语句加上前缀
  • suffixOverrides:指定去除多余的后缀内容
  • prefixOverrides:指定去除多余的前缀内容

For example: suffixOverrides="and", remove the redundant suffix "and" of the sql statement in the trim tag



choose, when, otherwise

Sometimes, we don't want to use all conditional statements, but just choose one or two. For this situation, MyBatis provides the choose element, which is a bit like the switch statement in Java.


    <select id="findStudentByChoose" resultType="studentInfo">
        select * from student where 1=1
        <choose>
            <when test="studentName!=null and studentName!=''">
                and studentName like concat(concat('%',#{
    
    studentName}),'%')
            </when>
            <when test="studentAge!=0">
                and studentAge>#{
    
    studentName}
            </when>
            <otherwise>
                and classId=#{
    
    classId}
            </otherwise>
        </choose>
    </select>
  • choose标签是按顺序判断其内部when标签中的test条件出否成立,如果有一个成立,则 choose 结束。当 choose 中所有 when 的条件都不满则时,则执行 otherwise 中的sql。类似于Java 的 switch 语句,choose 为 switch,when 为 case,otherwise 则为 default。


trim, where, set

The where element knows to insert the "WHERE" clause only if more than one if condition is true. Also, if the last content starts with "AND" or "OR", the where element also knows how to remove them.
A similar solution for dynamic update statements is called set. The set element can be used to dynamically include the columns that need to be updated and leave others out.


    <update id="update" parameterType="StudentInfo">
        update student
        <trim suffix="where studentId=#{studentId}" suffixOverrides=",">
            <set>
                <if test="studentName!=null">studentName=#{
    
    studentName},</if>
                <if test="studentSex!=null">studentSex=#{
    
    studentSex},</if>
                <if test="studentAddress!=null">studentAddress=#{
    
    studentAddress},</if>
                <if test="studentAge!=null">studentAge=#{
    
    studentAge},</if>
                <if test="classId!=null">classId=#{
    
    classId},</if>
            </set>
        </trim>
    </update>
  • trim标签一般用于去除sql语句中多余的and关键字,逗号,或者给sql语句前拼接 “where“、“set“以及“values(“ 等前缀,或者添加“)“等后缀,可用于选择性插入、更新、删除或者条件查询等操作。


foreach

Another common necessary operation of dynamic SQL is to traverse a collection, usually when building IN conditional statements.

    <select id="findStudentByMap" resultType="StudentInfo">
        select * from student where studentName like concat(concat('%',#{
    
    studentName}),'%') and classId in
        <foreach collection="list" item="map" open="(" separator="," close=")">
            #{
    
    map}
        </foreach>
    </select>

The most critical and most error-prone thing when using foreach is the collection attribute. This attribute must be specified, but in different situations, the value of this attribute is different. There are mainly three situations:

  • 如果传入的是单参数且参数类型是一个List的时候,collection属性值为list 。
  • 如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array 。
  • 如果传入的参数是多个的时候,我们就需要把它们封装成一个Map了,当然单参数也可以封装成map,实际上如果你在传入参数的时候,在MyBatis里面也是会把它封装成一个Map的,map的key就是参数名,所以这个时候collection属性值就是传入的List或array对象在自己封装的map里面的key。


for example:

mapper method:

public List<StudentInfo> findStudentByMap(Map<String,Object> map);

xml mapping file:

<?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">
<mapper namespace="cn.zbw.mapper.StudentInfoMapper">
    <select id="findStudentByMap" resultType="StudentInfo">
        select * from student where studentName like concat(concat('%',#{
    
    studentName}),'%') and classId in
        <foreach collection="list" item="map" open="(" separator="," close=")">
            #{
    
    map}
        </foreach>
    </select>

test class:

package cn.zbw.test;

import cn.zbw.entity.StudentInfo;
import cn.zbw.mapper.StudentInfoMapper;
import cn.zbw.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class Test07 {
    
    
    public static void main(String[] args) {
    
    
        test07();
    }

    private static void test07() {
    
    
        SqlSession session = MybatisUtils.getSession();
        HashMap<String, Object> map = new HashMap<>();
        List list = new ArrayList();
        list.add(2);
        map.put("studentName","冰");
        map.put("list",list);
        List<StudentInfo> stuList = session.getMapper(StudentInfoMapper.class).findStudentByMap(map);
        for (StudentInfo stu : stuList) {
    
    
            System.out.println(stu.getStudentName()+"\t"+stu.getStudentAddress());

        }
    }
}

search result:
insert image description here

Guess you like

Origin blog.csdn.net/weixin_45686583/article/details/114879420