MybatisPlus

505 阅读11分钟

魂斗罗的回忆,我的小霸王学习机 ↑ ↓ ↔ BABA

简介

啰嗦描述下官方的推荐的优点
最开始使用的原因:问了一个前辈推荐的就一直再用
官网地址:mp.baomidou.com/

MyBatis 是一个半自动的 ORM 框架。MyBatis-Plus (opens new window)(简称 MP)是一个 MyBatis (opens new window)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

特性

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑

  • 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作

  • 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求

  • 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错

  • 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题

  • 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作

  • 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )

  • 内置代码生成器:采用代码或者 Maven 插件可快速生成 MapperModelServiceController 层代码,支持模板引擎,更有超多自定义配置等您来使用

  • 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询

  • 分页插件支持多种数据库:支持 MySQLMariaDBOracleDB2H2HSQLSQLitePostgreSQLServer 等多种数据库

  • 内置性能分析插件:可输出 Sql 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询

  • 内置全局拦截插件:提供全表 deleteupdate 操作智能分析阻断,也可自定义拦截规则,预防误操作

框架结构

基于 SpringBoot 使用

基本开发环境

  1. 基于 Java 开发,建议 jdk 1.8+ 版本。
  2. 需要使用到 Spring Boot
  3. 需要使用到 Maven
  4. 需要使用 MySQL

Maven Pom文件

<parent>
     <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>2.4.3</version>
</parent>

<dependencies>
	
    <!-- 核心入门工具,包括自动配置支持,日志记录和YAML -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    	
     <!--引入springboot的web支持,帮你封装好了很多个依赖-->
     <!-- 使用Spring MVC构建Web(包括RESTful)应用程序的入门程序。使用Tomcat作为默认的嵌入式容器 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    
    <!-- mysql驱动 适用于MySQL的JDBC Type 4驱动程序 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
        <version>8.0.23</version>
    </dependency>
    
    <!-- 用于使用包括JUnit Jupiter,Hamcrest和Mockito在内的库测试Spring Boot应用程序的入门程序 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    
    <!-- 增强您的Java:自动资源管理,自动生成getter,setter,equals,hashCode和toString等 -->
	<dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.8</version>
        <scope>provided</scope>
    </dependency>
    
    <!-- mybatis plus 部分 -->
    
     <!-- 引入mybatis plus依赖 -->
    <!-- Mybatis的增强工具包,可简化开发 -->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.4.2</version>
    </dependency>
    
    <!-- 引入mybatis plus 代码生成器依赖 -->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-generator</artifactId>
        <version>3.4.1</version>
    </dependency>
    
 	<!-- 引入mybatis plus 代码生成器模版引擎依赖 -->
    <dependency>
        <groupId>org.freemarker</groupId>
        <artifactId>freemarker</artifactId>
        <version>2.3.31</version>
    </dependency>
    
     <!-- 引入 alibaba druid 数据库链接依赖 -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid-spring-boot-starter</artifactId>
        <version>1.2.4</version>
    </dependency>
    
    <!-- Apache Commons Lang,这是Java实用程序类的软件包,用于Java.lang层次结构中的类,或者被认为是标准的,可以证明存在于java.lang中 -->
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
        <version>3.11</version>
    </dependency>
    
    <!-- https://mvnrepository.com/artifact/log4j/log4j 日志 -->
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>
    
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
    
    <!-- 必须引入,否则启动报了一个错 -->
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <!-- src/main/resources下的指定资源放行 -->
            <includes>
                <include>**/*.xml</include>
                <include>**/*.properties</include>
                <include>**/*.yml</include>
            </includes>
            <filtering>false</filtering>
        </resource>
    </resources>
</build>

【注意】引入 MyBatis-Plus 之后请不要再次引入 MyBatis 以及 MyBatis-Spring,以避免因版本差异导致的问题。

配置 application.yml 文件

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password: 123456
    url: jdbc:mysql://localhost:3306/test?SSL=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false
    druid:
      # # 初始化时建立物理连接的个数。初始化发生在显示调用init方法,或者第一次getConnection时
      initial-size: 1
      # 最大连接池数量
      max-active: 20
      # 最小连接池数量
      min-idle: 1
      # 获取连接时最大等待时间,单位毫秒
      max-wait: 60000
      # # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
      time-between-eviction-runs-millis: 60000
      # 配置一个连接在池中最小生存的时间,单位是毫秒
      min-evictable-idle-time-millis: 300000
      # 用来检测连接是否有效的sql
      validation-query: select 1 FROM DUAL
      # 议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。
      test-while-idle: true
      # 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
      test-on-borrow: false
      # 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能
      test-on-return: false
      # 是否缓存preparedStatement,也就是PSCache  官方建议MySQL下建议关闭  个人建议如果想用SQL防火墙 建议打开
      pool-prepared-statements: true
      # 启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。
      # 在Druid中,不会存在Oracle下PSCache占用内存过多的问题,可以把这个数值配置大一些,比如说100
      max-open-prepared-statements: 20
      # 通过connectProperties属性来打开mergeSql功能;慢SQL记录
      connect-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
      # 配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入
      # 如果允许时报错  java.lang.ClassNotFoundException: org.apache.log4j.Priority
      # 则导入 log4j 依赖即可,Maven 地址:https://mvnrepository.com/artifact/log4j/log4j
      filter:
        stat:
          enabled: true
          db-type: mysql
          log-slow-sql: true
          slow-sql-millis: 1000
        wall:
          enabled: true
        log4j:
          enabled: true
      # 监控配置
      stat-view-servlet:
        # 开启页面监控
        enabled: true
        # web访问路径
        url-pattern: /druid/*
        # 允许清空统计
        reset-enable: false
        # 用户名
        login-username: admin
        # 密码
        login-password: 123456
        # 默认就是允许所有访问
        # 表示只有本机可以访问 localhost
        allow: ""
      web-stat-filter:
        enabled: true
        url-pattern: /*
        exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"
        # 配置profileEnable能够监控单个url调用的sql列表
        profile-enable: true

# mybatis plus 配置
mybatis-plus:
  # mapper.xml文件中resultMap的type或者parameterType会使用自定义的pojo,
  type-aliases-package: com.xxx.www.mybatisplus.pojo
  # 加载 mapper xml文件
  mapper-locations: classpath:mapping/*.xml
  # 配置中心
  configuration:
    map-underscore-to-camel-case: true
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

在 Spring Boot 启动类中添加 @MapperScan 注解,用于扫描 Mapper 文件夹:

/**
 * @author weixin
 */
