基础技术(MapStruct、SPI、TK-Mybatis)



零、总结

MapStruct:简化对象间的映射操作,提高开发效率

@Mapper
public interface MyMapper {
    
    
    @Mapping(source = "name", target = "fullName")
    @Mapping(source = "age", target = "yearsOld")
    Target sourceToTarget(Source source);
}

// 在编译时会自动生成实现了映射接口的具体实现类, Mapper名称加Impl
MyMapper mapper = new MyMapperImpl(); 
Target target = mapper.sourceToTarget(source);

SPI:作用:在运行时动态加载实现类,而不是在编译时静态绑定。不需要显式地引用实现类

通过 META-INF/services 目录下提供一个以接口名称命名的文本文件 实现

ServiceLoader<Animal> serviceLoader = ServiceLoader.load(Animal.class);
for (Animal animal : serviceLoader) {
    
    ..
<think>我们是在讨论如何移除tk-mybatis(注意,tk-mybatis是一个第三方封装的MyBatis工具,不同于MyBatis-Plus)的乐观锁配置。但是,用户之前提供的引用内容中,似乎提到了MyBatis-Plus的乐观锁配置(因为引用的配置类使用了MybatisPlusInterceptor和OptimisticLockerInnerInterceptor)。而用户的上一个问题中,我们给出的回答也是针对MyBatis-Plus的。现在用户再次明确提问,并且说“参考站内引用”,但引用的两个片段中:引用1:是一个测试类,使用了@SpringBootTest,引用了MybatisPlusApplicationTests,这里使用了MyBatis-Plus的BaseMapper(UserMapper)。引用2:明确提到了Mybatis-Plus的乐观锁实现方式。然而,用户的问题是关于tk-mybatis的(注意tk-mybatisMyBatis-Plus是两个不同的框架)。这里可能存在用户混淆。因此,我们需要澄清:如果用户实际上使用的是MyBatis-Plus,那么按照之前的回答(移除OptimisticLockerInnerInterceptor和实体类的@Version)是正确的。如果用户使用的是tk-mybatis(即Mapper3,由国人开源的另一款MyBatis通用Mapper),那么它的乐观锁实现方式与MyBatis-Plus不同。但用户的问题描述中明确说“springboot整合tkmybatis”,所以我们按tk-mybatis来处理。然而,tk-mybatis本身并没有内置乐观锁插件!常见的tk-mybatis乐观锁实现方式有两种:1.开发者自己编写拦截器或通过自定义的方式实现(比如在实体类上加注解,并在更新时通过自定义SQL或动态SQL实现)。2.使用第三方扩展,比如有开发者自己封装的乐观锁插件(但tk-mybatis官方并未提供)。所以,如果用户之前通过某种方式配置了乐观锁(可能是自己实现的,也可能是引入了某个扩展),现在想移除,那么需要根据当初是如何配置的来回退。常见的tk-mybatis乐观锁实现步骤(参考):1.在实体类中添加一个版本字段,并使用自定义注解(比如@Version)标记。2.编写一个拦截器,在执行更新操作时,检查实体类中是否有@Version字段,然后生成带版本条件的SQL(类似于whereid=#{id}andversion=#{version}),并更新版本号(version=version+1)。因此,移除步骤应该是:1.删除拦截器配置(如果配置了一个拦截器来支持乐观锁,那么需要从MyBatis的配置中移除这个拦截器)。2.移除实体类中的版本字段或至少移除上面的注解(如@Version)。3.检查Mapper接口或XML文件中是否有关于乐观锁的自定义SQL,如果有则修改为普通更新。由于用户没有提供自己的配置细节,我们只能给出一般性的移除步骤。假设用户使用的是某个扩展插件(例如,已知的tk-mybatis-ext项目,但非官方),那么移除步骤可能包括:步骤1:移除MyBatis拦截器配置如果是在MyBatis配置类中注册了乐观锁拦截器,那么删除该拦截器的注册。例如,如果之前配置类中这样写:```java@BeanpublicMybatisInterceptormybatisInterceptor(){MybatisInterceptorinterceptor=newMybatisInterceptor();interceptor.addInnerInterceptor(newOptimisticLockerInnerInterceptor());//假设存在这样一个拦截器returninterceptor;}```那么现在删除这个配置,或者删除添加乐观锁拦截器的代码行。但是,tk-mybatis的拦截器配置方式不同于MyBatis-Plus。常见的tk-mybatis配置拦截器是通过在application.properties中指定,或者在配置类中通过SqlSessionFactoryBean设置。步骤2:移除实体类中的@Version注解在所有的实体类中,找到被@Version注解标记的字段,删除该注解。如果这个版本字段没有其他用途,也可以删除该字段。步骤3:检查自定义SQL查看MapperXML文件中是否有自定义的更新操作,这些操作可能包含了版本检查条件,例如:```xml<updateid="updateById">updateusersetname=#{name},version=version+1whereid=#{id}andversion=#{version}</update>```需要将这样的SQL修改为不包含版本检查的普通更新:```xml<updateid="updateById">updateusersetname=#{name}whereid=#{id}</update>```注意:由于tk-mybatis的通用Mapper(如使用MySqlMapper)提供了默认的updateByPrimaryKey方法,该方法生成的更新语句不包含乐观锁条件(除非实体类上有特殊注解触发生成条件)。所以如果你没有自定义SQL,那么移除拦截器后,通用Mapper生成的SQL就不会再有乐观锁条件了。步骤4:验证测试更新操作,确保不再进行版本检查,更新操作直接根据主键进行。但是,用户之前提供的引用内容中并没有关于tk-mybatis乐观锁的具体配置。所以如果用户没有自定义任何乐观锁拦截器,只是按照某些博客配置的,那么很可能是参考了MyBatis-Plus的配置(错误地引入到tk-mybatis项目中)。这种情况下,直接删除之前添加的配置类即可。结论:由于tk-mybatis本身不提供乐观锁,所以如果用户是自己实现的,则要自己移除相应的代码(拦截器、实体类注解、自定义SQL)。如果是引入了某个第三方扩展,则需要移除该依赖或配置。鉴于用户问题中提到了“tkmybatis”,我们可以认为:1.如果用户项目中存在类似MyBatis-Plus的配置(如之前回答中的配置类),则删除这个配置类(因为tk-mybatis项目不应该出现MyBatis-Plus的配置)。2.如果用户自定义了拦截器或使用了一个扩展包,则移除相应的拦截器配置。最安全的做法:在项目中搜索以下内容:-搜索类中是否有配置Interceptor(关键词:Interceptor,@Bean,SqlSessionFactory)-搜索实体类中是否有@Version注解(或类似的自定义注解)-搜索XML文件中的SQL是否包含version条件然后删除或修改这些内容。由于用户没有提供具体的配置代码,我们给出一个通用的移除步骤:1.检查并删除乐观锁拦截器配置:如果有一个配置类用于配置MyBatis的SqlSessionFactory,并设置了Plugins(即拦截器数组),那么移除其中关于乐观锁的拦截器。例如,原配置可能是:```java@BeanpublicSqlSessionFactorysqlSessionFactory(DataSourcedataSource)throwsException{SqlSessionFactoryBeansessionFactory=newSqlSessionFactoryBean();sessionFactory.setDataSource(dataSource);//...其他配置//设置拦截器Interceptor[]plugins={newMyOptimisticLockInterceptor()};//这个自定义的拦截器用于乐观锁sessionFactory.setPlugins(plugins);returnsessionFactory.getObject();}```现在删除设置Plugins的这行,或者移除数组中的MyOptimisticLockInterceptor。2.移除实体类中的@Version注解(假设用的是@Version):在实体类中找到这个字段,删除注解。如果版本字段不需要,也可以删除字段。3.修改MapperXML文件,将包含version条件更新的SQL语句修改为普通更新(如果使用了自定义SQL)。4.清除编译并重启测试。注意:以上步骤基于用户之前确实配置了乐观锁。如果一开始就没有配置,那么无需操作。由于用户的问题描述可能并不完全准确(因为引用的内容都是MyBatis-Plus的),建议用户确认自己使用的框架:-如果使用的是MyBatis-Plus,那么应该参考之前的回答(针对MyBatis-Plus的移除方法)。-如果使用的是tk-mybatis,则按本回答操作。最后,生成相关问题:</think> 要在 Spring Boot 项目中正确移除 tkMybatis 的乐观锁配置,请遵循以下详细步骤: ### 📌 完整移除步骤 #### 1. **移除乐观锁拦截器配置** ```java // 删除或注释包含乐观锁的拦截器配置 @Configuration public class MyBatisConfig { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); // ↓ 删除或注释此行 ↓ // interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); return interceptor; } } ``` > 如果配置类仅用于乐观锁,可直接删除整个类[^2] #### 2. **移除实体类的版本字段注解** ```java @Entity @Table(name = "user") public class User { // ↓ 删除或注释此行 ↓ // @Version private Integer version; } ``` #### 3. **清理 SQL 中的版本检查逻辑** 在 Mapper XML 文件中检查并删除所有包含版本检查的 SQL 片段: ```xml <!-- 原更新语句(含乐观锁检查) --> <update id="updateById"> UPDATE user SET name=#{name}, <!-- version=#{version} + 1 --> WHERE id=#{id} <!-- AND version=#{version} --> </update> <!-- 修改为无锁版本 --> <update id="updateById"> UPDATE user SET name=#{name} WHERE id=#{id} </update> ``` #### 4. **检查并更新测试类** 验证无锁操作是否正常: ```java @SpringBootTest class UserServiceTest { @Autowired private UserMapper userMapper; @Test void testUpdateWithoutLock() { User user = userMapper.selectById(1L); user.setName("NewName"); // 此时应直接执行无条件更新 int rows = userMapper.updateById(user); assertTrue(rows > 0); // 验证成功更新 } } ``` ### ⚠️ 重要注意事项 1. **并发风险处理**: - 移除乐观锁后,需通过**数据库行锁**(`SELECT ... FOR UPDATE`)或**业务层分布式锁**解决并发冲突 - 示例使用分布式锁: ```java @Service public class UserService { public void safeUpdate(Long id) { lock.lock(); // 获取分布式锁 try { User user = userMapper.selectById(id); userMapper.updateById(user); } finally { lock.unlock(); } } } ``` 2. **版本字段处理建议**: | 场景 | 操作方案 | |---|---| | 需业务追踪 | 手动管理版本号(非自动更新) | | 无业务价值 | 直接删除数据库字段 | | 表结构不可改 | 保留字段但移除业务逻辑引用 | 3. **事务调整**: - 添加 `@Transactional` 确保操作的原子性: ```java @Transactional public void updateUser(User user) { userMapper.updateById(user); } ``` ### ✅ 验证移除效果 1. 检查 SQL 日志,确认 `UPDATE` 语句**不再包含** `AND version=?` 条件 2. 执行并发更新测试,验证不会触发 `OptimisticLockException` 3. 监控版本字段值,确认**不再自动递增** --- ### 🔍 相关问题 1. 如何验证 tkMybatis 乐观锁已成功移除? 2. 移除乐观锁后常用的并发控制方案有哪些? 3. 在 tkMybatis 中如何手动管理版本号字段? 4. tkMybatisMyBatis Plus 的乐观锁机制有何核心差异? > 💡 实际操作中若发现 SQL 仍包含版本检查,检查是否存在其他未清理的自定义 SQL 拦截器[^1]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值