Preface
In high concurrency scenarios, optimistic locking is the core tool to ensure data consistency. As the leader of the Java ORM framework, MyBatis-Plus provides developers with elegant and optimistic lock implementations through @Version annotation and OptimisticLockerInnerInterceptor plug-in. However, developers often encounter the problem of optimistic locking "not taking effect" in actual use.
1. The core principle of optimistic locking
1. What is optimistic lock?
Optimistic locking is a concurrency control strategy that assumes that "conflicts rarely occur" (optimistic locking assumes that most operations will not conflict and only checks the data version when updated. If the version matches, the update will be successful; otherwise, an exception will be thrown). The core idea is:
-
When reading data: Record the current version number (such as
version
field). -
When updating data: Verify whether the version number matches. If it matches, the update is successful and the version number is incremented; otherwise, an exception is thrown (such as
OptimisticLockException
)。
2. The implementation mechanism of MyBatis-Plus
MyBatis-Plus achieves optimistic locking through the following three steps:
- Entity class annotation @Version annotation: marks the version number field.
- Configure the OptimisticLockerInnerInterceptor plug-in: Intercept SQL and automatically process version number conditions.
- Automatically verify the version number during update operation: generate SQL similar to UPDATE ... WHERE version = ?.
2. Common reasons for the failure of optimistic locks
1. The plugin is not configured correctly
question: Not registeredOptimisticLockerInnerInterceptor
Plugin, causing MyBatis-Plus to not automatically process version number logic.
Sample code:
@Configuration public class MyBatisPlusConfig { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); // Optimistic lock plugin must be added (new OptimisticLockerInnerInterceptor()); return interceptor; } }
2. Entity class field is not marked @Version
question: Not used in entity class@Version
Note, MyBatis-Plus cannot recognize the version number field.
Sample code:
import ; public class User { // Correctly label the version number field @Version private Integer version; // Other fields...}
3. Database fields are not initialized
question: Database tableversion
The field isNULL
Or the default value is not set, resulting in the inability to compare version numbers during the first update.
Solution:
-- make sure version The field has an initial value ALTER TABLE user ADD COLUMN version INT NOT NULL DEFAULT 1;
4. The update operation is not based on the query data
question: Directly construct new object updates, and the version number in the database is not read, resulting in the optimistic lock failure.
Sample code:
// Error method: directly construct new objectUser user = new User(); (1L); ("New Name"); (user); // version not passed, optimistic lock fails // Correct way: query the data firstUser user = (1L); // Query the current data (including version)("New Name"); (user); // Automatic processing version increment
5. Custom SQL does not include version number conditions
question: Not explicitly added when using custom SQL updateversion
Conditions lead to the failure of optimistic lock plug-in.
Solution:
<!-- The correct way:Explicitly added version condition --> <update > UPDATE user SET name = #{name}, version = version + 1 WHERE id = #{id} AND version = #{version} </update>
6. The transaction is not started correctly
question: Optimistic locking depends on the atomicity of the transaction. If the transaction is not enabled, it may cause the version number to be updated.
Sample code:
@Transactional public void updateData(Long id, String newName) { User user = (id); // Query data (newName); (user); // The version number is incremented after the transaction is committed}
7. Concurrent tests did not trigger conflict
question: The concurrent scenario is not simulated, and the verification effect of optimistic lock cannot be observed.
Test code:
@Test public void testOptimisticLock() { User user1 = (1L); // version=1 User user2 = (1L); // version=1 ("Thread 1"); (user1); // version becomes 2 ("Thread 2"); try { (user2); // OptimisticLockException should be thrown here } catch (OptimisticLockException e) { ("Optimistic lock takes effect, update failed"); } }
8. Version field type mismatch
question:@Version
The types supported by annotations areInteger/Long/Date/Timestamp/LocalDateTime
, if using other types (such asString
), which will cause the optimistic lock to fail.
Sample code:
// Correct type@Version private Integer version; // or Long/LocalDateTime // Error type@Version private String version; // Type mismatch, optimistic lock fails
9. MyBatis-Plus version is too low
question: Older versions may have bugs or feature limitations.
Solution: Upgrade to the latest version (recommended3.5.7+
)。
<dependency> <groupId></groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.7</version> </dependency>
3. Complete solution example
1. Database table design
CREATE TABLE user ( id BIGINT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(100), version INT NOT NULL DEFAULT 1 -- Initialize version number );
2. Entity class configuration
import .*; @TableName("user") public class User { @TableId(type = ) private Long id; private String name; @Version private Integer version; // Version number field // Getter & Setter }
3. Configure plug-in
@Configuration public class MyBatisPlusConfig { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); (new OptimisticLockerInnerInterceptor()); return interceptor; } }
4. Business logic code
@Service public class UserService { @Autowired private UserMapper userMapper; @Transactional public void updateUser(Long id, String newName) { User user = (id); // Query the current data (newName); int result = (user); // Automatic version processing if (result == 0) { throw new OptimisticLockException("Optimistic lock update failed"); } } }
4. Advanced skills and precautions
1. Custom version number field name
If the database field name is inconsistent with the entity class field name, you can use@TableId
or@TableField
Specify the mapping:
@TableField("ver") @Version private Integer version;
2. Verification of version number for multi-condition updates
In complex update scenarios, the version number logic needs to be processed manually:
UpdateWrapper<User> wrapper = new UpdateWrapper<>(); ("id", 1L).eq("version", ()); (() + 1); (user, wrapper);
3. Version number consistency in distributed environments
In a distributed system, ensure that all nodes share the same database and avoid version number conflicts. If you need to synchronize across nodes, you can combine Redis or database middleware to implement it.
4. Performance optimization suggestions
- Reduce transaction scope: Only start transactions when necessary to avoid long transactions affecting concurrency performance.
- Batch update version number processing: For batch operations, you need to verify the version number one by one, or use sharding strategy.
5. Summary
The essence of MyBatis-Plus' optimistic locking mechanism is to "ensure data consistency through version number comparison", but its effectiveness depends on the correct configuration and implementation of multiple links. Here is a review of key points:
Key points | illustrate |
---|---|
Plug-in configuration | Must registerOptimisticLockerInnerInterceptor
|
Entity class annotation | use@Version Label version number field |
Database initialization |
version The field must have a non-null initial value |
Update logic | Based on the query data update, avoid direct construction of new objects |
Custom SQL | Explicitly addedversion condition |
Transaction Management | use@Transactional Ensure transaction consistency |
Concurrent testing | Simulate multi-threaded scene verification optimistic locking effect |
Field type and version compatibility | Make sure the field type isInteger/Long/LocalDateTime , upgrade MyBatis-Plus to the latest version |
Official DocumentMyBatis-Plus Optimistic Lock Guide。
The above is the detailed content of the common causes and solutions for the failure of MyBatis-Plus optimistic lock. For more information about the failure of MyBatis-Plus optimistic lock, please pay attention to my other related articles!