SpringBoot入門チュートリアル-Mybatis-Plusの統合

前書き

プラス-MyBatis(略称MP)はMyBatis 拡張ツールであり、  MyBatisに基づいて変更するだけでなく、開発を簡素化し、効率と健全性を向上させるために拡張されています。

ビジョン

私たちのビジョンは 、ベースとフレンドの組み合わせであるContraの1P、2Pのように、効率を2倍にするMyBatisの最高のパートナーになる ことです。

特徴

  • 侵入なし:強化するだけで変更はありません。導入しても既存のプロジェクトには影響しません。シルクのように滑らかです。
  • 低損失:基本的なCURDは起動時に自動的に注入され、パフォーマンスは基本的に損失なし、直接オブジェクト指向操作です
  • 強力なCRUD操作:組み込みの一般的なマッパー、一般的なサービス、わずかな構成で単一のテーブルのほとんどのCRUD操作を実現でき、さまざまな使用要件を満たすためのより強力な条件ビルダー
  • Lambdaフォーム呼び出しのサポート:Lambda式を使用すると、あらゆる種類のクエリ条件を簡単に記述でき、間違ったフィールドを書き込むことを心配する必要はありません。
  • 複数のデータベースをサポート:MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer2005、SQLServerおよびその他のデータベースをサポート
  • 自動主キー生成をサポート:最大4つの主キー戦略(分散一意IDジェネレーター-シーケンスを含む)をサポートします。これは自由に構成でき、主キーの問題を完全に解決します。
  • XMLホットリロードのサポート:マッパーに対応するXMLはホットリロードをサポートします。単純なCRUD操作の場合、XMLなしで開始することもできます。
  • ActiveRecordモードのサポート:ActiveRecordフォーム呼び出しをサポートします。エンティティクラスは、強力なCRUD操作を実行するためにModelクラスを継承するだけで済みます。
  • カスタムグローバル一般操作のサポート:グローバル一般メソッドインジェクションのサポート(1回書き込み、どこでも使用)
  • キーワード自動エスケープのサポート:データベースキーワード(順序、キー...)の自動エスケープをサポートし、キーワードをカスタマイズできます
  • 組み込みのコードジェネレーター:コードまたはMavenプラグインを使用して、マッパー、モデル、サービス、コントローラーレイヤーコード、サポートテンプレートエンジン、および使用するその他のカスタム構成をすばやく生成します
  • 組み込みのページングプラグイン:MyBatisの物理ページングに基づいているため、開発者は特定の操作を気にする必要がありません。プラグインを構成した後、ページングを作成することは通常のリストクエリと同等です。
  • 組み込みのパフォーマンス分析プラグイン:SQLステートメントとその実行時間を出力できます。開発およびテスト中にこの関数を有効にして、遅いクエリをすばやく検出することをお勧めします。
  • 組み込みのグローバルインターセプトプラグイン:テーブル全体の削除および更新操作のインテリジェントな分析とブロックを提供し、インターセプトルールをカスタマイズして誤操作を防ぐこともできます
  • 組み込みのSQLインジェクションストリッパー:SQLインジェクションストリッピングをサポートし、SQLインジェクション攻撃を効果的に防止します

フレーム構造

フレームワーク

 上記のコンテンツはMybatis-Plusの公式ウェブサイトからのものです。コンテンツは非常に詳細です。多くのトラバーサルを提供し、それを学習します。以下は私の学習プロセスの記録です。

最初にMavenの依存関係を投稿します。

<dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.0.3</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.46</version>
        </dependency>
        
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.2.2</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.2.2</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <scope>provided</scope>
        </dependency>
       
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.7</version>
        </dependency>


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.28</version>
        </dependency>
        <!-- 模板引擎 -->
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity-engine-core</artifactId>
            <version>2.0</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.0.9</version>
        </dependency>
        <dependency>
            <groupId>org.codehaus.jackson</groupId>
            <artifactId>jackson-mapper-asl</artifactId>
            <version>1.5.0</version>
        </dependency>

