美文网首页MyBatis Plus专题
210904:Mybatis-Plus的实体类注解/多数据源配置

210904:Mybatis-Plus的实体类注解/多数据源配置

作者: 弹钢琴的崽崽 | 来源:发表于2021-09-04 18:29 被阅读0次

    一. Mybatis-Plus的实体类注解

    1. @TableName注解

    @TableName(value = …)

    当数据库名与实体类名不一致或不符合驼峰命名时,需要在此注解指定表名

    @TableId(type = …)

    指定实体类的属性为对应的主键,主要有以下几种:

    // 数据库ID自增
    IdType.AUTO
    // 该类型为未设置主键类型(默认)
    IdType.NONE 
    /**
     * 用户输入ID
     * <p>该类型可以通过自己注册自动填充插件进行填充</p>
     */
    IdType.INPUT
    /* 以下3种类型、只有当插入对象ID 为空,才自动填充。 */
    //1.全局唯一ID (idWorker)
    IdType.ID_WORKER
    //2.全局唯一ID (UUID)
    IdType.UUID
    //3.字符串全局唯一ID (idWorker 的字符串表示)
    IdType.ID_WORKER_STR
    

    2. @TableField注解

    1. 主要用来解决实体类的字段名与数据库中的字段名不匹配的问题(数据库user_addr,字段useraddr未驼峰)
    2. 实体类中的属性字段在表中不存在的问题
    // 用来解决数据库中的字段和实体类的字段不匹配问题
    @TableField(value = "age")
    // 用来解决实体类中有的属性但是数据表中没有的字段
    @TableField(exist = false)  // 默认为true
    

    二. Navicat v15激活步骤

    navicat15安装完后别着急打开

    1. 运行Navicat Keygen Patch v5.6.0 DFoX.exe

    2. 点击Generate按钮就会生成一个许可证秘钥,将许可证秘钥复制后就打开Navicat Premium 15

    3. 打开Navicat Premium 15,点击注册

    4. 粘贴秘钥,然后点击激活按钮

    5. 在弹出的界面选择手动激活

    6. 将请求码粘贴到注册机Request Code框中

    7. 点击激活页面的激活弹出(说明激活成功)

    三. 服务部署到docker后,查看信息

    1. 查看日志信息

    docker logs -tf --tail 10 容器ID
    

    2. 查看服务的配置文件

    2.1 列出在运行的容器

    docker ps
    

    2.2 进入该容器

    docker exec -it 容器ID /bin/bash
    

    2.3 找到配置文件后进行修改查看

    四. Mybatis-plus多数据源配置

    1. 环境准备

    1.1 数据库相关

    以 mysql 为例进行演示说明,因为需要多数据源,一个最简单的 case 就是一个物理库上多个逻辑库,本文是基于本机的 mysql 进行操作

    创建数据库teststory,两个库下都存在一个表money (同名同结构表,但是数据不同哦)

    CREATE TABLE `money` (
      `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
      `name` varchar(20) NOT NULL DEFAULT '' COMMENT '用户名',
      `money` int(26) NOT NULL DEFAULT '0' COMMENT '钱',
      `is_deleted` tinyint(1) NOT NULL DEFAULT '0',
      `create_at` date NOT NULL  COMMENT '创建时间',
      `update_at` date NOT NULL  COMMENT '更新时间',
      PRIMARY KEY (`id`),
      KEY `name` (`name`)
    ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
    

    1.2 项目环境

    本项目借助SpringBoot 2.2.1.RELEASE + maven 3.5.3 + IDEA进行开发

    下面是核心的pom.xml

    <dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
    
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
            <version>3.3.1</version>
        </dependency>
    
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.3.1</version>
        </dependency>
    </dependencies>
    

    配置文件信息application.yml,请注意下面的写法格式,如有疑问可以参考官方教程

    spring:
      datasource:
        dynamic:
          primary: story #设置默认的数据源或者数据源组,默认值即为master
          strict: false  #设置严格模式,默认false不启动. 启动后在未匹配到指定数据源时候会抛出异常,不启动则使用默认数据源.
          datasource:
            story:
              driver-class-name: com.mysql.cj.jdbc.Driver
              url: jdbc:mysql://127.0.0.1:3306/story?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
              username: root
              password:
            test:
              driver-class-name: com.mysql.cj.jdbc.Driver
              url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
              username: root
              password:
    

    2. 项目演示

    2.1 实体类

    mybatis-plus 可以借助插件实现自动生成相应的代码,我们这里简单自主实现测试 demo,因为两个数据库中表结构完全一致,所以只需要一个 Entity

    @Data
    @Accessors(chain = true)
    @TableName(value = "money")
    public class MoneyPo {
        /**
         * 指定自增策略
         */
        @TableId(value = "id", type = IdType.AUTO)
        private Integer id;
    
        private String name;
    
        private Long money;
    
        @TableField("is_deleted")
        private Integer isDeleted;
    
        @TableField(value = "create_at")
        private Date createAt;
    
        @TableField(value = "update_at")
        private Date updateAt;
    }
    

    2.2 Mapper 接口

    数据库操作定义接口MoneyMapper

    public interface MoneyMapper extends BaseMapper<MoneyPo> {
    }
    

    对应的 xml 文件resources/mapper/money-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.ruangh.mybatisplus.datasouce.mybatisplusdatasouce.mapper.MoneyMapper">
    </mapper>
    

    2.3 Service 接口与实现

    因为两张表,所以我们可以定义一个接口,两个不同的实现

    public interface MoneyService extends IService<MoneyPo> {
    }
    
    @Service
    @DS("story")
    public class StoryMoneyServiceImpl extends ServiceImpl<MoneyMapper, MoneyPo> implements MoneyService {
    }
    
    @Service
    @DS("test")
    public class TestMoneyServiceImpl extends ServiceImpl<MoneyMapper, MoneyPo> implements MoneyService {
    }
    

    请注意上面 Service 的注解@DS,value 为前面数据源配置文件中的 key(spring.datasource.dynamic.datasource下面的story + test)

    这个注解可以放在类上也可以放在方法上,方法上的优先级 > 类,所以上面的两个 Service 实现可以改成一个

    @Service
    public class MoneyServiceImpl extends ServiceImpl<MoneyMapper, MoneyPo> implements MoneyService {
    
        @DS("story")
        public List<MoneyPo> findByStoryIds(Collection<Long> ids) {
            return baseMapper.selectBatchIds(ids);
        }
    
        @DS("test")
        public List<MoneyPo> findByTestIds(Collection<Long> ids) {
            return baseMapper.selectBatchIds(ids);
        }
    }
    

    2.4 测试

    为简单起见,直接在启动类中添加写上测试代码

    ![010](E:\ruanghDoc\LearningClip\学习笔记\新能康-复盘\210904-mybatis-plus注解\010.png)@SpringBootApplication
    @MapperScan("com.ruangh.mybatisplus.datasouce.mybatisplusdatasouce.mapper")
    public class MybatisplusDatasouceApplication {
    
        public MybatisplusDatasouceApplication(TestMoneyServiceImpl testMoneyService, StoryMoneyServiceImpl storyMoneyService) {
            List<MoneyPo> moneyPoList = testMoneyService.listByIds(Arrays.asList(1, 1000));
            System.out.println(moneyPoList);
            System.out.println("--------------");
    
            moneyPoList = storyMoneyService.listByIds(Arrays.asList(1, 1000));
            System.out.println(moneyPoList);
        }
    
        public static void main(String[] args) {
            SpringApplication.run(Application.class);
        }
    }
    

    3. 遇到的坑

    可以看到启动过程中我们配置的多数据库源Start completed.之后遇到异常之后又被shutdown了。

    因为引入了多个Mybatis 的jar包引起的,检查bom.xml文件是否引入了mybatis和mybatis-plus两个依赖,如果是去掉mybatis即可。

    五. MyBatis-Plus Wrapper条件构造器筛选不必要的字段

    1. 需求

    这个MP的Wrapper默认查询是查询全部的列,但是我的需求是需要查询某几个列即可。

    2. 解决办法

    /**
         * 名字包含雨并且年龄小于40
         * <p>
         * 只显示id、name 两列
         */
    @Test
    public void selectByWrapper1() {
        QueryWrapper<User> wrapper = new QueryWrapper();
        wrapper.like("name", "雨").lt("age", 40)
            .select("id","name");
        List<User> users = userMapper.selectList(wrapper);
        users.forEach(System.out::println);
    }
    
    /**
         * 名字包含雨并且年龄小于40
         * <p>
         * 除了create_time、manager_id 其他列都显示
         */
    @Test
    public void selectByWrapper2() {
        QueryWrapper<User> wrapper = new QueryWrapper();
        wrapper.like("name", "雨").lt("age", 40)
            .select(User.class,i -> !i.getColumn().equals("create_time")
                    && !i.getColumn().equals("manager_id"));
        List<User> users = userMapper.selectList(wrapper);
        users.forEach(System.out::println);
    }
    

    六. Mybatis-Plus代码自动生成

    1. 准备

    准备两张表,用于测试

    CREATE TABLE `userT0` (
      `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
      `name` varchar(20) NOT NULL DEFAULT '' COMMENT '用户名',
      `pwd` varchar(26) NOT NULL DEFAULT '' COMMENT '密码',
      `isDeleted` tinyint(1) NOT NULL DEFAULT '0',
      `created` varchar(13) NOT NULL DEFAULT '0',
      `updated` varchar(13) NOT NULL DEFAULT '0',
      PRIMARY KEY (`id`),
      KEY `name` (`name`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
    
    CREATE TABLE `story_t0` (
      `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
      `userId` int(20) unsigned NOT NULL DEFAULT '0' COMMENT '作者的userID',
      `name` varchar(20) NOT NULL DEFAULT '' COMMENT '作者名',
      `title` varchar(26) NOT NULL DEFAULT '' COMMENT '密码',
      `story` text COMMENT '故事内容',
      `is_deleted` tinyint(1) NOT NULL DEFAULT '0',
      `create_at` varchar(13) NOT NULL DEFAULT '0',
      `update_at` varchar(13) NOT NULL DEFAULT '0',
      `tag` int(11) DEFAULT NULL,
      PRIMARY KEY (`id`),
      KEY `userId` (`userId`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
    

    请注意,上面两张表的命名格式并不一样,有的是驼峰,有的是下划线(主要为了演示不同表名,对于生成代码的影响)

    2. 配置依赖

    首先需要在我们的xml文件中,添加相关的依赖

    <dependencies>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.3.1.tmp</version>
        </dependency>
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
    
        <!-- 下面两个,用于测试生成后的代码,在生成代码时,可以不需要-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.2.0</version>
        </dependency>
    </dependencies>
    

    3. 代码生成类

    写一个代码生成类方法,主要逻辑如下

    public class CodeGenerator {
        public static void main(String[] args) {
            // 代码生成器
            AutoGenerator mpg = new AutoGenerator();
    
            // 全局配置
            GlobalConfig gc = new GlobalConfig();
            String projectPath = System.getProperty("user.dir") + "/spring-boot/106-mybatis-plus-generator";
            gc.setOutputDir(projectPath + "/src/main/java");
            gc.setAuthor("ruangh");
            gc.setOpen(false);
            // 覆盖写
            gc.setFileOverride(false);
            mpg.setGlobalConfig(gc);
    
            // 数据源配置
            DataSourceConfig dsc = new DataSourceConfig();
            dsc.setUrl("jdbc:mysql://127.0.0.1:3306/story?useSSL=false&serverTimezone=UTC");
            // dsc.setSchemaName("public");
            dsc.setDriverName("com.mysql.jdbc.Driver");
            dsc.setUsername("root");
            dsc.setPassword("123456");
            mpg.setDataSource(dsc);
    
            // 包配置
            PackageConfig pc = new PackageConfig();
            // 不额外指定模块,如果指定为 test,则生成的xml会在 mapper/test/ 目录下
            pc.setModuleName("");
            pc.setParent("com.ruangh.mybatisplus.generator");
            mpg.setPackageInfo(pc);
    
            // 自定义配置
            InjectionConfig cfg = new InjectionConfig() {
                @Override
                public void initMap() {
                    // to do nothing
                }
            };
    
            // 如果模板引擎是 freemarker
            String templatePath = "/templates/mapper.xml.ftl";
    
            // 自定义输出配置
            List<FileOutConfig> focList = new ArrayList<>();
            // 自定义配置会被优先输出
            focList.add(new FileOutConfig(templatePath) {
                @Override
                public String outputFile(TableInfo tableInfo) {
                    // 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!!
                    return projectPath + "/src/main/resources/mapper/" + pc.getModuleName() + "/" +
                            tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
                }
            });
    
            cfg.setFileOutConfigList(focList);
            mpg.setCfg(cfg);
    
            // 配置模板
            TemplateConfig templateConfig = new TemplateConfig();
            templateConfig.setXml(null);
            // 不自动生成controller类
            templateConfig.setController(null);
            mpg.setTemplate(templateConfig);
    
            // 策略配置
            StrategyConfig strategy = new StrategyConfig();
            strategy.setNaming(NamingStrategy.underline_to_camel);
            strategy.setColumnNaming(NamingStrategy.underline_to_camel);
            // strategy.setSuperEntityClass("你自己的父类实体,没有就不用设置!");
            strategy.setEntityLombokModel(true);
            strategy.setRestControllerStyle(true);
            // 公共父类
            // strategy.setSuperControllerClass("你自己的父类控制器,没有就不用设置!");
            // 写于父类中的公共字段
            // strategy.setSuperEntityColumns("id");
    
            // 设置需要生成的表名
            strategy.setInclude("userT0", "story_t0");
            strategy.setControllerMappingHyphenStyle(true);
            // strategy.setTablePrefix(pc.getModuleName() + "_");
            mpg.setStrategy(strategy);
            mpg.setTemplateEngine(new FreemarkerTemplateEngine());
            mpg.execute();
        }
    }
    

    上面的代码,绝大部分都是通用的,下面着重说明需要注意的点

    • GlobalConfig#setOutputDir: 设置代码输出的项目根路径,请根据具体的项目要求进行指定,不包含包名哦

    • GlobalConfig#setFileOverride(true)
      

      : 设置为true,则每次生成都会覆盖之前生成的代码,适用于表结构发生变化的场景

      • 注意:会导致之前添加的业务代码被覆盖掉,需要额外注意
      • 通常希望设置为false,当表结构发生变化时,手动介入
    • DataSourceConfig: 数据源的设置,上面设置的是mysql的相关配置

    • PackageConfig
      

      : 包信息

      • setParent: java包路径
      • setModuleName: 设置模块名,如设置为test,则xml在mapper/test/目录下; parent包自动加上.test
    • FileOutConfig: xml文件名

    • TemplateConfig
      

      : 模板配置

      • 可用默认的代码生成模板,也可以使用自定义的模板
      • 不想生成某个模板类时,设置为null即可(如上面的不生成controller)
    • StrategyConfig
      

      : 策略配置

      • 可以指定db->pojo字段名的映射规则
      • 可以指定POJO/Controller继承自定义的基类

    在IDEA中,直接右键执行上面的代码,就会生成目标类,如下截图

    4. 输出测试

    测试我们生成的类,是否可以对db进行操作,则有必要写一个启动类

    @RestController
    @SpringBootApplication
    @MapperScan("com.ruangh.mybatisplus.generator.mapper")
    public class Application {
        @Autowired
        private IUserT0Service userT0Service;
    
        @GetMapping
        public UserT0 hello(int id) {
            return userT0Service.getById(id);
        }
    
        public static void main(String[] args) {
            SpringApplication.run(Application.class);
        }
    }
    

    请注意上面的@MapperScan注解,其次对应的application.yml配置文件内容如下

    spring:
      datasource:
        # 注意指定时区
        url: jdbc:mysql://127.0.0.1:3306/story?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
        username: root
        password:
    
    mybatis-plus:
      configuration:
        # 执行的sql语句日志输出
        log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    

    在db中插入一条数据

    INSERT INTO `userT0` (`id`, `name`, `pwd`, `isDeleted`, `created`, `updated`)
    VALUES
    true(1, '一灰灰', 'yihuihuiblog', 0, '2020-04-06 15', '2020-04-06 15');
    

    访问url: http://localhost:8080/?id=1

    控制台输出如下:

    5. 特殊场景说明

    上面的代码生成,针对首次执行生成打码时,问题不大;但是后续的业务开发中,总会有一些其他的情况,下面分别说明

    5.1 表结构修改

    当表的结构发生变化时,我们需要一般需要重新生成对应的Entity,这个时候,需要GlobalConfig#setFileOverride(true)

    5.2 继承公用POJO

    我们可以定义一个通用的PO类,希望所有的表生成的POJO继承它

    @Data
    public class BasePo implements Serializable {
        private static final long serialVersionUID = -1136173266983480386L;
    
        @TableId(value = "id", type = IdType.AUTO)
        private Integer id;
    
    }
    

    在代码自动生成类的策略配置中,添加下面的两行设置即可

    // 所有实体类继承自 BasePo, 且id在父类中
    StrategyConfig strategy = new StrategyConfig();
    strategy.setSuperEntityClass(BasePo.class);
    strategy.setSuperEntityColumns("id");
    

    5.3 生成部分代码

    有些时候,我并不希望生成service,xml,可能就只需要实体类 + mapper接口,这个时候可以设置TemplateConfig

    TemplateConfig templateConfig = new TemplateConfig();
    templateConfig.setController(null);
    templateConfig.setEntityKt(null);
    templateConfig.setService(null);
    templateConfig.setServiceImpl(null);
    

    相关文章

      网友评论

        本文标题:210904:Mybatis-Plus的实体类注解/多数据源配置

        本文链接:https://www.haomeiwen.com/subject/yugrwltx.html