The Role of MyBatis's resultMap and the Torture of xml Configuration

Original Blog: http://blog.csdn.net/iaiti/article/details/53227880
Simple construction.

MyBatis Actual Warfare, the predecessor of iBatis, Basic Environment Building and How to "Fish" this article describes the basic environment building and code operation.

I use the method of xml and interface to operate. Existing Employee classes. If it's a simple select, you can see the following simple example.

Employee.Java

public class Employee {//Omitting get set method  
    private int id;  
    private String first_name;  
    private String last_name;  
    private int salary;  
}  

EmployeeMapper.java

package com.mybatis3.mappers;  

import model.Employee;  

public interface EmployeeMapper  
{  
    Employee findEmployeeById(Integer a);  
}  

EmployeeMapper. XML (and EmployeeMapper.java are in the same package)

<?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.mybatis3.mappers.EmployeeMapper">    
  <select id="findEmployeeById" resultType="model.Employee">    
    select * from Employee where id = #{abc} <! -- Later, we found that it doesn't matter what we fill in here for this parameter name. It can be mapped to -->.  
  </select>    
</mapper>    

The mappers mapping of mybatis-config.xml is changed to:

<mapper class="com.mybatis3.mappers.EmployeeMapper" />  

Query operation.

public class Factory {    
    public static void main(String[] args) {    
        String configxml = "mybatis-config.xml";    
        InputStream is = null;    
        try {    
            is = Resources.getResourceAsStream(configxml);    
        } catch (IOException e) {    
            e.printStackTrace();    
        }    
        SqlSessionFactory sf = new SqlSessionFactoryBuilder().build(is);    
        SqlSession s = sf.openSession();    
        EmployeeMapper employeeMapper =  s.getMapper(EmployeeMapper.class);  
        Employee e =  employeeMapper.findEmployeeById(47);  
        System.out.println(e.getFirst_name());    
        System.out.println(e.getLast_name());    
        System.out.println(e.getSalary());   
        s.close();    
    }    
}    

This is the time for single-form queries, and then the problem arises. If it is a multi-table complex query. Now you have a new table Employer. If you were the architect of the framework, would you leave all Employee fields in Employer? Obviously, it's not appropriate.

This is how MyBatis provides resultmap. Let's first look at how a single class can also be mapped using resultmap.

Employer class

public class Employer {  
    private int id;//Omitting set get method  
    private int employee_id;  
    private String name;  
    private Employee em;  
}  

EmployerMapper.xml

<?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.mybatis3.mappers.EmployerMapper">  
    <resultMap id="Employer" type="model.Employer">  
        <id property="id" column="id" />  <!-- id Amount to resultmap Unique Identification of References-->  
        <result property="name" column="name" />  <!-- property Corresponding javabean The property name of the column Corresponding database field name -->  
        <result property="employee_id" column="employee_id" />  
    </resultMap>  

    <select id="findEmployeeById" resultMap="Employer">  
        select * from Employer where id = #{abc}  
    </select>  
</mapper>  

Test:

public class Factory {    
    public static void main(String[] args) {    
        String configxml = "mybatis-config.xml";    
        InputStream is = null;    
        try {    
            is = Resources.getResourceAsStream(configxml);    
        } catch (IOException e) {    
            e.printStackTrace();    
        }    
        SqlSessionFactory sf = new SqlSessionFactoryBuilder().build(is);    
        SqlSession s = sf.openSession();    
        EmployerMapper employerMapper =  s.getMapper(EmployerMapper.class);  
        Employer e2 =  employerMapper.findEmployeeById(1);  
        System.out.println(e2.getEmployee_id());  
        System.out.println(e2.getName());  
        s.close();    
    }    
}    

The id,result attribute of the toss resultMap:

Then it began to toss and turn. Change EmployerMapper.xml to the following:

<resultMap id="Employer" type="model.Employer">  
</resultMap>  

<select id="findEmployeeById" resultMap="Employer">  
    select * from Employer where id = #{abc}  
</select>  

Find that it can still map normally. But if you change an attribute of javabean:

private int employeeid;  
public int getEmployeeid() {  
    return employeeid;  
}  
public void setEmployeeid(int employee_id) {  
    this.employeeid = employee_id;  
}  