ここに、swagger、fastjson、jackson、freemarker、velocity、lombokなど、後で使用する依存関係を追加しました。もちろん、最も重要なのはmybatis-plus-boot-starter、ここで使用されるバージョン3.0.3です。それは比較的新しいです。導入後は、mybatisの依存関係を追加する必要はありません。

application.propertiesに追加するデータソースを構成します

spring.datasource.url=jdbc:mysql://localhost:3306/exchange?useUnicode=true&characterEncoding=gbk&useSSL=false&serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

データソース構成クラスを追加します。

@Configuration
public class MybatisConfig {
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource druidDataSource() {
        return new DruidDataSource();
    }

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

}

MPのコード生成機能を使用します。

コードジェネレータークラスを作成します。

package com.elens.data.rbces.mybatis;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;

/**
 * @BelongsProject: rbc-es
 * @BelongsPackage: com.elens.data.rbces.mybatis
 * @Author: xuweichao
 * @CreateTime: 2019-04-10 17:08
 * @Description: 代码生成
 */
public class MysqlGenerator {
    private static String projectPath = System.getProperty("user.dir");
    //父包路径
    private static String parentPackageName = "com.elens.data.rbces";
    //作者名字
    private static String authorName = "xuweichao";

    /**
     * 全局设置
     *
     * @return
     */
    public static GlobalConfig globalConfig() {

        GlobalConfig globalConfig = new GlobalConfig();
        globalConfig.setOutputDir(projectPath + "/src/main/java")
                // 是否支持 AR
                .setActiveRecord(true)
                //设置作者名字
                .setAuthor(authorName)
                //文件覆盖(全新文件)
                .setFileOverride(true)
                //主键策略
                .setIdType(IdType.AUTO)
                //SQL 映射文件
                .setBaseResultMap(true)
                //SQL 片段
                .setBaseColumnList(true)
                .setSwagger2(true)
                .setEnableCache(false)
                .setOpen(false)
                //时间类型
                .setDateType(DateType.ONLY_DATE)
                .setEnableCache(false)
        ;
        return globalConfig;
    }

    /**
     * 数据源配置
     *
     * @return
     */
    public static DataSourceConfig dataSourceConfig() {
        DataSourceConfig dataSourceConfig = new DataSourceConfig();
        ResourceBundle rootResource = ResourceBundle.getBundle("application");
        String url = rootResource.getString("spring.datasource.url");
        String username = rootResource.getString("spring.datasource.username");
        String password = rootResource.getString("spring.datasource.password");
        String driverClassName = rootResource.getString("spring.datasource.driver-class-name");

        dataSourceConfig
                .setDbType(DbType.MYSQL)
                .setUrl(url)
                .setDriverName(driverClassName)
                .setUsername(username)
//                .setSchemaName("public")
                .setPassword(password);
        return dataSourceConfig;
    }

    /**
     * 包名相关配置
     *
     * @return
     */
    public static PackageConfig packageConfig(String moduleName) {
        PackageConfig packageConfig = new PackageConfig();
        //配置父包路径
        packageConfig.setParent(parentPackageName)
                .setMapper("mybatis.mapper")
                .setXml("mybatis.mapper")
                .setEntity("mybatis.entity")
                .setService("service")
                //会自动生成 impl,可以不设定
                .setServiceImpl("service.impl")
                .setController("controller");

        if (StringUtils.isNotEmpty(moduleName)) {
            //配置业务包路径
            packageConfig.setModuleName(moduleName);
        }

        return packageConfig;
    }

    /**
     * 配置模板
     *
     * @return
     */
    public static InjectionConfig injectionConfig(String moduleName) {
        InjectionConfig injectionConfig = new InjectionConfig() {
            //自定义属性注入:abc
            //在.ftl(或者是.vm)模板中,通过${cfg.abc}获取属性
            @Override
            public void initMap() {
//                Map<String, Object> map = new HashMap<>();
//                map.put("abc", this.getConfig().getGlobalConfig().getAuthor() + "-mp");
//                this.setMap(map);
            }
        };

        // 自定义输出配置
        List<FileOutConfig> focList = new ArrayList<>();
        // 如果模板引擎是 freemarker
        String templatePath = "/templates/mapper.xml.ftl";
        // 如果模板引擎是 velocity
        // String templatePath = "/templates/mapper.xml.vm";

        // 自定义配置会被优先输出
        focList.add(new FileOutConfig(templatePath) {
            @Override
            public String outputFile(TableInfo tableInfo) {

                if (StringUtils.isEmpty(moduleName)) {
                    // 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!!
                    return projectPath + "/src/main/java/com/elens/data/rbces/mybatis/mapper/"
                            + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
                } else {
                    return projectPath + "/src/main/java/com/elens/data/rbces/mybatis/mapper/"
                            + moduleName + "/"
                            + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
                }

            }
        });
        injectionConfig.setFileOutConfigList(focList);

        return injectionConfig;
    }