@SpringBootApplication
@MapperScan("com.xxx.www.mybatisplus.mapper")
public class MybatisPlusApplication {

    public static void main(String[] args) {
        SpringApplication.run(MybatisPlusApplication.class, args);
    }
}

准备数据

用户表 user

CREATE TABLE `user` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `username` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '用户名',
  `birthday` date NOT NULL COMMENT '生日',
  `sex` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '生日',
  `address` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '地址',
  `create_time` bigint(20) NOT NULL COMMENT '创建时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `unique_username` (`username`) USING BTREE COMMENT '唯一用户名'
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户表';

订单表 order

CREATE TABLE `order` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增ID',
  `order_number` char(32) NOT NULL COMMENT '唯一订单ID',
  `user_id` int(10) NOT NULL COMMENT '用户ID',
  `prepayment_amount` bigint(10) NOT NULL COMMENT '预付金额 单位分',
  `actually_paid_amount` bigint(10) NOT NULL COMMENT '实付金额 = 支付价格 - 优惠价格 单位分',
  `create_time` bigint(20) NOT NULL COMMENT '进店时间',
  `goods_kind` int(10) DEFAULT NULL COMMENT '支付商品种类',
  `goods_quantity` int(10) DEFAULT NULL COMMENT '商品数量',
  `payment_method` varchar(255) DEFAULT NULL COMMENT '支付方式',
  `trade_on` varchar(255) DEFAULT NULL COMMENT '支付流水号',
  `price_after_discount` bigint(20) DEFAULT NULL COMMENT '优惠后价格',
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE KEY `unique_order_number` (`order_number`) USING BTREE COMMENT '唯一订单号'
) ENGINE=InnoDB AUTO_INCREMENT=92 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='交易订单表';

