SpringBoot2.x整合MybatisPlus3.x,实现数据的简单CRUD操作+逆向工程代码生成

一、项目地址

GitHub地址:https://github.com/kobeyk/springboot-myabatis-plus-sample.git

 

 

二、项目结构

三、Pom整合

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.0.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.appleyk</groupId>
    <artifactId>springboot-mybatisplus-sample</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>
    <name>springboot-mybatisplus-sample</name>
    <description>SpringBoot集成MybatisPlus实现单表增删改查的例子</description>

    <properties>
        <java.version>1.8</java.version>
        <jdk.version>1.8</jdk.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <!-- 编译时的编码 -->
        <maven.compiler.encoding>UTF-8</maven.compiler.encoding>
        <jackson.version>2.9.8</jackson.version>
        <postgresql.version>42.1.4</postgresql.version>
        <mybatisplus.version>3.2.0</mybatisplus.version>
        <velocity.version>1.7</velocity.version>
        <skipTests>true</skipTests>
    </properties>

    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--这玩意虽然省事,但是有利有弊吧,注意idea要安装对应的插件-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-boot-starter -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>${mybatisplus.version}</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-generator -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>${mybatisplus.version}</version>
        </dependency>

        <!-- postgresql -->
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <version>${postgresql.version}</version>
        </dependency>

        <!-- jackson -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>${jackson.version}</version>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>${jackson.version}</version>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>${jackson.version}</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.apache.velocity/velocity -->
        <!--一定要有这个玩意,模板,否则mybatisplus逆向工程生成代码找不到模板-->
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity</artifactId>
            <version>${velocity.version}</version>
        </dependency>

    </dependencies>

    <build>
        <finalName>${project.artifactId}</finalName>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
            </resource>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.3</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

四、application.properties配置


server.port=8080
logging.level.com.appleyk.dao.mapper = debug

#hikari
spring.datasource.hikari.driver-class-name=org.postgresql.Driver
spring.datasource.hikari.jdbc-url=jdbc:postgresql://localhost:5432/injection_db?stringtype=unspecified
spring.datasource.hikari.username=postgres
spring.datasource.hikari.password=postgres
spring.datasource.templateType=com.zaxxer.hikari.HikariDataSource
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.maximum-pool-size=15
spring.datasource.hikari.auto-commit=true
spring.datasource.hikari.idle-timeout=30000
spring.datasource.hikari.pool-name=DatebookHikariCP
spring.datasource.hikari.max-lifetime=1800000
spring.datasource.hikari.connection-timeout=30000
spring.datasource.hikari.connection-test-query=SELECT 1

五、自定义数据源,注入相应bean

package com.appleyk.config;

import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import com.zaxxer.hikari.HikariDataSource;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;


/**
 * <p>自定义数据源配置</p>
 *
 * @author Appleyk
 * @version V.0.1.1
 * @blob https://blog.csdn.net/Appleyk
 * @date created on 14:01 2020/2/26
 */
@EnableTransactionManagement
@MapperScan(value = {"com.appleyk.dao.mapper"}, sqlSessionTemplateRef  = "sqlSessionTemplate")
@Configuration
public class TDataSourceConfig {

    @Primary
    @Bean(name = "dataSource")
    @ConfigurationProperties(prefix = "spring.datasource.hikari") //需要导入配置
    public HikariDataSource dataSource(){
        return DataSourceBuilder.create().type(HikariDataSource.class).build();
    }