    /**
     * 生成策略配置
     *
     * @param tableName
     * @return
     */
    public static StrategyConfig strategyConfig(String moduleName, String... tableName) {
        StrategyConfig strategyConfig = new StrategyConfig();
        //设置命名规则  underline_to_camel 底线变驼峰
        strategyConfig.setNaming(NamingStrategy.underline_to_camel)
                //设置设置列命名  underline_to_camel 底线变驼峰
                .setColumnNaming(NamingStrategy.underline_to_camel)
                //设置继承类
                //.setSuperEntityClass("com.maoxs.pojo")
                //设置继承类
                //.setSuperControllerClass("com.maoxs.controller")
                //是否加入lombok
                .setEntityLombokModel(true)
                .setRestControllerStyle(true)
                .setControllerMappingHyphenStyle(true)
                //设置表名
                .setInclude(tableName)
                //设置超级列
//                .setSuperEntityColumns("id")
                //设置controller映射联字符
                .setControllerMappingHyphenStyle(true)
                //表的前缀
                .setTablePrefix(packageConfig(moduleName).getModuleName() + "_");
        return strategyConfig;
    }

    /**
     * 配置模板
     *
     * @return
     */
    public static TemplateConfig templateConfig() {
        // 配置模板
        TemplateConfig templateConfig = new TemplateConfig();

        // 配置自定义输出模板
        //指定自定义模板路径,注意不要带上.ftl/.vm, 会根据使用的模板引擎自动识别
        // templateConfig.setEntity("templates/entity2.java");
        // templateConfig.setService();
        templateConfig.setController("/templates/controller.java");

        templateConfig.setXml(null);
        return templateConfig;
    }

    public static void Generator(String moduleName, String... tableName) {
        AutoGenerator mpg = new AutoGenerator()
                .setCfg(injectionConfig(moduleName))
                .setTemplate(templateConfig())
                .setGlobalConfig(globalConfig())
                .setDataSource(dataSourceConfig())
                .setPackageInfo(packageConfig(moduleName))
                .setStrategy(strategyConfig(moduleName, tableName))
//              选择 freemarker 引擎需要指定如下加,注意 pom 依赖必须有!默认 Veloctiy
                .setTemplateEngine(new FreemarkerTemplateEngine());
        mpg.execute();
    }

    public static void main(String[] args) {
        Generator(null, new String[]{"elens_report"});
    }
}

ここにいくつかのパッケージ名があり、カスタマイズされたものは状況に応じて変更できます。

ここでは、コントローラークラスを生成するためのテンプレートを作成し、/ resources / templatesの下にcontroller.java.ftlを作成しました。

コードは次のように表示されます。

package ${package.Controller};


<#if restControllerStyle>
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.java.Log;
import org.springframework.web.bind.annotation.*;
<#else>
import org.springframework.stereotype.Controller;
</#if>
<#if superControllerClassPackage??>
import ${superControllerClassPackage};
</#if>
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.factory.annotation.Autowired;
import com.elens.data.rbces.vo.Wrapper;
import com.elens.data.rbces.vo.WrapMapper;

import com.elens.data.rbces.vo.QueryPageDto;

import ${package.Service}.${table.serviceName};
import ${package.Entity}.${entity};


/**
 *
 * @author ${author}
 * @since ${date}
 */