MybatisPlus Generator

AutoGeneratorMyBatis-Plus 的代码生成器,通过 AutoGenerator 可以快速生成 EntityMapperMapper XMLServiceController 等各个模块的代码,极大的提升了开发效率。

添加依赖

代码生成器依赖

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

模板引擎依赖

MyBatis-Plus 支持 Velocity(默认)、FreemarkerBeetl,用户可以选择自己熟悉的模板引擎,如果都不满足您的要求,可以采用自定义模板引擎

Velocity(默认):
<dependency>
    <groupId>org.apache.velocity</groupId>
    <artifactId>velocity-engine-core</artifactId>
    <version>2.1</version>
</dependency>
Freemarker:
<dependency>
    <groupId>com.ibeetl</groupId>
    <artifactId>beetl</artifactId>
    <version>3.0.0.M1</version>
</dependency>
Beetl:
<dependency>
    <groupId>com.ibeetl</groupId>
    <artifactId>beetl</artifactId>
    <version>3.0.0.M1</version>
</dependency>
【注意】如果您选择了非默认引擎,需要在 AutoGenerator 中 设置模板引擎。
AutoGenerator generator = new AutoGenerator();

// set freemarker engine
generator.setTemplateEngine(new FreemarkerTemplateEngine());

// set beetl engine
generator.setTemplateEngine(new BeetlTemplateEngine());

// set custom engine (reference class is your custom engine class)
generator.setTemplateEngine(new CustomTemplateEngine());

// other config
...

Generator Code 代码
public class MybatisPlusGenerator {

    /**
     * 包名
     */
    private static final String PACKAGE_NAME = "com.xxx.www.mybatisplus";

    /**
     * 模块名称
     */
    private static final String MODULE_NAME = "";

    /**
     * 代码生成者
     */
    private static final String AUTHOR = "xxx";

    /**
     * 输出文件的路径
     */
    private static final String OUT_PATH = "";

    /**
     * 驱动名称
     */
    private static final String DRIVER_NAME = "com.mysql.jdbc.Driver";

    /**
     * 驱动连接的URL
     */
    private static final String URL = "jdbc:mysql://localhost:3306/kkb?SSL=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false";

    /**
     * 数据库账号
     */
    private static final String USER_NAME = "root";

    /**
     * 数据库密码
     */
    private static final String PASSWORD = "123456";

    /**
     * 需要生成的表名
     */
    private static final String[] INCLUDE_TABLE = new String[] {"user","order"};


    /**
     * <p>
     * 读取控制台内容
     * </p>
     */
    public static String scanner(String tip) {
        Scanner scanner = new Scanner(System.in);
        StringBuilder help = new StringBuilder();
        help.append("请输入" + tip + ":");
        System.out.println(help.toString());
        if (scanner.hasNext()) {
            String ipt = scanner.next();
            if (StringUtils.isNotBlank(ipt)) {
                return ipt;
            }
        }
        throw new MybatisPlusException("请输入正确的" + tip + "!");
    }

