Mybatis framework -----> (6) Deep understanding of Mybatis dynamic SQL statements

One, dynamic SQL statement

  • What is a dynamic SQL statement:

Judge the conditions through the <if>, <where >, <foreach> tags provided by mybatis to realize dynamic splicing of SQL statements. It is mainly used to solve the situation of uncertain query conditions. It will query according to the query conditions submitted by the user. The main reason is that the back part of the SQL statement where keyword has changed.

  • Precautions:

If symbols such as greater than (>), less than (<), greater than or equal to (>=), less than or equal to (<=) appear in the dynamic SQL in the mapping file, it is best to convert them into entity symbols. Otherwise, XML may have parsing errors.
Focus :Especially for the less than sign (<), it must not appear in the XML file. Otherwise, an error will occur when parsing the mapping file

  • Entity symbol table:
< Less than &lt;
> more than the &gt;
>= greater or equal to &gt;=
<= Less than or equal to &lt;=
  • The following describes these types of tags:

(1) <if> tag

Syntax format:
<if test="判断java对象的属性值">
    部分sql语句
</if>
  • Define methods in the interface
List<Student> selectStudentIf(Student student);
  • Mapping file
<select id="selectStudentIf" resultType="Student">
    <include refid="studentSql"/>
    where 
    <if test="name!=null and name!=''">
        name=#{name}
    </if>
    <if test="age>0">
        or age>#{age}
    </if>
</select>

SQL statement code snippets are defined here to facilitate future calls and avoid code redundancy

Use steps:
1. First define <sql id="custom name unique"> sql statement, table name, field, etc.< /sql>
2. Use it again, <include refid="value of id" />

<sql id="studentSql" >
    select id,name,age,email from student
</sql>
  • Define the test method
@Test
public void testSelectStudenIf(){
    
    
    SqlSession sqlSession = MyBatisUtil.getSqlSession();
    StudentDao dao = sqlSession.getMapper(StudentDao.class);
    Student student = new Student();
    student.setName("李四");
    student.setAge(20);
    List<Student> studentList = dao.selectStudentIf(student);

    for (Student student1:studentList){
    
    
        System.out.println("学生if="+student1);
    }
}

For example, comment out the code name in the test method :

Student student = new Student();
//student.setName("李四");
student.setAge(20);
List<Student> studentList = dao.selectStudentIf(student);

Then the executed SQL statement will be wrong:

SQL:select id,name,age,email from student where or age>?

Defect :
When the following if statement is not satisfied or not satisfied, the SQL statement will be spliced ​​into
select id,name,age,email from student where or age>?
select id,name,age,email from student where
this SQL statement, which is obviously wrong

Tip :
You can add a satisfying condition (true clause) after where , for example: where id>0
so that the SQL statement becomes an executable statement.
select id,name,age,email from student where id>0 or age>?
But when the amount of data is large, it will seriously affect the query efficiency.

The improved mapping file is:

<select id="selectStudentIf" resultType="Student">
    <include refid="studentSql"/>
    where id>0
    <if test="name!=null and name!=''">
       and  name=#{name}
    </if>
    <if test="age>0">
        or age>#{age}
    </if>
</select>

Inside the where keyword is added a true clause id>0 and added before the name "and"
so that the execution of the SQL statement becomes:
SQL:select id,name,age,email from student where id>0 or age>?

(2) <where> tag

Syntax format:
<where> 
	其他动态 sql 
</where>
<where >: Solve the small defects caused by the <if> tag

<where> is used to contain multiple <if>
1. When multiple ifs are established, a WHERE keyword is automatically added to <where>
2. When the following if conditions are not established, you can remove the redundant and in if , Or etc.
3. When the following if conditions are not met, the WHERE keyword will also be removed

  • Define methods in the interface
List<Student> selectStudentWhere(Student student);
  • Mapping file
<select id="selectStudentWhere" resultType="Student">
    <include refid="studentSql"></include>
    <where>
        <if test="name!=null and name!=''">
            name=#{name}
        </if>
        <if test="age>0">
            or age>#{age}
        </if>
    </where>
</select>
  • Define the test method
