Mybatis study notes 12 nested query

We have learned before that in relational queries, our approach is to find out the data after the table is joined, and map them separately.

    <resultMap id="Department_Employee" type="Department">
        <id column="id" property="id"></id>
        <result column="name" property="name"></result>
        <result column="location" property="location"></result>
        
        <collection property="employees" ofType="Employee">
            <id column="emp_id" property="id"></id>
            <result column="emp_name" property="name"></result>
            <result column="salary" property="salary"></result>
        </collection>
    </resultMap>
    <select id="queryDepartmentById" resultMap="Department_Employee">
        select t_departments.id,t_departments.name,t_departments.location,
        t_employees.id as emp_id,t_employees.name as emp_name,t_employees.salary
        from t_departments join t_employees
        on t_departments.id = t_employees.dept_id
        where t_departments.id = #{id}
    </select>

The nested query is that in the related query, we no longer query once and redefine the encapsulation rules, but divide the query into two and encapsulate them separately.

Take the query department and all its employee information as an example:

1. We simplify the query method mapping of the department, so that it is only responsible for filling in the basic information of the department

<select id="queryDepartmentById" resultMap="Department_Employee">
        select id,name,location
        from t_departments
        where id = #{id}
    </select>

2. We added a method to query employee information based on department ID in the employee's DAO

List<Employee> queryEmployeesByDeptId(@Param("deptId") Integer deptId);

3. Define the SQL corresponding to mapper.xml

    <select id="queryEmployeesByDeptId" resultType="Employee">
        select id,name,salary
        from t_employees
        where dept_id = #{deptId}
    </select>

4. Call this method in the mapper.xml corresponding to the department DAO

    <resultMap id="Department_Employee" type="Department">
        <id column="id" property="id"></id>
        <result column="name" property="name"></result>
        <result column="location" property="location"></result>
        
        <collection property="employees" ofType="Employee"
                    select="com.zt.DAO.EmployeeDAO.queryEmployeesByDeptId"
                    column="id"/>
    </resultMap>

The execution process is: first execute queryDepartmentById, and perform basic encapsulation according to the rules of resultMap, and the result of the internal collection needs to be obtained by calling a method queryEmployeesByDeptId. The passed parameter is the id currently detected, that is, the id defined in the mapping rule. It also has its own mapper definition, so I did two queries to get the results.

5. Writing tests

    public static void main(String[] args) {
        DepartmentDAO mapper = MybatisUtil.getMapper(DepartmentDAO.class);
        Department department = mapper.queryDepartmentById(1);
        System.out.println(department);
        List<Employee> employees = department.getEmployees();
        for (Employee employee : employees) {
            System.out.println(employee);
        }
    }

You can see that two SQL statements are executed. The advantage of doing so is that it will not cause an excessively large intermediate result due to the table connection. If we have m pieces of data in table A and n pieces of data in table B, then m*n pieces of data will be generated after the connection, and then be modified on the basis of it. In doing so, we can now query on Table A once, and then use the results to query Table B again, that is, there will be no intermediate results, and the number of queries has been reduced from m*n to m+n.

Learn from one analogy: now we turn to write and check employees and check the department by the way

EmployeeMapper.xml:

    <resultMap id="Empolyee_Department" type="Employee">
        <id column="id" property="id"></id>
        <result column="name" property="name"></result>
        <result column="salary" property="salary"></result>
        <association property="department" javaType="Department"
                     select="com.zt.DAO.DepartmentDAO.queryDepartmentById"
                     column="dept_id"/>
    </resultMap>
    <select id="queryEmployeeById" resultMap="Empolyee_Department">
        select id,name,salary,dept_id
        from t_employees
        where id = #{id}
    </select>

Write the test:

    public static void main(String[] args) {
        EmployeeDAO mapper = MybatisUtil.getMapper(EmployeeDAO.class);
        Employee employee = mapper.queryEmployeeById(1);
        System.out.println(employee);
        Department department = employee.getDepartment();
        System.out.println(department);
    }

It is worth noting that because DepartmentDAO itself is a method of querying based on ID, we directly bound him to the method of querying employees based on ID, and we previously bound the method of querying a group of employees based on ID. Method, so three SQLs will be executed here.

Lazy loading: Although such binding can simplify SQL and facilitate query operations, this nested query is automatically triggered. Sometimes we don’t need to check the information. Mybatis provides the option of lazy loading. If we don’t use those Cascading data will not trigger nested queries, which is beneficial to improve speed and save memory.

1. Set in the main configuration file

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

2. Experiment

A. The investigation department does not use employee data

    public static void main(String[] args) {
        DepartmentDAO mapper = MybatisUtil.getMapper(DepartmentDAO.class);
        Department department = mapper.queryDepartmentById(1);
        System.out.println(department.getId());
        /*List<Employee> employees = department.getEmployees();
        for (Employee employee : employees) {
            System.out.println(employee);
        }*/
    }

[There is a big pit here]: If we directly print the detected department object, it will actually trigger a nested query, but the employees attribute is not used in the toString() method overwritten by our department. This may That is, Mybatis uses the class directly by default, so the data of the class must be complete, so the division query:

    @Override
    public String toString() {
        return "Department{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", location='" + location + '\'' +
                '}';
    }

B. Check the department's use of employee data

    public static void main(String[] args) {
        DepartmentDAO mapper = MybatisUtil.getMapper(DepartmentDAO.class);
        Department department = mapper.queryDepartmentById(1);
        System.out.println(department.getId());
        List<Employee> employees = department.getEmployees();
        for (Employee employee : employees) {
            System.out.println(employee);
        }
    }

Guess you like

Origin blog.csdn.net/qq_39304630/article/details/112307959