    public static void main(String[] args) {

        // 代码生成器
        AutoGenerator mpg = new AutoGenerator();

        // 项目地址 此处是子项目加了 /mybatis-plus
        // 根据自己实际项目来
        String projectPath = System.getProperty("user.dir") + "/mybatis-plus";
        System.out.println(projectPath);

        //////////// 使用全局配置 ////////////
        GlobalConfig gc = new GlobalConfig();
        //生成文件的输出目录 默认值:D 盘根目录
        gc.setOutputDir(projectPath + "/src/main/java");
        //是否覆盖已有文件
        gc.setFileOverride(true);
        // 开发人员作者
        gc.setAuthor(AUTHOR);
        //是否打开输出目
        gc.setOpen(false);
        //开启 baseColumnList
        gc.setBaseColumnList(true);
        // 开启 swagger2 模式
        // gc.setSwagger2(false);
        // 开启 Kotlin 模式
        gc.setKotlin(false);
        // 指定生成的主键的ID类型 AUTO, NONE, INPUT, ID_WORKER, UUID, ID_WORKER_STR; ID_Worker是雪花算法生成的主键
        gc.setIdType(IdType.AUTO);
        // 开启 BaseResultMap
        gc.setBaseResultMap(true);
        // 设置给到代码生成器
        mpg.setGlobalConfig(gc);

        //////////// 数据源配置 ////////////
        DataSourceConfig dsc = new DataSourceConfig();
        // 驱动链接地址
        dsc.setUrl(URL);
        // 驱动
        dsc.setDriverName(DRIVER_NAME);
        // 数据库账号
        dsc.setUsername(USER_NAME);
        // 数据库密码
        dsc.setPassword(PASSWORD);
        // 数据库类型
        dsc.setDbType(DbType.MYSQL);
        // 设置给到代码生成器
        mpg.setDataSource(dsc);

        //////////// 包配置 ////////////
        PackageConfig pc = new PackageConfig();
        // 父包名。如果为空,将下面子包名必须写全部, 否则就只需写子包名
        pc.setParent(PACKAGE_NAME);
        //设置控制器包名
        pc.setController("controller");
        // 设置 Mapper 包名
        pc.setMapper("mapper");
        // 设置 Service 包名
        pc.setService("service");
        // 设置 Service Impl包名
        pc.setServiceImpl("service.impl");
        // 设置实体类包名
        pc.setEntity("entity");
        // 设置给到代码生成器
        mpg.setPackageInfo(pc);

        // 自定义配置
        InjectionConfig cfg = new InjectionConfig() {
            @Override
            public void initMap() {
                // to do nothing
            }
        };

        // 如果模板引擎是 freemarker
        String templatePath = "/templates/mapper.xml.ftl";
        // 如果模板引擎是 velocity
        // String templatePath = "/templates/mapper.xml.vm";
        // 自定义输出配置
        List<FileOutConfig> focList = new ArrayList<>();
        // 自定义配置会被优先输出
        focList.add(new FileOutConfig(templatePath) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义输入文件名称
                return projectPath + "/src/main/resources/mapping/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
            }
        });

        cfg.setFileOutConfigList(focList);
        // 设置配置给到代码生成器
        mpg.setCfg(cfg);
        //
        mpg.setTemplate(new TemplateConfig().setXml(null));


        //////////// 策略配置 ////////////
        StrategyConfig strategy = new StrategyConfig();
        // 数据库表映射到实体的命名策略 下划线转驼峰命名
        strategy.setNaming(NamingStrategy.underline_to_camel);
        // 数据库表字段映射到实体的命名策略, 未指定按照 naming 执行
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
        // 【实体】是否为lombok模型
        strategy.setEntityLombokModel(true);
        // 需要包含的表名,允许正则表达式(与exclude二选一配置) 需要生成的表
        strategy.setInclude(INCLUDE_TABLE);
        // 生成 @RestController 控制器
        strategy.setRestControllerStyle(true);
        // 驼峰转连字符
        strategy.setControllerMappingHyphenStyle(true);
        // 设置策略配置给代码生成器
        mpg.setStrategy(strategy);
        // 自定义基础的Entity类,公共字段
        // strategy.setSuperEntityColumns("id");
        // 公共父类
        // strategy.setSuperControllerClass("你自己的父类控制器,没有就不用设置!");
        // 设置表名前缀
        // strategy.setTablePrefix(pc.getModuleName() + "_");
        // 排除生成的表
        // strategy.setExclude(new String[]{"test"});


        // 选择 freemarker 引擎需要指定如下加,注意 pom 依赖必须有!
        mpg.setTemplateEngine(new FreemarkerTemplateEngine());

        // 开始执行
        mpg.execute();
    }
}

生成对应的Entity类

订单类

@Data
@EqualsAndHashCode(callSuper = false)
@TableName(value = "`order`")
public class Order implements Serializable {