<#if restControllerStyle??>
@Log
@Api(value="${entity} 相关接口",tags ="${entity} 相关接口")
@RestController
<#else>
@Controller
</#if>
@RequestMapping("<#if package.ModuleName??>${package.ModuleName}</#if><#if controllerMappingHyphenStyle??>${controllerMappingHyphen}<#else>${table.entityPath}</#if>")
<#if superControllerClass??>
public class ${table.controllerName} extends ${superControllerClass} {
<#else>
public class ${table.controllerName} {
</#if>
    @Autowired
    public ${table.serviceName} ${table.entityPath}Service;


    /**
     * 分页查询数据
     *
     * @return
     */
    @ApiOperation(value = "分页查询", notes = "分页查询")
    @PostMapping("getPage")
    public Wrapper get${entity}List(@RequestBody QueryPageDto queryPageDto){
        log.info("获取的参数:===>>" + queryPageDto);

        Page<${entity}> page = new Page<>(queryPageDto.getPage(), queryPageDto.getSize());
        try{
            QueryWrapper<${entity}> queryWrapper = new QueryWrapper<>();
        <#--queryWrapper.select("user_name", "user_company");-->
        <#--queryWrapper.like("user_name", "测试");-->
        <#--queryWrapper.ne("user_company", "");-->
            ${table.entityPath}Service.pageMaps(page, queryWrapper);

            }catch(Exception e){
                e.printStackTrace();
                return WrapMapper.error();
            }
            return WrapMapper.wrap(Wrapper.SUCCESS_CODE, Wrapper.SUCCESS_MESSAGE, page);
    }

    /**
     * 添加修改
     * @param ${table.entityPath}
     * @return
     */
    @ApiOperation(value = "添加或修改", notes = "根据id添加或修改")
    @PostMapping("addUpd")
    public Wrapper ${table.entityPath}AddUpd(${entity} ${table.entityPath}){
        log.info("获取的参数:===>>" + ${table.entityPath});
            try{
                ${table.entityPath}Service.saveOrUpdate(${table.entityPath});
            }catch(Exception e){
                 e.printStackTrace();
                return WrapMapper.error();
            }
            return WrapMapper.ok();
    }



    /**
     * 根据id删除对象
     * @param id  实体ID
     */
    @ApiOperation(value = "删除", notes = "根据id删除")
    @GetMapping("del/{id}")
    public Wrapper ${table.entityPath}Delete(@PathVariable int id){
        log.info("获取的参数:===>>" + id);
            try{
                ${table.entityPath}Service.removeById(id);
            }catch(Exception e){
                e.printStackTrace();
                return WrapMapper.error();
            }
            return WrapMapper.ok();
    }

}

追加、削除、変更、およびページングクエリ機能を含みます。

MysqlGeneratorクラスを開始します。

目に見えるビルドディレクトリ

赤字のファイル名は自動生成されたファイルです。

コントローラファイルは次のとおりです。

@Log
@Api(value="ElensReport 相关接口",tags ="ElensReport 相关接口")
@RestController
@RequestMapping("elens-report")
public class ElensReportController {
    @Autowired
    public IElensReportService elensReportService;


    /**
     * 分页查询数据
     *
     * @return
     */
    @ApiOperation(value = "分页查询", notes = "分页查询")
    @PostMapping("getPage")
    public Wrapper getElensReportList(@RequestBody QueryPageDto queryPageDto){
        log.info("获取的参数:===>>" + queryPageDto);

        Page<ElensReport> page = new Page<>(queryPageDto.getPage(), queryPageDto.getSize());
        try{
            QueryWrapper<ElensReport> queryWrapper = new QueryWrapper<>();
            elensReportService.pageMaps(page, queryWrapper);

            }catch(Exception e){
                e.printStackTrace();
                return WrapMapper.error();
            }
            return WrapMapper.wrap(Wrapper.SUCCESS_CODE, Wrapper.SUCCESS_MESSAGE, page);
    }

    /**
     * 添加修改
     * @param elensReport
     * @return
     */
    @ApiOperation(value = "添加或修改", notes = "根据id添加或修改")
    @PostMapping("addUpd")
    public Wrapper elensReportAddUpd(ElensReport elensReport){
        log.info("获取的参数:===>>" + elensReport);
            try{
                elensReportService.saveOrUpdate(elensReport);
            }catch(Exception e){
                 e.printStackTrace();
                return WrapMapper.error();
            }
            return WrapMapper.ok();
    }