@Test
public void testSelectStudenWhere(){
    
    
    SqlSession sqlSession = MyBatisUtil.getSqlSession();
    StudentDao dao = sqlSession.getMapper(StudentDao.class);

    Student student = new Student();
    //student.setName("李四");
    student.setAge(20);
    List<Student> studentList = dao.selectStudentWhere(student);

    for (Student student1:studentList){
    
    
        System.out.println("学生where="+student1);
    }
}

(3) <foreach> tag

Syntax format:
<foreach collection="" open="" close="" item="" separator=""> 
	#{item 的值} 
</foreach> 

The <foreach> tag is used to realize the traversal of arrays and collections, mainly used in the in statement of the sql statement

1. Splicing out SQL statements without tags here

For example: query student id is 1001,1002,1003

select * from student where id in (1001,1002,1003)

Here defines a test method to splice the above SQL statement

@Test
public void testfor(){
    
    
    List<Integer> list=new ArrayList<>();
    list.add(1001);
    list.add(1002);
    list.add(1003);
    //String sql = "select * from student where id in(1001,1002,1003);
    String sql ="select * from student where id in";
    StringBuilder builder = new StringBuilder(sql);
    int init=0;
    int len=list.size();
    //添加开始的(
    builder.append("(");
    for (Integer i:list){
    
    
        builder.append(i).append(",");
    }
    //将最后一个逗号删除
    builder.deleteCharAt(builder.length()-1);
    //循环结束
    builder.append(")");
    sql = builder.toString();
    System.out.println("sql=="+sql);
}

Obviously the above code is very long and smelly , let’s make improvements...

2. Splicing SQL statements through the <foreach> tag

Usage 1: Traverse List<simple type>

  • Define methods in the interface
List<Student> selectStudentForeachOne(List<Integer> list);
  • Mapping file
<select id="selectStudentForeachOne" resultType="Student">
    <include refid="studentSql"/> where id in
    <foreach collection="list" item="myid" open="(" close=")" separator=",">
        #{myid}
    </foreach>
</select>

Analyze the attributes in the tag :
1. collection: indicates the type of method parameters in the interface,
if it is an array, use array, if it is a list collection, use list
2. item: a custom variable that represents array and collection members, equivalent to Integer The i variable in i
for (Integer i:list){ builder.append(i).append(",");}3. open: the character at the beginning of the loop "("4. close: the character at the end of the loop" )"5. Separator: Separator between set members ","




  • Define the test method
@Test
public void testSelectStudenForeachOne(){
    
    
    SqlSession sqlSession = MyBatisUtil.getSqlSession();
    StudentDao dao = sqlSession.getMapper(StudentDao.class);
    List<Integer> list=new ArrayList<>();
    list.add(1001);
    list.add(1002);
    list.add(1003);
    List<Student> studentList = dao.selectStudentForeachOne(list);
    for (Student student1:studentList){
    
    
        System.out.println("学生foreachone="+student1);
    }
}

Usage 2: Traverse List<object type>

  • Define methods in the interface
List<Student> selectStudentForeachTwo(List<Student> studentlist);
  • Mapping file
<select id="selectStudentForeachTwo" resultType="Student">
    <include refid="studentSql"/> where id in (
    <foreach collection="list" item="stu" separator=",">
        #{stu.id}
    </foreach>
    )
</select>

Note : The value stu of item here is just the corresponding Java object

  • Define the test method
@Test
public void testSelectStudenForeachTwo(){
    
    
    SqlSession sqlSession = MyBatisUtil.getSqlSession();
    StudentDao dao = sqlSession.getMapper(StudentDao.class);

    List<Student> stulist=new ArrayList<>();
    Student s1 = new Student();
    s1.setId(1001);
    stulist.add(s1);

    Student s2 = new Student();
    s2.setId(1002);
    stulist.add(s2);

    List<Student> studentList = dao.selectStudentForeachTwo(stulist);

    for (Student student1:studentList){
    
    
        System.out.println("学生foreachtwo="+student1);
    }
}

2. Thinking outline

Insert picture description here

Please correct me if there are any deficiencies!

Guess you like

Origin blog.csdn.net/hcz666/article/details/113132501