In this way, the final value is not available, because the mapping is not possible. Is that the attribute name or the name mapping through the getset method? Re-tossing:

private int employeeid;  
public int getEmployee_id() {  
    return employeeid;  
}  
public void setEmployee_id(int employee_id) {  
    this.employeeid = employee_id;  
}  

The employeeid attribute name does not correspond to the database field name, but the get, set method name corresponds to the database field name. The operation is normal.

If you don't want to mess around with configuration, keeping JavaBean field names and database field names are the best choices.

Toss resultMap extends attributes, table associated queries.

Employer.xml

<?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.mybatis3.mappers.EmployerMapper">  
    <resultMap id="Employer" type="model.Employer">  
    </resultMap>  
    <resultMap type="model.Employer" id="EmployerWithEmployee"  
        extends="Employer">  
        <result property="em.id" column="id" />  
        <result property="em.first_name" column="first_name" />  
        <result property="em.last_name" column="last_name" />  
        <result property="em.salary" column="salary" />  
    </resultMap>  
    <select id="findEmployeeById2" resultMap="EmployerWithEmployee">  
        select employee_id,name,b.first_name,b.salary,b.last_name from Employer a  
        left join Employee b on a.employee_id=b.id where a.id = #{abc}  
    </select>  
</mapper>  

Test:

SqlSessionFactory sf = new SqlSessionFactoryBuilder().build(is);    
SqlSession s = sf.openSession();    
EmployerMapper employerMapper =  s.getMapper(EmployerMapper.class);  
Employer e2 =  employerMapper.findEmployeeById2(1);  
System.out.println(e2.getEmployee_id());  
System.out.println(e2.getName());  
System.out.println(e2.getEm().getFirst_name());  
System.out.println(e2.getEm().getLast_name());  

Note that this em is no longer the same as the first toss above, but is consistent with the method name. This time it's the same as the attribute name. Otherwise you will make a mistake.

And MyBatis's Association query is as simple as that. It's the same association statement, with only a few mapping configurations added.

Torture association

Extensions expansion looks good, but when it comes to decoupling, your extends come out as a nondescript thing. I own Employee.

So, association s appear.

<mapper namespace="com.mybatis3.mappers.EmployerMapper">  
    <resultMap id="Employee" type="model.Employee">  
        <id property="id" column="id" />  
        <result property="first_name" column="first_name" />  
        <result property="last_name" column="last_name" />  
        <result property="salary" column="salary" />  
    </resultMap>  

    <resultMap id="Employer" type="model.Employer">  
        <id property="id" column="id" />  <!-- id Amount to resultmap Unique Identification of References-->  
        <result property="name" column="name" />  <!-- property Corresponding javabean The property name of the column Corresponding database field name -->  
        <result property="employee_id" column="employee_id" />  
        <association property="em" resultMap="Employee" />  
    </resultMap>  
    <select id="findEmployeeById2" resultMap="Employer">  
        select employee_id,name,b.first_name,b.salary,b.last_name from Employer a  
        left join Employee b on a.employee_id=b.id where a.id = #{abc}  
    </select>  
</mapper>  

The test code remains unchanged:

SqlSessionFactory sf = new SqlSessionFactoryBuilder().build(is);    
SqlSession s = sf.openSession();    
EmployerMapper employerMapper =  s.getMapper(EmployerMapper.class);  
Employer e2 =  employerMapper.findEmployeeById2(1);  
System.out.println(e2.getEmployee_id());  
System.out.println(e2.getName());  
System.out.println(e2.getEme().getFirst_name());  
System.out.println(e2.getEme().getLast_name());  
s.close();    

But unlike using extends in resultmap, result tags are indispensable, and once less, their attribute values will not be obtained.

After all the above twists and turns, I finally know what the author is talking about: finally, I understand the role of ResultMap in the book, mapping the results of the SQL selection declaration to JavaBean attributes. Simple selection declarations can be mapped to complex declarations through one-to-one and one-to-many associations.

Keywords: Mybatis xml Attribute Database

Added by cool-palace-ceo on Sat, 06 Jul 2019 01:33:57 +0300