    private static final long serialVersionUID = 1L;

    /**
     * 自增ID
     */
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;

    /**
     * 唯一订单ID
     */
    private String orderNumber;

    /**
     * 用户ID
     */
    private Integer userId;

    /**
     * 预付金额 单位分
     */
    private Long prepaymentAmount;

    /**
     * 实付金额 = 支付价格 - 优惠价格 单位分
     */
    private Long actuallyPaidAmount;

    /**
     * 进店时间
     */
    private Long createTime;

    /**
     * 支付商品种类
     */
    private Integer goodsKind;

    /**
     * 商品数量
     */
    private Integer goodsQuantity;

    /**
     * 支付方式
     */
    private String paymentMethod;

    /**
     * 支付流水号
     */
    private String tradeOn;

    /**
     * 优惠后价格
     */
    private Long priceAfterDiscount;
}

用户类

xin

@Data
@EqualsAndHashCode(callSuper = false)
@TableName(value = "`user`")
public class User implements Serializable {

    private static final long serialVersionUID = 1L;

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

    /**
     * 用户名
     */
    private String username;

    /**
     * 生日
     */
    private LocalDate birthday;

    /**
     * 生日
     */
    private String sex;

    /**
     * 地址
     */
    private String address;

    /**
     * 创建时间
     */
    private Long createTime;

}
@Data 是 Lombok 提供的能让代码更加简洁的注解,能够减少大量的模板代码。注解在类上,为类提供读写属性,此外还提供了 equals()hashCode()toString() 方法。
@TableName(value = "user") 表名为关键字需要使用,或者实体类类名需要自定义可以声明对应的表名

Mapper映射接口

  • 通用 CRUD 封装 BaseMapper 接口,为 Mybatis-Plus 启动时自动解析实体表关系映射转换为 Mybatis 内部对象注入容器
  • 泛型 T 为任意实体对象
  • 参数 Serializable 为任意类型主键 Mybatis-Plus 不推荐使用复合主键约定每一张表都有自己的唯一 id 主键
  • 对象 Wrapper条件构造器

UserMapper

public interface UserMapper extends BaseMapper<User> {

    /**
     * 获取用户列表
     * @return List<User>
     */
    @Select("SELECT * FROM user GROUP BY create_time desc")
    List<User> getUserList();

    /**
     * 获取用户地址
     * @param username String
     * @return User
     */
    @Select("SELECT address FROM user where username = #{username}")
    String selectUserAddress(String username);

    /**
     * 获取用户地址
     * @param username String
     * @return User
     */
    @Select("SELECT * FROM user where username = #{username}")
    User selectUserByUsername(String username);
}

OrderMapper

public interface OrderMapper extends BaseMapper<Order> {
	//toDO 自定义
}

Service

  • 通用 Service CRUD 封装 IService 接口,进一步封装 CRUD 采用 get 查询单行 remove 删除 list 查询集合 page 分页 前缀命名方式区分 Mapper 层避免混淆。
  • 泛型 T 为任意实体对象
  • 建议如果存在自定义通用 Service 方法的可能,请创建自己的 IBaseService 继承 Mybatis-Plus 提供的基类
  • 对象 Wrapper条件构造器

IUserService

public interface IUserService extends IService<User> {

    /**
     * 查询用户通过用户名称
     * @param username String 用户名
     * @return  User
     */
    User selectUserByUsername(String username);

    /**
     * 查询用户地址
     * @param username String 用户名
     * @return User
     */
    String selectUserAddress(String username);

}

UserServiceImpl

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Autowired
    private UserMapper userMapper;

    @Override
    public User selectUserByUsername(String username) {
        return userMapper.selectUserByUsername(username);
    }

    @Override
    public String selectUserAddress(String username) {
        return userMapper.selectUserAddress(username);
    }

}

测试

