背景:原项目用mybatis,感觉很麻烦,一些基础的crud也要写,而且还出容易出错,但是已经有不少代码使用旧方法写了,一定要保证老的代码不能出现问题,改动不能太大,实现平滑升级,从网上查了很多,磕磕绊绊总算弄好了,问题总是一个又一个冒出来,特此记录一下,希望能帮助后边的人少踩些坑
1、首先第一步就是引入mp依赖:
<dependency>
<groupId></groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.5</version>
<exclusions>
<exclusion>
<artifactId>mybatis-spring</artifactId>
<groupId></groupId>
</exclusion>
<exclusion>
<artifactId>mybatis</artifactId>
<groupId></groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId></groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<!--基于Spring Boot引入 Caffeine本地缓存依赖-->
<dependency>
<groupId></groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId></groupId>
<artifactId>caffeine</artifactId>
</dependency>
<!-- MyBatis-Plus 代码生成器依赖 -->
<dependency>
<groupId></groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.3.2</version>
</dependency>
<!-- FreeMarker -->
<dependency>
<groupId></groupId>
<artifactId>freemarker</artifactId>
<version>2.3.31</version>
</dependency>
<!-- Swagger 核心库 -->
<dependency>
<groupId></groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<!-- Swagger UI 页面 -->
<dependency>
<groupId></groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<!--pagehelper分页插件依赖-->
<dependency>
<groupId></groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
</dependency>
针对以上依赖我简单说明一下,有需要的话一次性加好:
- mp3.5.5是我试过的最新版本了,想升级更高的版本的话可能还要考虑更多依赖兼容问题
- mybatis-spring-boot-starter版本是2.3.2版本,暂时不能升更高了,更高会报错,不信的可以自己试一下
- 想使用一些他本地的缓存策略的话,要用caffine依赖,这个看自己需要,我是有就加,无所畏惧
- mp的生成器这个很方便,建议是都要加上,我换mp的原因之一也是因为这个很方便,想玩的话自己自定义一些代码模板,会更方便,这也是我下一步的计划
- freemarker是为生成器依赖准备的,所以直接加上不犹豫
- swagger可以有可以没有,但是生成器里边往往也会和swagger互动,为了避免麻烦调整,直接加上
- 最后一个是因为我是从mybatis升级过来的,用的就是这个通用的mybatis分页插件,如果直接改成mp的分页插件,以前的老代码直接报销,所以就用这个更通用的,适合老升新,全新的项目爱用什么用什么,个人觉得这个插件也挺好的,老但是好用
2、第二步:直接用代码生成器生成代码去
既然玩就直接玩全套的,这个官网上有直接现成的代码mp生成器代码,自己过去看
3、直接拿个新的mapper试一下
基本上mapper行,那就新代码都行,所以自己写个springboot的测试用例测试一下吧,这种随便一搜都有的我就不复制给大家了,毕竟我也是抽工作的空写的
4、不出意外,肯定有意外
我遇到了不少问题,但比较核心的就两个,有遇到同样的问题的,希望可以帮到你
1、mapper扫描不到的老代码的情况,我mapperscan注解里明明加了对应的包,根本不起效果,我debug源代码看了好一会,发现是我的statement根本就没有老代码用xml写的方法,新代码那些默认的这些注册方法倒是加进去了,说明xml文件始终被扫描不到,最后我在配置类里直接用变量注入的方式搞定了,奉劝大家如果实在不生效,肯定是包之间有兼容或者冲突问题了,本着能跑就行的原则,直接配置类里写
package ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
/**
* @author nxj
*/
@Configuration
public class MyBatisPlusConfig {
@Value("${-locations}")
private String mybatisPlusMapperLocations;
static {
// 默认支持序列化 FstSerialCaffeineJsqlParseCache,JdkSerialCaffeineJsqlParseCache
(new JdkSerialCaffeineJsqlParseCache(
(cache) -> (1024)
.expireAfterWrite(5, ))
);
}
@Bean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
MybatisSqlSessionFactoryBean sqlSessionFactory = new MybatisSqlSessionFactoryBean();
(dataSource);
MybatisConfiguration configuration = new MybatisConfiguration();
(configuration);
(new PathMatchingResourcePatternResolver().getResources(mybatisPlusMapperLocations));
// 全局配置
GlobalConfig globalConfig = new GlobalConfig();
// ...其他配置...
(globalConfig);
return ();
}
// @Bean
// public MybatisPlusInterceptor mybatisPlusInterceptor() {
// MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// (new PaginationInnerInterceptor());
// return interceptor;
// }
}
最终加上这行终于扫描进来了,真够费劲的
2、第二个问题来源于LocalDate这1.8整个新时间类型的问题,按说如果是纯净的mp是带有序列化和反序列化器的,但我的就是不生效,我自己写了两个序列化气也是通过上面的配置类注入进去,就可以,我当时想也是依赖冲突了,最后发现mybatis依赖了两个版本,统一了版本还是没用,因为其实不算太搭噶,不同模块依赖的不同版本,所以找错方向了,最后通过debug源码,发现了在解析LocalDate这一类型的时候,是druid这个依赖掉了链子:
<!--阿里jdbc链接数据库依赖-->
<dependency>
<groupId></groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${}</version>
</dependency>
我依赖的版本是1.1.9(老项目了,可以理解吧)核心是这个类DruidPooledResultSet,简而言之mybatis会把结果集类型转换的事情交给这个类来搞,调用getObject方法,结果这个类的早期版本根本不支持这样做,所以会抛出异常
public <T> T getObject(int columnIndex, Class<T> type) throws SQLException {
throw new SQLFeatureNotSupportedException();
}
public <T> T getObject(String columnLabel, Class<T> type) throws SQLException {
throw new SQLFeatureNotSupportedException();
}
既然如此直接升级,druid版本直接来到1.2.8,这个版本的getObject方法长这样,这就丝滑,然后就解决了序列化的问题,所有类型转换都正常了,自己写的序列化器也果断删掉,有官方的,就绝不用自己写的,哈哈哈哈
@Override
public <T> T getObject(int columnIndex, Class<T> type) throws SQLException {
try {
return (columnIndex, type);
} catch (Throwable t) {
throw checkException(t);
}
}
@Override
public <T> T getObject(String columnLabel, Class<T> type) throws SQLException {
try {
return (columnLabel, type);
} catch (Throwable t) {
throw checkException(t);
}
}
行,大概的就先到这儿吧,关键的我也都写了,废话不能说没有,原因是我也是第一次写,不太会搞格式啥的,思路有,但怎么输出给大家我也不算很擅长,只有慢慢改进了,希望有错误的地方大家包涵并指正一下,一不小心能能帮到你的话,那就真的太好了