Custom mapping resultMap and lazy loading

Custom mapping resultMap:

resultMap handles the mapping relationship between fields and attributes

  • resultMap: Set custom mapping relationship
    • Attributes:
      • id: represents the unique identifier of the custom mapping, which cannot be repeated.
      • type: The type of entity class to be mapped to the queried data
    • Sub tags:
      • id: Set the mapping relationship of the primary key
      • result: Set the mapping relationship of common fields
      • Subtag attributes:
        • property: Set the attribute name in the mapping relationship, which must be the attribute name in the entity class type set by the type attribute.
        • column: Set the field name in the mapping relationship, which must be the field name queried by the SQL statement
  • –》If the field name is inconsistent with the attribute name in the entity class, you can set a custom mapping through resultMap. Even the attributes with the same field name and attribute name must be mapped, that is, all attributes must be listed.
<resultMap id="empResultMap" type="Emp">
<id property="eid" column="eid"></id>
<result property="empName" column="emp_name"></result>
<result property="age" column="age"></result>
<result property="sex" column="sex"></result>
<result property="email" column="email"></result>
</resultMap>

<!--List<Emp> getAllEmp();-->
<select id="getAllEmp" resultMap="empResultMap">
select * from t_emp
</select>
  • –》If the field name is inconsistent with the attribute name in the entity class, it is because the field name conforms to the rules of the database (using _ ), and the attribute name in the entity class conforms to the rules of Java (using camel case ). At this time, the mapping relationship between field names and attributes in the entity class can also be handled in the following two ways:

    1. You can alias the fields to ensure they are consistent with the attribute names in the entity class.

    <!--List<Emp> getAllEmp();-->
    <select id="getAllEmp" resultType="Emp">
    select eid,emp_name empName,age,sex,email from t_emp
    </select>
    

    2. You can set a global configuration information mapUnderscoreToCamelCase in the setting tag in the core configuration file of MyBatis, which can automatically convert _ type field names to camel case when querying data in the table, for example: The field name user_name, mapUnderscoreToCamelCase is set, and the field name will be converted to userName.

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

Many-to-one mapping processing:

Query employee information and department information corresponding to the employee

public class Emp {<!-- -->
private Integer eid;
private String empName;
private Integer age;
private String sex;
private String email;
private Dept dept;
//...Constructor, get, set method, toString method, etc.
}

How to deal with many-to-one mapping relationships: cascading attribute assignment

<resultMap id="empAndDeptResultMapOne" type="Emp">
<id property="eid" column="eid"></id>
<result property="empName" column="emp_name"></result>
<result property="age" column="age"></result>
<result property="sex" column="sex"></result>
<result property="email" column="email"></result>
<result property="dept.did" column="did"></result>
<result property="dept.deptName" column="dept_name"></result>
</resultMap>

<!--Emp getEmpAndDept(@Param("eid")Integer eid);-->
<select id="getEmpAndDept" resultMap="empAndDeptResultMapOne">
select * from t_emp left join t_dept on t_emp.eid = t_dept.did where t_emp.eid = #{eid}
</select>

The second way to deal with many-to-one mapping relationships: association tag

  • association: handles many-to-one mapping relationships
  • property: the property name that needs to handle the many-to-one mapping relationship
  • javaType: the type of this attribute
<resultMap id="empAndDeptResultMapTwo" type="Emp">
<id property="eid" column="eid"></id>
<result property="empName" column="emp_name"></result>
<result property="age" column="age"></result>
<result property="sex" column="sex"></result>
<result property="email" column="email"></result>
<association property="dept" javaType="Dept">
<id property="did" column="did"></id>
<result property="deptName" column="dept_name"></result>
</association>
</resultMap>

<!--Emp getEmpAndDept(@Param("eid")Integer eid);-->
<select id="getEmpAndDept" resultMap="empAndDeptResultMapTwo">
select * from t_emp left join t_dept on t_emp.eid = t_dept.did where t_emp.eid = #{eid}
</select>

The third way to deal with many-to-one mapping relationships: step-by-step query

The first step of step-by-step query. Query employee information
//Methods in EmpMapper.xml
/**
 * Query employee and department information corresponding to the employee through step-by-step query
 * Step-by-step query Step 1: Query employee information
 */
Emp getEmpAndDeptByStepOne(@Param("eid") Integer eid);
<resultMap id="empAndDeptByStepResultMap" type="Emp">
    <id property="eid" column="eid"></id>
    <result property="empName" column="emp_name"></result>
    <result property="age" column="age"></result>
    <result property="sex" column="sex"></result>
    <result property="email" column="email"></result>
    <!--
            select: Set the unique identifier of the SQL for step-by-step query (namespace.SQLId or the full class name of the mapper interface. Method name)
            column: Set the conditions for step-by-step query
          -->
    <association property="dept"
                 select="com.atguigu.mybatis.mapper.DeptMapper.getEmpAndDeptByStepTwo"
                 column="did"></association>
</resultMap>
    
<select id="getEmpAndDeptByStepOne" resultMap="empAndDeptByStepResultMap">
    select * from t_emp where eid = #{eid}
</select>
The first step of step-by-step query. Query department information
//Methods in DeptMapper
/**
 * Query employee and department information corresponding to the employee through step-by-step query
 * The second step of step-by-step query: query the department corresponding to the employee through did
 */
Dept getEmpAndDeptByStepTwo(@Param("did") Integer did);
<!--The resultMap here only handles the mapping relationship between fields (dept_name) and attributes (deptName) -->
<resultMap id="EmpAndDeptByStepTwoResultMap" type="Dept">
<id property="did" column="did"></id>
<result property="deptName" column="dept_name"></result>
</resultMap>

