1. Lazy loading strategy: load on demand, optimize performance
1. Lazy Load vs Load Now: Core Difference
-
Load now: When the main query (such as querying the user) is executed,Actively associated loading of associated data(such as all users’ accounts).
- Scene: For many-to-one query (such as an account associated with a user), you need to obtain the associated data immediately.
-
Delay loading: When the main query is executedThe associated data is not loaded yet, only when the program accesses the associated data, a subquery will be triggered.
- Scene: One-to-many query (such as the user associated with multiple accounts), reducing the initial query pressure.
To give a small example:
Scene: The user information is not loaded immediately when querying, and the query is only triggered when the order needs to be viewed.
Example: The e-commerce user details page first displays the user's name and address. Only when the user's order list is loaded is loaded when the "View Order" button is clicked.
2. Many-to-one lazy loading implementation (Account → User)
Step analysis:
1. Define the association query: The main query only checks the account table, and the associated user information is delayed by subquery.
<!-- Main query:Check the account only --> <select resultMap="accountMap"> SELECT * FROM account </select> <!-- Subquery:By userIDCheck user information --> <select parameterType="int" resultType="User"> SELECT * FROM user WHERE id = #{id} </select>
2. Configure delayed loading:passassociation
Tags specify subquery paths and parameters.
<resultMap type="Account" > <association property="user" <!-- AccountIn the classUserproperty --> javaType="User" <!-- Associated object type --> select="findById" <!-- Subquery method name --> column="uid" <!-- The column used for association in the main query result(Account tableuid) --> /> </resultMap>
3. Globally enable delayed loading:existConfiguration.
<settings> <setting name="lazyLoadingEnabled" value="true"/> <!-- Turn on delayed loading --> <setting name="aggressiveLazyLoading" value="false"/> <!-- Close Active Loading(All associated data will be loaded by default) --> </settings>
Test verification:
@Test public void testLazyLoading() { List<Account> accounts = (); for (Account account : accounts) { ("Account Amount:" + ()); // Only the amount is output when the main query is executed ("User Name:" + ().getUsername()); // Trigger subquery when accessing user for the first time } }
3. One-to-many lazy loading implementation (User → Accounts)
Core configuration:
<!-- Main query:Check the user table only --> <select resultMap="userMap"> SELECT * FROM user </select> <resultMap type="User" > <collection property="accounts" <!-- UserAccount list attributes in class --> ofType="Account" <!-- Collection element type --> select="" <!-- Subquery:By userIDCheck the account --> column="id" <!-- Main query结果中的用户ID --> /> </resultMap> <!-- Subquery:According to the userIDCheck the account --> <select parameterType="int" resultType="Account"> SELECT * FROM account WHERE uid = #{uid} </select>
Key Differences:
- Many-to-one use
association
(Single object), one-to-multi-purposecollection
(gather). - Subquery parameters pass
column
Pass the fields in the main query result (such as the user tableid
)。
2. MyBatis caching mechanism: reduce database access
1. The core value of cache
- definition: Storing frequently queried data in memory temporarily to avoid repeated access to the database and improve query speed.
- Applicable scenarios: Data that reads more and writes less and updates infrequently (such as dictionary tables, configuration information).
2. Level 1 cache: SqlSession-level cache
(1) Essence and function
-
Scope:based on
SqlSession
Object, sameSqlSession
The same query inside will get the results directly from the cache. -
Implementation principle:
SqlSession
Maintain an internal oneHashMap
, the key is the unique identifier of the query (SQL + parameter), and the value is the query result object.
(2) Verify Level 1 cache
@Test public void testFirstLevelCache() { // Two identical queries within the same SqlSession User user1 = (1); User user2 = (1); // Get it directly from the cache without executing SQL (user1 == user2); // Output true (the object reference is the same)}
(3) Cache failure scenario
-
SqlSession
Close or submit (commit
)。 - implement
update
/insert
/delete
Operation (the cache will be cleared). - Manual call
()
Clear the cache.
3. Level 2 cache: SqlSessionFactory-level cache
(1) Core concept
-
Scope:based on
SqlSessionFactory
, crossSqlSession
Shared cache (such as multipleSqlSession
Execute the same query). -
Implementation conditions:
Entity class needs to be implemented
Serializable
Interface (serialized storage is supported).exist
Enable Level 2 cache (it is enabled by default).
Configure in Mapper
<cache/>
Label.
(2) Configuration steps
1、 Entity class serialization:
public class User implements Serializable { // Omit properties and methods}
2. Enable cache in Mapper:
<mapper namespace=""> <cache/> <!-- Enable Level 2 Cache --> <select resultType="User" useCache="true"> SELECT * FROM user WHERE id = #{id} </select> </mapper>
3. Configure cache policy (optional):
<cache eviction="LRU" <!-- Cache Elimination Strategy:LRU(Least recently used) --> flushInterval="60000" <!-- Automatic refresh interval(millisecond) --> size="512" <!-- Maximum number of cached objects --> readOnly="true" <!-- Read only:true(Shared Objects)/ false(Copy the object) --> />
(3) Cache priority and refresh
- Priority: Level 2 Cache > Level 1 Cache > Database Query.
-
Refresh mechanism:implement
update
/insert
/delete
When , the corresponding Mapper's level 2 cache will be cleared.
(4) Test and Verification
@Test public void testSecondLevelCache() { try (SqlSession session1 = ()) { UserMapper mapper1 = (); User user1 = (1); // The first query is to hit the database } try (SqlSession session2 = ()) { UserMapper mapper2 = (); User user2 = (1); // The second query hits the second level cache and does not execute SQL } }
3. Summary: Core points of performance optimization
technology | Core role | Key configurations |
Delay loading | Reduce the initial query data volume and improve response speed |
lazyLoadingEnabled 、association/collection ofselect Attributes |
Level 1 cache | Reduce duplicate queries within the same session | Automatically take effect, no additional configuration is required (noteSqlSession life cycle) |
Level 2 cache | Share cache across sessions to reduce database pressure | Entity class serialization,<cache/> Tags and cache policy configuration |
Rational use of delayed loading and caching can significantly improve the performance of MyBatis applications, but it needs to be flexibly selected according to the business scenario to avoid data inconsistency or memory overflow caused by excessive use.
This is the end of this article about the implementation of MyBatis lazy loading and caching. For more related content on MyBatis lazy loading and caching, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!