Mybatis decomposition query

Table of contents

 

1. Mybatis one-to-many decomposition query

1. Add new persistence layer interface method

2. Add the label corresponding to the mapping file

3. New test method

4. Operation effect

Two, Mybatis one-to-one decomposition query

1. Add new persistence layer interface method

2. Add the label corresponding to the mapping file

3. New test method

4. Operation effect

3. Mybatis lazy loading

1. Enable lazy loading

2. Test lazy loading


 

1. Mybatis one-to-many decomposition query

Decomposed query is to split a Sql statement into multiple

In MyBatis multi-table query, all data can be queried with one Sql statement when using connection query. like:

# When querying the class, associate the query with the students

select *

   from classes

   left join student

   on student.classId = classes.cid

You can also use decomposed query, that is, decompose a connection Sql statement into multiple Sql statements, such as:

# When querying the class, associate the query with the students

select * from classes;

select * from student where classId = 1;

select * from student where classId = 2;

This way of writing is also called N+1 query .

Connection query :

Advantages: reduce the number of queries, thereby improving query efficiency.

Disadvantage: If the query returns a large number of result sets, it will consume memory space.

N+1 query :

Advantages: The result set is obtained step by step, saving memory space.

Disadvantages: Due to the need to execute multiple queries, it is less efficient than join queries.

Let's take the related query of students when querying classes as an example, and use N+1 query: 

1. Add new persistence layer interface method

Added ClassesMapper2.java interface

package com.example.mapper;

import com.example.pojo.Classes;

import java.util.List;

public interface ClassesMapper2 {
    List<Classes> findAll();
}

Add StudentMapper.java interface

package com.example.mapper;

import com.example.pojo.Student;

import java.util.List;

public interface StudentMapper2 {
    List<Student> findByClassId(int classId);
}

2. Add the label corresponding to the mapping file

Added ClassesMapper.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="com.example.mapper.ClassesMapper2">

    <!-- 自定义映射关系 -->
    <resultMap id="myClassesMapper" type="com.example.pojo.Classes">
        <id property="cid" column="cid"/>
        <result property="className" column="className"/>
        <!-- select: 从表查询调用的方法 column:调用方法时传入的参数字段 -->
        <collection property="studentList" column="cid"
                    ofType="com.example.pojo.Student"
                    select="com.example.mapper.StudentMapper2.findByClassId"/>
    </resultMap>

    <select id="findAll" resultMap="myClassesMapper">
        select * from classes
    </select>
</mapper>

Add StudentMapper.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="com.example.mapper.StudentMapper2">
    <select id="findByClassId"
            parameterType="int"
            resultType="com.example.pojo.Student">
        select * from student where classId = ${classId}
    </select>
</mapper>

3. New test method

// 分解式查询一对多
    @Test
    public void testFindAllClasses2(){
        ClassesMapper2 classesMapper2 = session.getMapper(ClassesMapper2.class);
        List<Classes> all = classesMapper2.findAll();
        all.forEach(System.out::println);
    }

4. Operation effect

21f461022d21441c8c2118c12f63f325.png

        Here we can see that two query statements are indeed separated

Two, Mybatis one-to-one decomposition query

When querying students, you can also use the decomposed query to associate the query to find out the class. First, separate the query statement:

select * from student;

select * from classes where cid = ?

1. Add new persistence layer interface method

Add StudentMapper3.java interface

package com.example.mapper;

import com.example.pojo.Student;

import java.util.List;

public interface StudentMapper3 {
    // 查询所有学生
    List<Student> findAll();
}

Added ClassesMapper3.java interface 

package com.example.mapper;

import com.example.pojo.Classes;

import java.util.List;

public interface ClassesMapper3 {
    // 根据ID查询班级
    Classes findById(int cid);
}

2. Add the label corresponding to the mapping file

Added ClassesMapper.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="com.example.mapper.ClassesMapper3">

    <select id="findByCid"
            resultType="com.example.pojo.Classes"
            parameterType="int">
        select * from classes where cid = ${cid}
    </select>
</mapper>

Add StudentMapper.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="com.example.mapper.StudentMapper3">
    <!-- 自定义映射关系 -->
    <resultMap id="MyClassesMapper" type="com.example.pojo.Student">
        <id property="sid" column="sid"/>
        <result property="name" column="name"/>
        <result property="age" column="age"/>
        <result property="sex" column="sex"/>
        <!-- select: 从表查询调用的方法 column:调用方法时传入的参数字段 -->
        <association property="classes" column="classId"
                     javaType="com.example.pojo.Classes"
                     select="com.example.mapper.ClassesMapper3.findByCid"/>
    </resultMap>

    <select id="findAll" resultMap="MyClassesMapper">
        select * from student
    </select>
</mapper>

3. New test method

// 分解式查询一对一
    @Test
    public void testFindAllStudent2(){
        StudentMapper3 studentMapper3 = session.getMapper(StudentMapper3.class);
        List<Student> all = studentMapper3.findAll();
        all.forEach(System.out::println);
    }

4. Operation effect

be0f6c85b53b4864be3233ba71999376.png

OK, indeed the query came out. 

3. Mybatis lazy loading

Decomposed queries are further divided into two loading methods:

        Immediate loading: Execute all Sql statements when querying the main table.

        Lazy loading: also known as lazy loading, the query statement of the main table is executed first, and the query statement of the secondary table is triggered only when the data of the secondary table is used.

Lazy loading is slower when fetching associated data, but it saves resources and fetches it as it is used.

1. Enable lazy loading

Set all N+1 queries as lazy loading, add the following settings in the Mybatis configuration file:

    <settings>
        <setting name="lazyLoadingEnabled" value="true"/>
        <setting name="lazyLoadTriggerMethods" value=""/>
    </settings>

Set a method as lazy loading:

Add the fetchType attribute in <association> and <collection> to set the loading method.

lazy: lazy loading; eager: immediate loading.

2. Test lazy loading

         Since the toString method of the object will be called when printing the object, the toString method will trigger the query of lazy loading by default, so we cannot test the effect of lazy loading.

        We set the lazyLoadTriggerMethods attribute in the configuration file. This attribute specifies what method of the object triggers lazy loading, and it can be set to an empty string.  

Test Methods: 

    @Test
    public void testFindAllClasses2(){
        ClassesMapper2 classesMapper2 = session.getMapper(ClassesMapper2.class);
        List<Classes> all = classesMapper2.findAll();
        all.forEach(System.out::println);
        System.out.println("---------------------");
        System.out.println(all.get(0).getStudentList());
    }

operation result:

3ae8eee4b71447f1b1fdd93a06907185.png

        OK, this is obvious, that is, the student list was not queried in the first query, and the query will be uploaded when the subsequent query is needed.     

        In general, lazy loading is used for one-to-many queries, and immediate loading is used for one-to-many queries.

 

Guess you like

Origin blog.csdn.net/qq_53317005/article/details/129634685