MyBatis-Plus(苞米豆)快速进行开发

1,143 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第6天,点击查看活动详情

前言

orm持久层层现在我们用的比较多的框架是MyBatis,自动生成dao层代码,简化了开发的复杂性,动态sql可以自由实现业务逻辑,一级、二级缓存、分页、批量操作,如果还觉得不够,还想偷懒的话,那么就可以用 MyBatis-Plus简称 MP是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。MyBatis-Plus 可以不需要写SQL语句就能快速完成单表的操作,MyBatis-Plus的愿景就是成为 MyBatis 最好的搭档。

快速构建项目

1.导入MyBatis-Plus(baomidou)核心依赖

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-generator</artifactId>
    <version>3.3.2</version>
</dependency>

<dependency>
    <groupId>org.apache.skywalking</groupId>
    <artifactId>apm-toolkit-logback-1.x</artifactId>
    <version>8.5.0</version>
</dependency>
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
    <version>2.5.6</version>
</dependency>

2.yml配置文件DB配置

spring:
  cloud:
  #配置数据源
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource 
    driver-class-name: com.mysql.cj.jdbc.Driver    
    url: jdbc:mysql://localhost:3306/qns_bms_bill?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&rewriteBatchedStatements=true
    username: root
    password: root

3.实体类、mapper、mapper.xml通过Generator自动生成

public void run() {
    Properties props = this.getProperties();
    AutoGenerator mpg = new AutoGenerator();
    GlobalConfig gc = new GlobalConfig();
    String outputDir = this.getOutputDir();
    String author = props.getProperty(“author”);
    gc.setOutputDir(outputDir);
    gc.setAuthor(author);
    gc.setFileOverride(true);
    gc.setOpen(false);
    gc.setActiveRecord(false);
    gc.setEnableCache(false);
    gc.setBaseResultMap(true);
    gc.setBaseColumnList(true);
    gc.setMapperName(“%sMapper”);
    gc.setXmlName(“%sMapper”);
    gc.setServiceName(“%sService”);
    gc.setServiceImplName(“%sServiceImpl”);
    gc.setControllerName(“%sController”);
    gc.setSwagger2(this.isSwagger2);
    //定义生成的实体类中日期类型
    gc.setDateType(DateType./ONLY_DATE/);
    mpg.setGlobalConfig(gc);
    DataSourceConfig dsc = new DataSourceConfig();
    String driverName = Func./toStr/(this.driverName, props.getProperty(“spring.datasource.driver-class-name”));
    if (StringUtil./containsAny/(driverName, new CharSequence[]{DbType./MYSQL/.getDb()})) {
        dsc.setDbType(DbType./MYSQL/);
        dsc.setTypeConvert(new MySqlTypeConvert());
    } else if (StringUtil./containsAny/(driverName, new CharSequence[]{DbType./POSTGRE_SQL/.getDb()})) {
        dsc.setDbType(DbType./POSTGRE_SQL/);
        dsc.setTypeConvert(new PostgreSqlTypeConvert());
    } else {
        dsc.setDbType(DbType./ORACLE/);
        dsc.setTypeConvert(new OracleTypeConvert());
    }

    dsc.setDriverName(driverName);
    dsc.setUrl(Func./toStr/(this.url, props.getProperty(“spring.datasource.url”)));
    dsc.setUsername(Func./toStr/(this.username, props.getProperty(“spring.datasource.username”)));
    dsc.setPassword(Func./toStr/(this.password, props.getProperty(“spring.datasource.password”)));
    mpg.setDataSource(dsc);
    StrategyConfig strategy = new StrategyConfig();
    strategy.setNaming(NamingStrategy./underline_to_camel/);
    strategy.setColumnNaming(NamingStrategy./underline_to_camel/);
    strategy.setTablePrefix(this.tablePrefix);
    if (this.includeTables.length > 0) {
        strategy.setInclude(this.includeTables);
    }

    if (this.excludeTables.length > 0) {
        strategy.setExclude(this.excludeTables);
    }

    if (this.hasSuperEntity) {
        if (StringUtil./isNotBlank/(this.superEntityClass)) {
            strategy.setSuperEntityClass(this.superEntityClass);
        } else {
            strategy.setSuperEntityClass(“org.springblade.core.mp.base.BaseEntity”);
        }
        strategy.setSuperEntityColumns(this.superEntityColumns);
        if (StringUtil./isNotBlank/(this.superServiceClass)) {
            strategy.setSuperServiceClass(this.superServiceClass);
        } else {
            strategy.setSuperServiceClass(“org.springblade.core.mp.base.BaseService”);
        }
        if (StringUtil./isNotBlank/(this.superServiceImplClass)) {
            strategy.setSuperServiceImplClass(this.superServiceImplClass);
        } else {
            strategy.setSuperServiceImplClass(“org.springblade.core.mp.base.BaseServiceImpl”);
        }
    } else {
        if (StringUtil./isNotBlank/(this.superServiceClass)) {
            strategy.setSuperServiceClass(this.superServiceClass);
        } else {
            strategy.setSuperServiceClass(“com.baomidou.mybatisplus.extension.service.IService”);
        }
        if (StringUtil./isNotBlank/(this.superServiceImplClass)) {
            strategy.setSuperServiceImplClass(this.superServiceImplClass);
        } else {
            strategy.setSuperServiceImplClass(“com.baomidou.mybatisplus.extension.service.impl.ServiceImpl”);
        }

    }

    strategy.setSuperControllerClass(“org.springblade.core.boot.ctrl.BladeController”);
    strategy.setEntityBuilderModel(false);
    strategy.setEntityLombokModel(true);
    strategy.setControllerMappingHyphenStyle(true);
    mpg.setStrategy(strategy);
    PackageConfig pc = new PackageConfig();
    pc.setModuleName((String) null);
    pc.setParent(this.packageName);
    pc.setController(“controller”);
    pc.setEntity(“entity”);
    pc.setXml(“mapper”);
    mpg.setPackageInfo(pc);
    mpg.setCfg(this.getInjectionConfig());
    mpg.execute();
}