    @Bean
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }

    @Bean(name = "sqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSource") DataSource dataSource,@Qualifier("paginationInterceptor") PaginationInterceptor paginationInterceptor) throws Exception {
        /**坑1:注意这里一定要是MybatisPlus的MybatisSqlxxBean,而不是正常的SqlXXBean,否者会出现statement绑定无效*/
        MybatisSqlSessionFactoryBean bean = new MybatisSqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        /**坑2:注意,一定要设置 MyBatis-Plus的分页插件,否者分页结果无效*/
        Interceptor[] plugins = {paginationInterceptor};
        bean.setPlugins(plugins);
        return bean.getObject();
    }

    @Bean(name = "transactionManager")
    public DataSourceTransactionManager transactionManager(@Qualifier("dataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean(name = "sqlSessionTemplate")
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier("sqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory);
    }

}

注意坑1: 如果配置成了SqlSessionFactoryBean,会提示

{
    "timestamp": 1582787261756,
    "status": 500,
    "error": "Internal Server Error",
    "message": "Invalid bound statement (not found):   com.appleyk.dao.mapper.TUserMapper.selectPage",
    "path": "/user/query"
}

注意坑2: 如果没有为MybatisPlus设置分页插件,则基于分页查询的结果会有问题

六、MybatisPlus逆向工程生产代码

package com.appleyk.config;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;

/**
 * <p>
 *
 *    自动代码生成器(myabtisplus逆向工程),本项目中controller、service、dao均是自动生成的
 *    注意: 由于代码已经生成,但是配置里面设置的重新生成会覆盖之前的文件,因此,博主已经把它改成false了
 *    .setFileOverride(true)  ====》 .setFileOverride(false)
 *
 * </p>
 *
 * @author Appleyk
 * @version V.0.1.1
 * @blob https://blog.csdn.net/Appleyk
 * @date created on 14:01 2020/2/26
 */
public class TCodeGenerator {

    /**项目存储位置*/
    public static String PROJECT_GENERATE_DISK = System.getProperty("user.dir")+"/src/main/java";
    /**数据库地址*/
    public static String DB_URL = "jdbc:postgresql://localhost:5432/injection_db?stringtype=unspecified";
    /**数据库驱动名*/
    public static String DRIVER_CLASS_NAME = "org.postgresql.Driver";
    /**数据库类型*/
    public static String DB_TYPE = DbType.POSTGRE_SQL.name();
    /**数据库用户*/
    public static String USER = "postgres";
    /**数据库密码*/
    public static String PASSWORD = "postgres";
    /**参与逆向工程的表名**/
    public static String[] INCLUDE_TABLE_NAMES = new String[]{"t_user","t_user_info"};
    /**不参与逆向工程的表名**/
    public static String[] EXCLUDE_TABLE_NAMES = new String[]{"spatial_ref_sys"};
    /**创建人*/
    public static String AUTHOR = "Appleyk";
    /**表字段生成对应的实体类时,字段属性是否需要强制带上注解*/
    public static boolean ENABLE_TABLE_FIELD_ANNOTATION = false;
    /**表id,用哪一种生成策略,如下面用的是分布式全局唯一ID,是不是分布式暂时没考就哈*/
    public static IdType TABLE_ID_TYPE = IdType.ID_WORKER;
    /**是否去掉生成实体的属性名前缀,如表有t_table1,m_table2,则这个值可以为 = new String[]{"t","m"}*/
    public static String[] FIELD_PREFIX = null;

    /**
     * 全局配置
     * @return
     */
    private static GlobalConfig GlobalGenerate(){
        GlobalConfig config = new GlobalConfig();
        /*不需要ActiveRecord特性的请改为false*/
        config.setActiveRecord(false)
                .setIdType(TABLE_ID_TYPE)
                /*是否启用二级缓存*/
                .setEnableCache(false)
                /*设置作者*/
                .setAuthor(AUTHOR)
                /*生成完之后,不弹窗,告知我在生成在哪个目录了*/
                .setOpen(false)
                /*XML 设置映射结果 ResultMap*/
                .setBaseResultMap(true)
                /*XML 设置表列 ColumnList*/
                .setBaseColumnList(true)
                /*设置生产的文件(包)在哪,一般是相对于本项目而言*/
                .setOutputDir(PROJECT_GENERATE_DISK)
                /*每次生成,是否覆盖之前的文件(慎重考虑啊)*/
                .setFileOverride(false)
                /*自定义文件命名,注意 %s 会自动填充表实体属性!*/
                .setControllerName("%sController")
                .setServiceName("%sService")
                .setServiceImplName("%sServiceImpl")
                .setMapperName("%sMapper")
                .setXmlName("%sMapper");
        return config;
    }

    /**
     * 数据源配置
     * @return
     */
    private static DataSourceConfig DaoSourceGenerate(){
        DataSourceConfig dataSourceConfig = new DataSourceConfig();
        DbType type=null;
        if("oracle".equals(DB_TYPE)){
            type=DbType.ORACLE;
        }else if("sql_server".equals(DB_TYPE)){
            type=DbType.SQL_SERVER;
        }else if("mysql".equals(DB_TYPE)){
            type=DbType.MYSQL;
        }else if("postgre_sql".equals(DB_TYPE)){
            type=DbType.POSTGRE_SQL;
        }
        /*设置数据库类型*/
        dataSourceConfig.setDbType(type)
                /*设置数据库驱动(反射,基于类名,找到对应的类)*/
                .setDriverName(TCodeGenerator.DRIVER_CLASS_NAME)
                /*设置数据库连接地址,地址包含库ip、端口、库名等*/
                .setUrl(DB_URL)
                /*设置数据库用户名*/
                .setUsername(TCodeGenerator.USER)
                /*设置数据库密码*/
                .setPassword(TCodeGenerator.PASSWORD);
        return dataSourceConfig;
    }

    /**
     * 策略配置
     * @return
     */
    private static StrategyConfig StrategyGenerate() {
        StrategyConfig strategyConfig = new StrategyConfig();
        strategyConfig
                .setVersionFieldName("version")
                /*全局大写命名 ORACLE 注意*/
                .setCapitalMode(true)
                /*生成RestController*/
                .setRestControllerStyle(true)
                /*是否使用Lombok省略getter、setter*/
                .setEntityLombokModel(false)
//                .setDbColumnUnderline(true)
                /*表名生成策略 -- 驼峰*/
                .setNaming(NamingStrategy.underline_to_camel)
                .setEntityTableFieldAnnotationEnable(ENABLE_TABLE_FIELD_ANNOTATION)
                /* 生成指定的xxxController、、xxService等是否去掉数据库表名的前缀,如t_user -> user -> UserController*/
                .setFieldPrefix(FIELD_PREFIX)
                /*设置哪些表参与逆向工程,多个表名传数组*/
                .setInclude(INCLUDE_TABLE_NAMES)
                /*设置哪些表不参与逆向工程,多个表名传数组;注意,不能和Include一起使用*/
//                .setExclude(EXCLUDE_TABLE_NAMES)
                /*此处可以修改为您的表前缀*/
                .setTablePrefix(null)
                /*自定义实体,公共字段*/
                .setSuperEntityColumns(null)
                /*自定义 mapper 父类*/
                .setSuperMapperClass(null)
                /*自定义 service 父类*/
                .setSuperServiceClass(null)
                /*自定义 serviceImpl 父类*/
                .setSuperServiceImplClass(null)
                /*自定义 controller 父类*/
                .setSuperControllerClass(null)
                /*【实体】是否生成字段常量(默认 false)public static final String ID = "test_id";*/
                .setEntityColumnConstant(false)//
                /*【实体】是否为构建者模型(默认 false)public User setName(String name) {this.name = name; return this;}*/
                .setEntityBuilderModel(false)
                /*【实体】是否为lombok模型(默认 false)*/
                .setEntityLombokModel(false)
                /*Boolean类型字段是否移除is前缀处理*/
                .setEntityBooleanColumnRemoveIsPrefix(true);
        return strategyConfig;
    }

    /**
     * 自定义模板配置
     * @return
     */
    private static TemplateConfig TemplateGenerate(){
        TemplateConfig templateConfig = new TemplateConfig()
                .setController("/templates/controller.java")
                .setMapper("/templates/mapper.java")
                .setXml("/templates/mapper.xml")
                .setService("/templates/service.java")
                .setServiceImpl("/templates/serviceImpl.java");
        return templateConfig;
    }

    public static PackageConfig PackageGenerate(){
        PackageConfig pc = new PackageConfig()
                .setParent("com.appleyk")
                .setController("controller")
                .setService("service")
                .setServiceImpl("service.impl")
                .setEntity("dao.entity")
                .setMapper("dao.mapper")
                .setXml("dao.mapper");
        return pc;
    }

    public void generateByTablesWithInjectConfig() {
        //全局配置
        GlobalConfig config =TCodeGenerator.GlobalGenerate();
        //配置数据源
        DataSourceConfig dataSourceConfig=TCodeGenerator.DaoSourceGenerate();
        //配置策略
        StrategyConfig strategyConfig = TCodeGenerator.StrategyGenerate();
        //配置包
        PackageConfig packageConfig=TCodeGenerator.PackageGenerate();
        //生成代码
        new AutoGenerator()
                .setGlobalConfig(config)
                .setDataSource(dataSourceConfig)
                .setStrategy(strategyConfig)
                .setPackageInfo(packageConfig)
                .execute();
    }

    public static void main(String[] args) {
        TCodeGenerator generatorServiceEntity=new TCodeGenerator();
        generatorServiceEntity.generateByTablesWithInjectConfig();
    }

}

七、分页查询演示

项目启动:

Service:

@Service
public class TUserServiceImpl extends ServiceImpl<TUserMapper, TUser> implements TUserService {

    @Autowired
    private TUserMapper userMapper;

    @Override
    public IPage<TUser> find(){
        Page<TUser> page = new Page<>(1,20);
        return userMapper.selectPage(page,null);
    }

}

Mapper:

public interface TUserMapper extends BaseMapper<TUser> {

}

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.appleyk.dao.mapper.TUserMapper">

    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.appleyk.dao.entity.TUser">
        <id column="id" property="id" />
        <result column="name" property="name" />
        <result column="password" property="password" />
        <result column="create_time" property="createTime" />
    </resultMap>

    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List">
        id, name, password, create_time
    </sql>

</mapper>

Controller:

@RestController
@RequestMapping("/user")
public class TUserController {

    @Autowired
    private TUserService userService;

    /**
     * 分页查询
     * @return
     */
    @GetMapping("/query")
    public TResult query(){
        return TResult.ok(userService.find());
    }
}

PostMan测试:

{
    "status": 200,
    "message": "成功!",
    "data": {
        "records": [
            {
                "id": "111",
                "name": "appelyk",
                "password": "11111",
                "createTime": 1582791338107
            },
            {
                "id": "1232679405023793154",
                "name": "appelyk",
                "password": "123456a",
                "createTime": 1582791338108
            },
            {
                "id": "1232680020835762177",
                "name": "appelyk",
                "password": "123456a",
                "createTime": 1582791338108
            },
            {
                "id": "1232680432896749569",
                "name": "appelyk",
                "password": "123456a",
                "createTime": 1582646400000
            },
            {
                "id": "1232680817808056322",
                "name": "appelyk",
                "password": "123456a",
                "createTime": 1582646400000
            },
            {
                "id": "1232681928061243393",
                "name": "appelyk",
                "password": "123456a",
                "createTime": 1582646400000
            },
            {
                "id": "1232684931182948354",
                "name": "kobe",
                "password": "123456a",
                "createTime": 1582646400000
            },
            {
                "id": "1232687920962592770",
                "name": "kobe",
                "password": "123456a",
                "createTime": 1582646400000
            }
        ],
        "total": "8",
        "size": "20",
        "current": "1",
        "orders": [],
        "searchCount": true,
        "pages": "1"
    },
    "timeStamp": "2020-02-27 16:15:38"
}

八,逆向工程演示

(1)数据库增加一张表,t_test,字段如下

(2)代码中,include_tables中加上这个表的名称

(3)执行

(4)验证生成的文件是否存在

(5)我们看下,自动生成的mapper默认都具有哪些数据操作方法

(6)我们看下,自动生成的service默认都具有哪些数据操作方法

九,小结

             至于MybatisPlus是否足够出色,还需要我们研发人员在用的过程中,不断的去体验,去感受!

发布了208 篇原创文章 · 获赞 645 · 访问量 212万+

猜你喜欢

转载自blog.csdn.net/Appleyk/article/details/104534480