<!--Dept getEmpAndDeptByStepTwo(@Param("did") Integer did);-->
<select id="getEmpAndDeptByStepTwo" resultMap="EmpAndDeptByStepTwoResultMap">
select * from t_dept where did = #{did}
</select>

One-to-many mapping processing:

public class Dept {<!-- -->
    private Integer did;
    private String deptName;
    private List<Emp> emps;
//...Constructor, get, set methods, etc.
}

Resolve one-to-many mapping relationship through collection tag:

  • collection: used to handle one-to-many mapping relationships
  • ofType: Indicates the type of data stored in the collection corresponding to this attribute (which is the type of collection defined by List emps above)
<resultMap id="DeptAndEmpResultMap" type="Dept">
<id property="did" column="did"></id>
<result property="deptName" column="dept_name"></result>
    <!--
   collection: handles one-to-many mapping relationships
        ofType: Indicates the type of data stored in the collection corresponding to the attribute
 -->
<collection property="emps" ofType="Emp">
<id property="eid" column="eid"></id>
<result property="empName" column="emp_name"></result>
<result property="age" column="age"></result>
<result property="sex" column="sex"></result>
<result property="email" column="email"></result>
</collection>
</resultMap>

<!--Dept getDeptAndEmp(@Param("did") Integer did);-->
<select id="getDeptAndEmp" resultMap="DeptAndEmpResultMap">
select * from t_dept left join t_emp on t_dept.did = t_emp.did where t_dept.did = #{did}
</select>

Solve one-to-many mapping relationship through step-by-step query:

1. Query department information based on department id
/**
  * Query department and all employee information in the department through step-by-step query
  * Step-by-step query Step 1: Query department information
 */
Dept getDeptAndEmpByStepOne(@Param("did") Integer did);
<resultMap id="DeptAndEmpByStepOneResultMap" type="Dept">
<id property="did" column="did"></id>
<result property="deptName" column="dept_name"></result>
    <!--
select: Set the unique identifier of the SQL for step-by-step query (namespace.SQLId or the full class name of the mapper interface. Method name)
         column: Set the conditions for step-by-step query
-->
<collection property="emps"
select="com.atguigu.mybatis.mapper.EmpMapper.getDeptAndEmpByStepTwo"
column="did"></collection>
</resultMap>

<!--Dept getDeptAndEmpByStepOne(@Param("did") Integer did);-->
<select id="getDeptAndEmpByStepOne" resultMap="DeptAndEmpByStepOneResultMap">
select * from t_dept where did = #{did}
</select>
2. Query all employees in the department based on department id
/**
  * Query department and all employee information in the department through step-by-step query
  * The second step of step-by-step query: Query employee information based on did
  * The type is defined as: List<Emp> because the type of emps defined in the model class of Dept is this
 */
List<Emp> getDeptAndEmpByStepTwo(@Param("did") Integer did);
<!--List<Emp> getDeptAndEmpByStepTwo(@Param("did") Integer did);-->
<select id="getDeptAndEmpByStepTwo" resultType="Emp">
select * from t_emp where did = #{did}
</select>

Summary:

?Many to one: corresponding object! (You need to create a “one” object in the entity class, which is equivalent to creating the Dept object in the Emp class above)!

?One-to-many: corresponding set! (You need to create a collection that stores “many” in the entity class, which is equivalent to creating the List collection in the Dept class above)!

Lazy loading:

  • Advantages of step-by-step query: Lazy loading can be achieved, but global configuration information must be set in the core configuration file:
    • lazyLoadingEnabled: global switch for lazy loading. When enabled, all associated objects will be loaded lazily
    • aggressiveLazyLoading: When enabled, any method call will load all properties of the object. Otherwise, each property is loaded on demand
  • At this time, on-demand loading can be achieved. Whatever data is obtained, only the corresponding SQL will be executed. At this time, you can set whether the current step-by-step query uses lazy loading (making lazy loading controllable) through the fetchType attribute in association and collection, fetchType=”lazy (lazy loading (default))|eager (immediate loading)”
<!--Core configuration file (mybatis-config.xml)-->
<settings>
<!--Enable delayed loading, so that all delayed loading is implemented within Mybatis! -->
<setting name="lazyLoadingEnabled" value="true"/>
</settings>
@Test
public void getEmpAndDeptByStepOne() {<!-- -->
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
Emp emp = mapper.getEmpAndDeptByStepOne(1);
System.out.println(emp.getEmpName()); // Only get employee names!
}
  • Turn off lazy loading and both SQL statements are run.
  • Enable lazy loading and only run the SQL statement to obtain emp
@Test
public void getEmpAndDeptByStepOne() {<!-- -->
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
Emp emp = mapper.getEmpAndDeptByStepOne(1);
System.out.println(emp.getEmpName());
System.out.println("----------------");
System.out.println(emp.getDept());
}
  • Turn off lazy loading:

  • After it is turned on, the corresponding SQL statement will be called only when querying dept.

<resultMap id="empAndDeptByStepResultMap" type="Emp">
<id property="eid" column="eid"></id>
<result property="empName" column="emp_name"></result>
<result property="age" column="age"></result>
<result property="sex" column="sex"></result>
<result property="email" column="email"></result>
    <!--
 fetchType: When global delayed loading is enabled (global delayed loading must be enabled first, otherwise the following two attributes mean immediate loading), you can manually control the effect of delayed loading through this attribute.
fetchType="lazy(lazy loading (default))|eager(immediate loading)"
-->
<association property="dept"
select="com.atguigu.mybatis.mapper.DeptMapper.getEmpAndDeptByStepTwo"
column="did"
fetchType="lazy"></association>
</resultMap>