Dao层,mapper接口

//**/
/ */
/ *//
public interface SupplierBillStatementMapper extends MyBaseMapper<SupplierBillStatement> {

	//**/
/	 * 自定义分页/
/	 */
/	 */*@param*/page/
/	 */*@param*/supplierBillStatementDTO/
/	 */*@return*
/*//
IPage<SupplierBillStatementVO> selectSupplierBillStatementPage(@Param(“page”) IPage page, @Param(“dto”) SupplierBillStatementDTO supplierBillStatementDTO);
}

D2856A55-315F-4E30-A01B-5194AE40DE6C.png

注意:正常mapper继承的是BaseMapper ,所有的crud已经在BaseMapper里面简单实现,但是批量添加、更新还是没有去实现,所以在BaseMapper的基础上在封装了一层MyBaseMapper

F94C6739-DD73-44DD-A62A-C176BC0049B3.png

3F067BF4-0F54-444C-80F5-1876C53CF199.png

我们的service实现类会去继承BaseServiceImpl,里面会去继承BaseMapper 封装批量添加、更新方法,但是在service层其实我们去调用dao层这样的写法更加规范,所以我在dao层去做基础封装。

public interface MyBaseMapper<T> extends BaseMapper<T> {

    default QueryChainWrapper<T> queryChain() {
        return new QueryChainWrapper<>(this);
    }

    default LambdaQueryChainWrapper<T> lambdaQueryChain() {
        return new LambdaQueryChainWrapper<>(this);
    }

    default UpdateChainWrapper<T> updateChain() {
        return new UpdateChainWrapper<>(this);
    }

    default LambdaUpdateChainWrapper<T> lambdaUpdateChain() {
        return new LambdaUpdateChainWrapper<>(this);
    }


    //**/
/     * 批量插入/
/     */
/     */*@param*/entityList/
/     */*@return*
/*//
int insertBatchSomeColumn(List<T> entityList);


    //**/
/     * 批量更新/
/     */
/     */*@param*/entity/
/     */*@return*
/*//
int alwaysUpdateSomeColumnById(@Param(Constants./ENTITY/) List<T> entity);


    //**/
/     * 批量删除/
/     */
/     */*@param*/entity/
/     */*@return*
/*//
int deleteByIdWithFill(T entity);

    //**/
/     */*@param*/id/
/     */*@return*
/*//
T findOne(Serializable id);

}

MybatisPlusConfig分页配置

@Configuration
public class MybatisPlusConfig {


    //**/
/     * 分页插件拦截器/
/     *//
@Bean
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }

    //**/
/     * 自定义Sql注入器/
/     *//

@Bean
    public MySqlInjector sqlInjector() {
        return new MySqlInjector();
    }

}

同时mapper返回的resulType对象也需要IPage类去接收,实现自动分页。

63583A89-BDA4-43D1-ADE1-B774C5081F8B.png

4:、Wrappers 、lambdaQuery构造器的使用

A64835CA-0A10-4CBB-8D2A-28D52BBDD9C9.png

BBFC2E20-020A-4D79-A9D1-6D10F972AFF5.png

FD19EA97-2CFF-471C-B84D-05955A77B92F.png 实现Compare查询条件接口,接口方法对应mysql的查询拼接条件,可以使用 Lambda 语法使用 Wrapper,直接使用Wrapper构造器完成sql的编写在代码层解决问题,避免手写sql出现的错误。

启动类会去扫描mapper文件目录

@SpringCloudApplication
@MapperScan({“com.xxx.**.mapper.**”})
public class xxxApplication {

	public static void main(String[] args) {
		String appName = “xxxx”;
		if(args.length>0){
			for (String arg:args){
				if (arg.contains(“xxxxx=“)){
					appName = arg.replace(xxxxx=“,””).trim();
					break;
				}
			}
		}
		BladeApplication./run/(appName, xxxApplication.class, args);
	}

}

结果调用

创建controller入口调用

//**/
/ * 自定义分页 供应商账单表/
/ *//
@PostMapping(“/page”)
@ApiOperationSupport(order = 1)
@ApiOperation(value = “自定义分页”, notes = “传入supplierBillStatementDTO”)
public R<IPage<SupplierBillStatementVO>> page(@RequestBody SupplierBillStatementDTO supplierBillStatementDTO) {
    /log/.info(“自定义分页 【入参】 page supplierBillStatementDTO={},query={}”, JSON./toJSONString/(supplierBillStatementDTO));
    return R./data/(supplierBillStatementService.selectSupplierBillStatementPage(supplierBillStatementDTO, this.getCurrentUser(true)));
}

45E643CB-E5D9-4EF4-AA2F-B61FCF13072A.png 通过swagger调用controller暴露接口,返回查询结果。

总结

以上介绍的就是通过MyBatis-Plus快速进行curd开发的过程,这个过程我们基本都可以通过代码生成,可以大大增加我们的开发效率,使我们能拥有更多的时间去专注于service层业务逻辑的开发,当然框架底层的实现也是值得我们去深入研究的,我们不光得会用还要只其原理,更加充实我们的武器库,加油吧,骚年~