UserController

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

    @Autowired
    private IUserService userService;

    /**
     * 根据用户名获取用户地址
     * @param username String
     * @return String 地址
     */
    @PostMapping("/getUserAddress")
    public String getUserAddress(@RequestParam("username") String username){

        String address = userService.selectUserAddress(username);

        return "用户" + username + " 的地址是:" + address;
    }

    /**
     * 条件构造器模式
     * 根据用户名查询性别
     * @param username String
     * @return String 性别
     */
    @PostMapping("/getUserSex")
    public String getUserSex(@RequestParam("username") String username){
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("username", username);
        User user = userService.getBaseMapper().selectOne(userQueryWrapper);
        return "用户" + username + " 的性别是:" + user.getSex();
    }

    /**
     * 获取用户信息通过用户名
     * @param username String
     * @return User 用户信息
     */
    @PostMapping("/getUserByUsername")
    public User getUserByUsername(@RequestParam("username") String username){
        return userService.selectUserByUsername(username);
    }

    /**
     * 获取用户列表
     * @return List<User>
     */
    @GetMapping("getUserList")
    public List<User> getUserList(){
        //  List<User> users = userService.getBaseMapper().selectList(null);
         List<User> users = userService.list();
        users.forEach( user -> System.out.println(user.getUsername()));
        return users;
    }

    /**
     * 搜索用户根据用户名称
     * @param searchName String 用户名称
     * @return List<User>
     */
    @PostMapping("/searchUser")
    public List<User> searchUser(@RequestParam("username") String searchName){
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        // 可以判断参数是否为空
        userQueryWrapper.like(StringUtils.isBlank(searchName),"username","%" + searchName  +"%");
        List<User> users = userService.getBaseMapper().selectList(userQueryWrapper);
        users.forEach(user -> System.out.println(user.getUsername()));
        return users;
    }

    /**
     * 添加用户信息
     * @return User
     */
    @PostMapping("insertUser")
    public User insertUser(User user) throws ParseException {
        String username = user.getUsername();
        User user1 = userService.selectUserByUsername(username);
        System.out.println(user1);
        if (user1 != null){
            System.out.println("用户名已存在");
            return null;
        }
        user.setBirthday(LocalDate.now());
        user.setCreateTime(System.currentTimeMillis());
        int rows =  userService.getBaseMapper().insert(user);
        System.out.println("影响行数:" + rows);
        System.out.println("用户ID:" + user.getId());
        return user;
    }

    /**
     * 修改用户信息根据ID
     * @param user User
     * @return boolean
     */
    @PostMapping("updateUser")
    public boolean updateUser(User user){
        // 用户ID
        if (user.getId() == null){
            System.out.println("用户ID不能为空");
            return false;
        }

        Integer id = user.getId();
        System.out.println("用户id:" + id);

        // 判断用户是否存在
        User user1 = userService.getBaseMapper().selectById(id);
        if (user1 == null){
            System.out.println("用户不存在");
            return false;
        }

        User user2 = userService.selectUserByUsername(user.getUsername());
        if (user2 !=  null){
            System.out.println("用户名已存在");
            return false;
        }

        // 修改用户信息
        int rows =  userService.getBaseMapper().updateById(user);
        System.out.println("影响行数:" + rows);
        return true;
    }

    /**
     * 删除用户根据用户ID
     * @param userId Integer
     * @return boolean
     */
    @PostMapping("deleteUser")
    public boolean deleteUser(@RequestParam("userId") Integer userId){
        int rows = userService.getBaseMapper().deleteById(userId);
        System.out.println("删除行数:" + rows);
        return true;
    }

    /**
     * 分页查询用户信息
     * @return IPage<User>
     */
    @PostMapping("selectUserPage")
    public IPage<User> selectUserPage(){
        Page<User> userPage = new Page<>(1,2);
        // 排序
        userPage.addOrder(OrderItem.asc("create_time"));
        return userService.getBaseMapper().selectPage(userPage, null);
    }
}

错误

问题1

Description:

Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.

Reason: Failed to determine a suitable driver class


Action:

Consider the following:
	If you want an embedded database (H2, HSQL or Derby), please put it on the classpath.
	If you have database settings to be loaded from a particular profile you may need to activate it (no profiles are currently active).

解决: 根据自己配置文件类型,此处用的是yml文件