前言
之前我写过一篇《mybatis分页插件pagehelper的基本使用方法》。当时主要是图简单,引入简单,使用简单,不用想那么多功能。不过最近,我对自己进行了深入的反思。觉得自己太过于纠结代码的细节了。其实,之前查过mybatis plus,但是由于学习成本有些高,封装的功能有点多,就不太像学它。另外,由于我对于实体的建立,增删改查的操作逻辑,各层对象的属性把控都提出了很高的要求,要求研发人员注意思考并实现。于是,就造成了像mybatis plus这种可以快速帮助我们进行增删改查的框架发挥不了多大作用。
但是,后来我进行了自我的深入反思。反观一年来团队的建设内容,说实话,少的可怜。而且,质量也不见得多高。为什么呢?因为,我无法和我自己合作,研发人员和我是两个个体,我无法对他们提出对我自己的要求,因为他们不知道我在想什么,我接下来想到了什么。另外,由于建设思考的多,速度就慢下来了,所以反馈循环走的少,自然质量高不起来,自己再怎么思考也是空想,需要结合实践的反馈才有现实意义。
而且,最近我 突然想通了。其实,大部分的操作就是快速的增删改查。因为,有了基础的数据,才能够进行更高层面的设计和建设。所谓设计能力,不是凭空设计和想象的能力,而是在变化和不确定中带着项目一步一步向前走的能力。所以,现在我要拥抱mybatis plus这种生产力工具啦。(熟悉之后,我还希望能够参与这个开源项目)
引入
这次的引入费了我不小的周折呀。先说正确的引入方法吧,其实很简单:
- 引入mybatis-plus-boot-starter,配好DataSource。其实这样就完成了引入,就可以使用了。
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.1</version>
</dependency>
- 但是,我是老项目改造,所以还有些后续工作,就是修改SqlSessionFactory的bean,之前这个bean是直接使用Mybatis的Bean,这里要改成Mybatis plus的bean
@Bean
public SqlSessionFactory sqlSessionFactory() throws Exception {
MybatisSqlSessionFactoryBean fb = new MybatisSqlSessionFactoryBean();
fb.setDataSource(dataSource);// 指定数据源(这个必须有,否则报错)
return fb.getObject();
}
- 这一步其实可有可无,但是鉴于我费了那么大的劲,还是写上吧,就是调整好依赖。由于我引入的starter的springboot的版本和项目原本的版本并不一致,所以起初我以为是这个原因。但是,后来经过问题的排查和解决,基本可以确定不是这里的原因。但是,调整的过程中,却出现过Application找不到上下文的问题,起原因是2.1.x和2.2.x的差异导致的。这也是我最近发现的,即现在spring里面第二位版本号的差异也可能导致一些兼容性问题了。
使用BaseMapper
其实,这个使用也很简单,但是因为我引入的过程是那它做的第一个例子。所以,这里还是介绍下我验证过的一些事情。
- 首先,在官方文档中都是使用MapperScan来划定引入范围的,其实使用Mapper注解是同样生效的。
- BaseMapper的生效一是依赖于Mapper的扫描,而是你需要使用mybatis plus的SqlSessionFactory,就是我在引入章节第二点写的。
- 能找到Mapper了,我们还需要标志实体对应的是哪张表,主键是谁。这通过在类上的注解TableName和属性上的注解TableId来解决这个问题。
- 它对应的操作会自动的把实体中驼峰的命名转换为下划线分隔的命名方式,不一致的可以自己通过注解指明。但是,需要注意的是,java的数据类型要和数据库的对应上。我把我验证过的数据类型列在了下面,由于我使用的是PostgreSQL,所以这里的数据类型是PostgreSQL的
JAVA类型 | PostgreSQL类型 |
---|---|
Integer | int(4) |
Long | int(8) |
Boolean | bool |
String | varchar |
- 说了这么多都没说怎么用。其实很简单,建立自己的Mapper接口,然后让他继承BaseMapper并指定实体泛型即可
常用注解
TableName
我主要用来标志表名是谁。在使用自定义的TypeHandler的时候,可以打在属性上,然后设置autoResultMap为true。别的功能就没用过了。
TableId
用来标志谁是主键
TableField
这个是打在属性上的。对属性做的事情基本都在这里。我用过的功能有:
- 设置数据库对应的列名。驼峰和下划线是自动转换的,无法自动转换就得自己写了。
- 设置自定义的TypeHandler,比如我自己写的JsonTypeHandler
- 设置更新策略,比如我的updatetime和createtime都是数据库自动更新,就需要设置插入和更新的策略忽略他们。还有一些,具体看官方文档吧。
使用条件构造器进行条件查询
其实,早期的时候我并没有把这个算成吸引我的东西。不过随着写的业务的深入,能够直接使用java的条件构造器自定义where语句,而不是想着怎么兼容各种可能有的没有的条件去写可以参数化的sql语句,这个确实是省了不少心的。这对于编码量和研发时间是非常直接的节约,同时由于不用自己设计了,也会减少很多bug的产生,很实用。
具体的使用其实也很简单,官方的指南中有条件构造器的章节。它整体上都是基于其AbstractWrapper。其下,针对select和Update有特定的实现类,使用对应的接口实现想要的功能就好。并不复杂。具体的使用,我就不赘述了,官网文档讲的很清楚:https://mybatis.plus/guide/wrapper.html#abstractwrapper 我的使用方式一般如下:
//我这个例子里用到了分页参数,需要自行构建。
LambdaQueryWrapper<YourEntity> queryWrapper= Wrappers.lambdaQuery();
//下面根据你的条件构造需要对queryWrapper进行调整,比如下面:
//记录ID
if(condition.getRecordId()!=null){
queryWrapper=queryWrapper.eq(SensorBatchEntity::getRecordId,condition.getRecordId());
}
//最后,使用构造好的queryWrapper进行查询即可。
IPage<YourEntity> data= this.sensorBatchDao.selectPage(page,queryWrapper);
下面要说的是一些小众的操作。
自定义条件拼接
由于我的表里面有PostgreSQL的jsonb字段,使用jsonb里的值进行查询时,预定好的条件语句就显得不够用了。这个时候,就需要其条件构造器中的apply方法进行支持了。它的声明如下:
apply(String applySql, Object... params)
apply(boolean condition, String applySql, Object... params)
这个方法里,可以放置你自定义的条件语句的sql,比如下面的形式:
apply("((light_source->>'ps')::int2={0} or (light_source->>'led')::int2={0})",queryCondition.getLightSource())
light_source的数据类型是jsonb,根据值中的属性进行查询和筛选在mybatis plus中是不支持的。但是,我有不想自己写一个查询方法,于是就找到了apply方法来解决这个问题。在上述代码中,可以看到我们使用了字符串的{index}来拼接语句。这样是可以防止sql注入的,如果不用这种形式,直接拼接好字符串放进去,也是可以的,但是无法防止sql注入。
分页插件
默认mybatis-plus是没有配置分页插件的。所以,即使你按照官网提供的方法调用了,也会发现,分页并没有生效。我的配置代码如下:
@Bean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
MybatisSqlSessionFactoryBean fb = new MybatisSqlSessionFactoryBean();
// 指定数据源(这个必须有,否则报错)
fb.setDataSource(dataSource);
//分页插件
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
// 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求 默认false
// paginationInterceptor.setOverflow(false);
// 设置最大单页限制数量,默认 500 条,-1 不受限制
// paginationInterceptor.setLimit(500);
// 开启 count 的 join 优化,只针对部分 left join
paginationInterceptor.setDbType(DbType.POSTGRE_SQL);
paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));
fb.setPlugins(paginationInterceptor);
// 开启 数据库字段 下划线 转驼峰
//fb.getObject().getConfiguration().setMapUnderscoreToCamelCase(true);
return fb.getObject();
}
总之,就是使用mybatis-plus提供的SqlSessionFactory来创建SqlSession,并把分页插件配置进去,就可以了。
网友评论