Delayed loading mechanism of mybatis

Delayed loading mechanism of mybatis

The meaning of delayed loading: relevant operations will be carried out only when it is used

Mybatis supports delayed loading of association Association objects and Collection association collection objects

Difference: association usage scenario is a one-to-one association query, and collection is a one to many association query

Its principle is

  • Use CGLIB dynamic proxy to create the proxy object of the target object. When calling the target method, enter the interceptor method to check whether there is a value
  • For example, call user Getaccount(), interceptor invoke() method found user If getaccount () is a null value, the sql query associated with the user object will be sent separately to query the account
  • Then call user.. Setaccount (account), so the user's account attribute has a value

Example

An account and a user table

CREATE TABLE `account` (
  `acc_id` int(11) NOT NULL,
  `num` int(10) unsigned zerofill DEFAULT NULL,
  `user_id` int(11) NOT NULL,
  PRIMARY KEY (`acc_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE `user` (
  `user_id` int(11) NOT NULL,
  `name` varchar(255) NOT NULL,
  PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

Here, an Account member variable is added to the user entity class to test delayed loading

public class User{
    private Integer userId;

    private String name;

    private Account account;
}
public class Account{
    private Integer accId;

    private Integer num;

    private Integer userId;
}

When we normally query user by id, only one sql statement is queried

//java code 
User user = userMapper.selectByPrimaryKey(1);
System.out.println("user.getUserId() = " + user.getUserId());
System.out.println("user.getName() = " + user.getName());
System.out.println("user.getAccount() = " + user.getAccount());

//sql
select user_id, `name` from test.`user` where user_id = ?
//result
user.getUserId() = 1
user.getName() = test
user.getAccount() = null

If we turn on delayed loading

In the Mybatis configuration file, you can configure whether deferred loading is enabled

# Turn on delayed loading
mybatis.configuration.lazy-loading-enabled=true
# Change positive loading to negative loading, that is, delayed loading
mybatis.configuration.aggressive-lazy-loading=false

In usermapper Add an association tag to the resultMap in the XML file

(if it is a one-to-one relationship, use the association label, and one to many use the collection label)

It means that I not only need to put the original user in the database_ ID and name

I will also delay loading the attributes corresponding to the following features

  • The property property name is account

  • The full javaType class name is com ifyyf. boot_ test. pojo. Account

  • The location of the select query method is com ifyyf. boot_ test. dao. AccountMapper. Selectbyuserid (method in accountmapper)

  • The parameter passed in by column is user_ ID (because the selectByUserId in AccountMapper is queried based on user_id)

  <resultMap id="BaseResultMap" type="com.ifyyf.boot_test.pojo.User">
    <!--@mbg.generated-->
    <!--@Table test.`user`-->
    <id column="user_id" jdbcType="INTEGER" property="userId" />
    <result column="name" jdbcType="VARCHAR" property="name" />
    <association property="account"
                 javaType="com.ifyyf.boot_test.pojo.Account"
                 select="com.ifyyf.boot_test.dao.AccountMapper.selectByUserId"
                 column="user_id">
    </association>
  </resultMap>

Result analysis

We can see from the picture that the sql code is executed twice, and the execution time is different

  • select user_id,namefrom test.userwhere user_id = ?, First, query the user object through the ID, and output the userId and name (this is executed normally)
  • Then when it executes system out. println("user.getAccount() = " + user. getAccount()); Found user Getaccount () is null, and then select * from account where user is executed again_ id = ?
  • Then set the queried account result into user, that is, user setAccount(account)
  • Finally, print it out user getAccount()

Keywords: Java MySQL Hibernate Mybatis Back-end

Added by frankstr on Tue, 18 Jan 2022 00:42:40 +0200