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()