    /**
     * 根据id删除对象
     * @param id  实体ID
     */
    @ApiOperation(value = "删除", notes = "根据id删除")
    @GetMapping("del/{id}")
    public Wrapper elensReportDelete(@PathVariable int id){
        log.info("获取的参数:===>>" + id);
            try{
                elensReportService.removeById(id);
            }catch(Exception e){
                e.printStackTrace();
                return WrapMapper.error();
            }
            return WrapMapper.ok();
    }

}

これは、単純な追加、削除、変更、およびチェックのインターフェイスです。サービスによって呼び出されるメソッドはすべて組み込みのMPであり、必要に応じて他のメソッドもテンプレートで構成できます。

生成されたエンティティクラスは、lombok関連のアノテーションで構成されます。

@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel(value="ElensReport对象", description="")
public class ElensReport extends Model<ElensReport> {

    private static final long serialVersionUID = 1L;

    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;

    @ApiModelProperty(value = "报告名称")
    private String reportName;

    @ApiModelProperty(value = "标题")
    private String reportTitle;

    @ApiModelProperty(value = "报告内容")
    private String reportContent;

    @ApiModelProperty(value = "修改时间")
    private Date updateTime;

    private String photo;

    private String perId;

    private Date createTime;


    @Override
    protected Serializable pkVal() {
        return this.id;
    }

}
//Mapper 接口 集成BaseMapper
public interface ElensReportMapper extends BaseMapper<ElensReport> {

}

BaseMapper chakがソースコードを見ると、一般的に使用されている操作メソッドのほとんどがすでに含まれていることがわかります。

mapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.elens.data.rbces.mybatis.mapper.ElensReportMapper">

    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.elens.data.rbces.mybatis.entity.ElensReport">
        <id column="id" property="id" />
        <result column="report_name" property="reportName" />
        <result column="report_title" property="reportTitle" />
        <result column="report_content" property="reportContent" />
        <result column="update_time" property="updateTime" />
        <result column="photo" property="photo" />
        <result column="per_id" property="perId" />
        <result column="create_time" property="createTime" />
    </resultMap>

    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List">
        id, report_name, report_title, report_content, update_time, photo, per_id, create_time
    </sql>

</mapper>

サービスインターフェース:

public interface IElensReportService extends IService<ElensReport> {

}
IService 接口也是MP 自带的接口同样内置了很多常用的方法:

 

服务实现类:
@Service
public class ElensReportServiceImpl extends ServiceImpl<ElensReportMapper, ElensReport> implements IElensReportService {

}

さらに、マッパーをスキャンして挿入するには、アプリケーションのスタートアップクラスにアノテーション@mapperScanを追加する必要があります。

ここでSwaggerを構成しました。

@EnableSwagger2
@Configuration
public class SwaggerConfig {

    @Bean
    public Docket apiDoc() {
        return docket();
    }

    private Docket docket() {
        return new Docket(DocumentationType.SWAGGER_2).select()
//                .apis(RequestHandlerSelectors.withClassAnnotation(RestController.class))//这里采用包含注解的方式来确定要显示的接口
//                .apis(RequestHandlerSelectors.basePackage("com.elens.data.oauth.manager.controller"))    //这里采用包扫描的方式来确定要显示的接口
                .apis(RequestHandlerSelectors.withClassAnnotation(Api.class))
                .paths(PathSelectors.any())
                .build()
                .ignoredParameterTypes(Errors.class)
                .apiInfo(apiInfo());

    }

   private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("Swagger2 api文档")
                .description("Swagger2 api文档")
                .version("1.0.0")
                .build();

    }
}

データブラウザ入力を開始した後:

http:localhost:port/swagger-ui.html 可以看到生成的接口




このようにして、テストを直接実行できます。

もちろん、MP自体のメソッドがビジネスニーズを満たすことができない場合は、Serviceでメソッドをカスタマイズし、Mapper.xmlでMybatisの方法でSQLを記述できます。

おすすめ

転載: blog.csdn.net/qq_27828675/article/details/89307878