目录

Life in Flow

知不知,尚矣;不知知,病矣。
不知不知,殆矣。

X

Mybatis plus

介绍

  • 如果写一个数据库表的 crud 接口,正常流程:编写实体类-》编写 Controller-》编写 Service-》编写 DAO-》-》编写 XML 文件

  • 特别是管理后台,多数都是简单的 CRUD,用普通的 MyBatis 有的鸡肋

  • 介绍

    • 官网 https://baomidou.com/
    • 是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生
    • 是怎么增强的呢?已经封装好了一些 crud 方法,我们不需要再写 XML 了,直接调用这些方法就行,类似 JPA 但优于 JPA
  • 更多特性

 1无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
 2
 3损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
 4
 5强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
 6
 7支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
 8
 9支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
10
11支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
12支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
13
14内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
15
16内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
17分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
18
19内置性能分析插件:可输出 Sql 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
20
21内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作

准备数据

xd_shop

  1
  2CREATE TABLE `address` (
  3  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  4  `user_id` bigint(20) DEFAULT NULL COMMENT '用户id',
  5  `default_status` int(1) DEFAULT NULL COMMENT '是否默认收货地址:0->否;1->是',
  6  `receive_name` varchar(64) DEFAULT NULL COMMENT '收发货人姓名',
  7  `phone` varchar(64) DEFAULT NULL COMMENT '收货人电话',
  8  `province` varchar(64) DEFAULT NULL COMMENT '省/直辖市',
  9  `city` varchar(64) DEFAULT NULL COMMENT '市',
 10  `region` varchar(64) DEFAULT NULL COMMENT '区',
 11  `detail_address` varchar(200) DEFAULT NULL COMMENT '详细地址',
 12  `create_time` datetime DEFAULT NULL,
 13  PRIMARY KEY (`id`)
 14) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='电商-公司收发货地址表';
 15
 16
 17
 18CREATE TABLE `banner` (
 19  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
 20  `img` varchar(524) DEFAULT NULL COMMENT '图片',
 21  `url` varchar(524) DEFAULT NULL COMMENT '跳转地址',
 22  `weight` int(11) DEFAULT NULL COMMENT '权重',
 23  PRIMARY KEY (`id`)
 24) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
 25
 26INSERT INTO `banner` (`id`, `img`, `url`, `weight`)
 27VALUES
 28  (1, 'https://file.xdclass.net/video/2020/alibabacloud/zx-lbt.jpeg', 'https://m.xdclass.net/#/member', 1),
 29  (2, 'https://file.xdclass.net/video/%E5%AE%98%E7%BD%91%E8%BD%AE%E6%92%AD%E5%9B%BE/20%E5%B9%B4%E5%8F%8C11%E9%98%BF%E9%87%8C%E4%BA%91/fc-lbt.jpeg', 'https://www.aliyun.com/1111/pintuan-share?ptCode=MTcwMTY3MzEyMjc5MDU2MHx8MTE0fDE%3D&userCode=r5saexap', 3),
 30  (3, 'https://file.xdclass.net/video/%E5%AE%98%E7%BD%91%E8%BD%AE%E6%92%AD%E5%9B%BE/20%E5%B9%B4%E5%8F%8C11%E9%98%BF%E9%87%8C%E4%BA%91/FAN-lbu-vip.jpeg', 'https://file.xdclass.net/video/%E5%AE%98%E7%BD%91%E8%BD%AE%E6%92%AD%E5%9B%BE/Nginx.jpeg', 2);
 31
 32
 33
 34CREATE TABLE `coupon` (
 35  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
 36  `category` varchar(11) DEFAULT NULL COMMENT '优惠卷类型[NEW_USER注册赠券,TASK任务卷,PROMOTION促销劵]',
 37  `publish` varchar(11) DEFAULT NULL COMMENT '发布状态, PUBLISH发布,DRAFT草稿,OFFLINE下线',
 38  `coupon_img` varchar(524) DEFAULT NULL COMMENT '优惠券图片',
 39  `coupon_title` varchar(128) DEFAULT NULL COMMENT '优惠券标题',
 40  `price` decimal(16,2) DEFAULT NULL COMMENT '抵扣价格',
 41  `user_limit` int(11) DEFAULT NULL COMMENT '每人限制张数',
 42  `start_time` datetime DEFAULT NULL COMMENT '优惠券开始有效时间',
 43  `end_time` datetime DEFAULT NULL COMMENT '优惠券失效时间',
 44  `publish_count` int(11) DEFAULT NULL COMMENT '优惠券总量',
 45  `stock` int(11) DEFAULT '0' COMMENT '库存',
 46  `add_one` int(11) DEFAULT NULL COMMENT '是否叠加0是不行,1是可以',
 47  `create_time` datetime DEFAULT NULL,
 48  `condition_price` decimal(16,2) DEFAULT NULL COMMENT '满多少才可以使用',
 49  PRIMARY KEY (`id`)
 50) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
 51
 52
 53
 54
 55CREATE TABLE `product` (
 56  `id` bigint(11) unsigned NOT NULL AUTO_INCREMENT,
 57  `title` varchar(128) DEFAULT NULL COMMENT '标题',
 58  `cover_img` varchar(128) DEFAULT NULL COMMENT '封面图',
 59  `detail` varchar(256) DEFAULT '' COMMENT '详情',
 60  `old_price` decimal(16,2) DEFAULT NULL COMMENT '老价格',
 61  `price` decimal(16,2) DEFAULT NULL COMMENT '新价格',
 62  `stock` int(11) DEFAULT NULL COMMENT '库存',
 63  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
 64  `lock_stock` int(11) DEFAULT '0' COMMENT '锁定库存',
 65  PRIMARY KEY (`id`)
 66) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
 67
 68
 69
 70CREATE TABLE `product_order` (
 71  `id` bigint(11) NOT NULL AUTO_INCREMENT,
 72  `out_trade_no` varchar(64) DEFAULT NULL COMMENT '订单唯一标识',
 73  `state` varchar(11) DEFAULT NULL COMMENT 'NEW 未支付订单,PAY已经支付订单,CANCEL超时取消订单',
 74  `create_time` datetime DEFAULT NULL COMMENT '订单生成时间',
 75  `total_fee` decimal(16,2) DEFAULT NULL COMMENT '订单总金额',
 76  `pay_fee` decimal(16,2) DEFAULT NULL COMMENT '订单实际支付价格',
 77  `pay_type` varchar(64) DEFAULT NULL COMMENT '支付类型,微信-银行-支付宝',
 78  `nickname` varchar(64) DEFAULT NULL COMMENT '昵称',
 79  `head_img` varchar(524) DEFAULT NULL COMMENT '头像',
 80  `user_id` int(11) DEFAULT NULL COMMENT '用户id',
 81  `del` int(5) DEFAULT '0' COMMENT '0表示未删除,1表示已经删除',
 82  `update_time` datetime DEFAULT NULL COMMENT '更新时间',
 83  `order_type` varchar(32) DEFAULT NULL COMMENT '订单类型 DAILY普通单,PROMOTION促销订单',
 84  `receiver_address` varchar(1024) DEFAULT NULL COMMENT '收货地址 json存储',
 85  PRIMARY KEY (`id`)
 86) ENGINE=MyISAM DEFAULT CHARSET=utf8;
 87
 88
 89CREATE TABLE `product_order_item` (
 90  `id` bigint(11) unsigned NOT NULL AUTO_INCREMENT,
 91  `product_order_id` bigint(11) DEFAULT NULL COMMENT '订单号',
 92  `out_trade_no` varchar(32) DEFAULT NULL,
 93  `product_id` bigint(11) DEFAULT NULL COMMENT '产品id',
 94  `product_name` varchar(128) DEFAULT NULL COMMENT '商品名称',
 95  `product_img` varchar(524) DEFAULT NULL COMMENT '商品图片',
 96  `buy_num` int(11) DEFAULT NULL COMMENT '购买数量',
 97  `create_time` datetime DEFAULT NULL,
 98  `total_fee` decimal(16,2) DEFAULT NULL COMMENT '购物项商品总价格',
 99  `pay_fee` decimal(16,0) DEFAULT NULL COMMENT '购物项商品支付总价格',
100  PRIMARY KEY (`id`)
101) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
102
103
104
105CREATE TABLE `user` (
106  `id` bigint(11) unsigned NOT NULL AUTO_INCREMENT,
107  `name` varchar(128) DEFAULT NULL COMMENT '昵称',
108  `pwd` varchar(124) DEFAULT NULL COMMENT '密码',
109  `head_img` varchar(524) DEFAULT NULL COMMENT '头像',
110  `slogan` varchar(524) DEFAULT NULL COMMENT '用户签名',
111  `sex` tinyint(2) DEFAULT '1' COMMENT '0表示女,1表示男',
112  `points` int(10) DEFAULT '0' COMMENT '积分',
113  `create_time` datetime DEFAULT NULL,
114  `mail` varchar(64) DEFAULT NULL COMMENT '邮箱',
115  `secret` varchar(12) DEFAULT NULL COMMENT '盐,用于个人敏感信息处理',
116  PRIMARY KEY (`id`),
117  UNIQUE KEY `mail_idx` (`mail`)
118) ENGINE=InnoDB DEFAULT CHARSET=utf8;
119

SpringBoot2.X 整合 MybatisPlus+Lombok

添加依赖

  1<?xml version="1.0" encoding="UTF-8"?>
  2<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  4	<modelVersion>4.0.0</modelVersion>
  5	<parent>
  6		<groupId>org.springframework.boot</groupId>
  7		<artifactId>spring-boot-starter-parent</artifactId>
  8		<version>2.4.1</version>
  9		<relativePath/> <!-- lookup parent from repository -->
 10	</parent>
 11	<groupId>net.xdclass</groupId>
 12	<artifactId>1024shop-manager</artifactId>
 13	<version>0.0.1-SNAPSHOT</version>
 14	<name>1024shop-manager</name>
 15	<description>Demo project for Spring Boot</description>
 16
 17	<properties>
 18		<java.version>11</java.version>
 19	</properties>
 20
 21	<dependencies>
 22		<dependency>
 23			<groupId>org.springframework.boot</groupId>
 24			<artifactId>spring-boot-starter-web</artifactId>
 25		</dependency>
 26
 27		<dependency>
 28			<groupId>org.springframework.boot</groupId>
 29			<artifactId>spring-boot-starter-test</artifactId>
 30			<scope>test</scope>
 31		</dependency>
 32
 33		<!-- lombok -->
 34		<dependency>
 35			<groupId>org.projectlombok</groupId>
 36			<artifactId>lombok</artifactId>
 37			<version>1.18.16</version>
 38			<scope>provided</scope>
 39		</dependency>
 40
 41		<!-- mysql -->
 42		<dependency>
 43			<groupId>mysql</groupId>
 44			<artifactId>mysql-connector-java</artifactId>
 45		</dependency>
 46
 47		<!--mybatis plus和springboot整合-->
 48		<dependency>
 49			<groupId>com.baomidou</groupId>
 50			<artifactId>mybatis-plus-boot-starter</artifactId>
 51			<version>3.4.1</version>
 52		</dependency>
 53
 54
 55		<!-- 代码自动生成依赖 begin -->
 56		<dependency>
 57			<groupId>com.baomidou</groupId>
 58			<artifactId>mybatis-plus-generator</artifactId>
 59			<version>3.4.1</version>
 60		</dependency>
 61		<!-- velocity -->
 62		<dependency>
 63			<groupId>org.apache.velocity</groupId>
 64			<artifactId>velocity-engine-core</artifactId>
 65			<version>2.0</version>
 66		</dependency>
 67		<!-- 代码自动生成依赖 end-->
 68
 69	</dependencies>
 70
 71	<build>
 72		<plugins>
 73			<plugin>
 74				<groupId>org.springframework.boot</groupId>
 75				<artifactId>spring-boot-maven-plugin</artifactId>
 76			</plugin>
 77			<plugin>
 78				<groupId>org.apache.maven.plugins</groupId>
 79				<artifactId>maven-compiler-plugin</artifactId>
 80				<configuration>
 81					<source>15</source>
 82					<target>15</target>
 83				</configuration>
 84			</plugin>
 85		</plugins>
 86	</build>
 87
 88
 89	<!-- 代码库 -->
 90	<repositories>
 91		<repository>
 92			<id>maven-ali</id>
 93			<url>http://maven.aliyun.com/nexus/content/groups/public//</url>
 94			<releases>
 95				<enabled>true</enabled>
 96			</releases>
 97			<snapshots>
 98				<enabled>true</enabled>
 99				<updatePolicy>always</updatePolicy>
100				<checksumPolicy>fail</checksumPolicy>
101			</snapshots>
102		</repository>
103	</repositories>
104
105	<pluginRepositories>
106		<pluginRepository>
107			<id>public</id>
108			<name>aliyun nexus</name>
109			<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
110			<releases>
111				<enabled>true</enabled>
112			</releases>
113			<snapshots>
114				<enabled>false</enabled>
115			</snapshots>
116		</pluginRepository>
117	</pluginRepositories>
118
119
120
121</project>
122

增加数据库配置 application.properties

1server.port=8081
2#==============================数据库相关配置========================================
3spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
4spring.datasource.url=jdbc:mysql://192.168.31.101:50000/xd_shop?useUnicode=true&characterEncoding=utf-8&useSSL=false
5spring.datasource.username =root
6spring.datasource.password =123456
7

包扫描:添加 @MapperScan 注解

 1package net.xdclass.shopmanager;
 2
 3import org.mybatis.spring.annotation.MapperScan;
 4import org.springframework.boot.SpringApplication;
 5import org.springframework.boot.autoconfigure.SpringBootApplication;
 6
 7@SpringBootApplication
 8@MapperScan("net.xdclass.shopmanager.mapper")
 9public class Application {
10
11    public static void main(String[] args) {
12        SpringApplication.run(Application.class, args);
13
14    }
15
16}
17

快速上手

基础准备

  • 统一接口返回协议-JsonData
 1package net.xdclass.shopmanager.util;
 2
 3import lombok.AllArgsConstructor;
 4import lombok.Data;
 5import lombok.NoArgsConstructor;
 6
 7@Data
 8@AllArgsConstructor //会生成一个包含所有变量
 9@NoArgsConstructor //生成一个无参数的构造方法
10public class JsonData {
11    /**
12     * 状态码 0 表示成功,1表示处理中,-1表示失败
13     */
14    private Integer code;
15    /**
16     * 数据
17     */
18    private Object data;
19    /**
20     * 描述
21     */
22    private String msg;
23
24    // 成功,传入数据
25    public static JsonData buildSuccess() {
26        return new JsonData(0, null, null);
27    }
28
29    // 成功,传入数据
30    public static JsonData buildSuccess(Object data) {
31        return new JsonData(0, data, null);
32    }
33
34    // 失败,传入描述信息
35    public static JsonData buildError(String msg) {
36        return new JsonData(-1, null, msg);
37    }
38
39    // 失败,传入描述信息,状态码
40    public static JsonData buildError(String msg, Integer code) {
41        return new JsonData(code, null, msg);
42    }
43
44}

BannerDO 类编写

1@Data
2@TableName("banner")//表名映射
3public class BannerDO {
4
5    private Integer id;
6    private String img;
7    private String url;
8    private Integer weight;
9}

Controller

 1@RestController
 2@RequestMapping("/api/banner/v1")
 3public class BannerController {
 4  
 5    //注入有红色告警可以忽略,idea识别问题
 6    @Autowired
 7    private BannerService bannerService;
 8
 9    @RequestMapping("list")
10    public JsonData list(){
11
12        return JsonData.buildSuccess(bannerService.list());
13    }
14
15}

Service

1public interface BannerService {
2    List<BannerDO> list();
3}

ServiceImpl

 1@Service
 2public class BannerServiceImpl implements BannerService {
 3    @Autowired
 4    private BannerMapper bannerMapper;
 5
 6    @Override
 7    public List<BannerDO> list() {
 8        //查询全部
 9        List<BannerDO> list = bannerMapper.selectList(new QueryWrapper<BannerDO>());
10        return list;
11    }
12}

Mapper

1import com.baomidou.mybatisplus.core.mapper.BaseMapper;
2import net.xdclass.shopmanager.model.BannerDO;
3
4public interface BannerMapper extends BaseMapper<BannerDO> {
5}
6

测试

 1// http://localhost:8081/api/banner/v1/list
 2
 3{
 4  "code": 0,
 5  "data": [
 6    {
 7      "id": 1,
 8      "img": "https://file.xdclass.net/video/2020/alibabacloud/zx-lbt.jpeg",
 9      "url": "https://m.xdclass.net/#/member",
10      "weight": 1
11    },
12    {
13      "id": 2,
14      "img": "https://file.xdclass.net/video/%E5%AE%98%E7%BD%91%E8%BD%AE%E6%92%AD%E5%9B%BE/20%E5%B9%B4%E5%8F%8C11%E9%98%BF%E9%87%8C%E4%BA%91/fc-lbt.jpeg",
15      "url": "https://www.aliyun.com/1111/pintuan-share?ptCode=MTcwMTY3MzEyMjc5MDU2MHx8MTE0fDE%3D&userCode=r5saexap",
16      "weight": 3
17    },
18    {
19      "id": 3,
20      "img": "https://file.xdclass.net/video/%E5%AE%98%E7%BD%91%E8%BD%AE%E6%92%AD%E5%9B%BE/20%E5%B9%B4%E5%8F%8C11%E9%98%BF%E9%87%8C%E4%BA%91/FAN-lbu-vip.jpeg",
21      "url": "https://file.xdclass.net/video/%E5%AE%98%E7%BD%91%E8%BD%AE%E6%92%AD%E5%9B%BE/Nginx.jpeg",
22      "weight": 2
23    }
24  ],
25  "msg": null
26}

单元测试、控制台数据 SQL

Spring Boot Test 是在 Spring Test 之上的再次封装, 使用 @SpringBootTest 后,Spring 将加载所有被管理的 bean,等同于启动了整个服务

项目添加依赖

1<dependency>
2  <groupId>org.springframework.boot</groupId>
3  <artifactId>spring-boot-starter-test</artifactId>
4</dependency>

MyBatis plus 配置控制台打印日志

1#配置mybatis plus打印sql日志
2mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

项目新建测试

 1package net.xdclass.shopmanager;
 2
 3import lombok.extern.slf4j.Slf4j;
 4import net.xdclass.shopmanager.model.BannerDO;
 5import net.xdclass.shopmanager.service.BannerService;
 6import org.junit.jupiter.api.Test;
 7import org.springframework.beans.factory.annotation.Autowired;
 8import org.springframework.boot.test.context.SpringBootTest;
 9
10import java.util.List;
11
12@SpringBootTest(classes = Application.class)
13@Slf4j
14class ApplicationTests {
15
16	@Autowired
17	private BannerService bannerService;
18
19	@Test
20	public void testBannerList(){
21		List<BannerDO> list = bannerService.list();
22		log.info("轮播图列表:{}",list);
23	}
24
25}

核心类 BaseMapper

核心类介绍: Mapper 继承该接口后,无需编写 mapper.xml 文件,即可获得 CRUD 功能

  • 方法很多:记住常用的几个就行
  1
  2/**
  3 * Mapper 继承该接口后,无需编写 mapper.xml 文件,即可获得CRUD功能
  4 * <p>这个 Mapper 支持 id 泛型</p>
  5 *
  6 * @author hubin
  7 * @since 2016-01-23
  8 */
  9public interface BaseMapper<T> extends Mapper<T> {
 10
 11    /**
 12     * 插入一条记录
 13     *
 14     * @param entity 实体对象
 15     */
 16    int insert(T entity);
 17
 18    /**
 19     * 根据 ID 删除
 20     *
 21     * @param id 主键ID
 22     */
 23    int deleteById(Serializable id);
 24
 25    /**
 26     * 根据 columnMap 条件,删除记录
 27     *
 28     * @param columnMap 表字段 map 对象
 29     */
 30    int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
 31
 32    /**
 33     * 根据 entity 条件,删除记录
 34     *
 35     * @param queryWrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)
 36     */
 37    int delete(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
 38
 39    /**
 40     * 删除(根据ID 批量删除)
 41     *
 42     * @param idList 主键ID列表(不能为 null 以及 empty)
 43     */
 44    int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
 45
 46    /**
 47     * 根据 ID 修改
 48     *
 49     * @param entity 实体对象
 50     */
 51    int updateById(@Param(Constants.ENTITY) T entity);
 52
 53    /**
 54     * 根据 whereEntity 条件,更新记录
 55     *
 56     * @param entity        实体对象 (set 条件值,可以为 null)
 57     * @param updateWrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)
 58     */
 59    int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper<T> updateWrapper);
 60
 61    /**
 62     * 根据 ID 查询
 63     *
 64     * @param id 主键ID
 65     */
 66    T selectById(Serializable id);
 67
 68    /**
 69     * 查询(根据ID 批量查询)
 70     *
 71     * @param idList 主键ID列表(不能为 null 以及 empty)
 72     */
 73    List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
 74
 75    /**
 76     * 查询(根据 columnMap 条件)
 77     *
 78     * @param columnMap 表字段 map 对象
 79     */
 80    List<T> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
 81
 82    /**
 83     * 根据 entity 条件,查询一条记录
 84     *
 85     * @param queryWrapper 实体对象封装操作类(可以为 null)
 86     */
 87    T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
 88
 89    /**
 90     * 根据 Wrapper 条件,查询总记录数
 91     *
 92     * @param queryWrapper 实体对象封装操作类(可以为 null)
 93     */
 94    Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
 95
 96    /**
 97     * 根据 entity 条件,查询全部记录
 98     *
 99     * @param queryWrapper 实体对象封装操作类(可以为 null)
100     */
101    List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
102
103    /**
104     * 根据 Wrapper 条件,查询全部记录
105     *
106     * @param queryWrapper 实体对象封装操作类(可以为 null)
107     */
108    List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
109
110    /**
111     * 根据 Wrapper 条件,查询全部记录
112     * <p>注意: 只返回第一个字段的值</p>
113     *
114     * @param queryWrapper 实体对象封装操作类(可以为 null)
115     */
116    List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
117
118    /**
119     * 根据 entity 条件,查询全部记录(并翻页)
120     *
121     * @param page         分页查询条件(可以为 RowBounds.DEFAULT)
122     * @param queryWrapper 实体对象封装操作类(可以为 null)
123     */
124    <E extends IPage<T>> E selectPage(E page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
125
126    /**
127     * 根据 Wrapper 条件,查询全部记录(并翻页)
128     *
129     * @param page         分页查询条件
130     * @param queryWrapper 实体对象封装操作类
131     */
132    <E extends IPage<Map<String, Object>>> E selectMapsPage(E page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
133}

QueryWrapper 介绍

  • 查询包装类,可以封装多数查询条件,泛型指定返回的实体类
1List<BannerDO> list = bannerMapper.selectList(new QueryWrapper<BannerDO>());

MyBatis plus 常用注解

  • @TableName 用于定义表名
  • @TableId 用于定义表的主键
    • 属性
1value 用于定义主键字段名
2type 用于定义主键类型(主键策略 IdType)
  • 主键策略
1IdType.AUTO          主键自增,系统分配,不需要手动输入
2IdType.NONE          未设置主键
3IdType.INPUT         需要自己输入 主键值
4IdType.ASSIGN_ID     系统分配 ID,用于数值型数据(Long,对应 mysql 中 BIGINT 类型)
5IdType.ASSIGN_UUID   系统分配 UUID,用于字符串型数据(String,对应 mysql 中 varchar(32) 类型)

@TableField 用于定义表的非主键字段

  • 属性
 1value 用于定义非主键字段名,用于别名匹配,假如java对象属性和数据库属性不一样
 2
 3exist 用于指明是否为数据表的字段, true 表示是,false 为不是,假如某个java属性在数据库没对应的字段则要标记为faslse
 4
 5fill 用于指定字段填充策略(FieldFill,用的不多)
 6  字段填充策略:一般用于填充 创建时间、修改时间等字段
 7  FieldFill.DEFAULT         默认不填充
 8  FieldFill.INSERT          插入时填充
 9  FieldFill.UPDATE          更新时填充
10  FieldFill.INSERT_UPDATE   插入、更新时填充。

示例

 1@Data
 2@TableName("banner")//表名映射
 3public class BannerDO {
 4  
 5    @TableId(value = "id", type = IdType.AUTO)
 6    private Integer id;
 7
 8    private String img;
 9
10    private String url;
11
12    @TableField("weight")
13    private Integer weightAAA;
14
15    @TableField(exist = false)
16    private Date createTime;
17}
18

查询

  • selectById
  • selectBatchIds
  • selectOne
  • selectCount
  • selectList
 1package net.xdclass.shopmanager;
 2
 3import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 4import lombok.extern.slf4j.Slf4j;
 5import net.xdclass.shopmanager.mapper.BannerMapper;
 6import net.xdclass.shopmanager.model.BannerDO;
 7import net.xdclass.shopmanager.service.BannerService;
 8import org.junit.jupiter.api.Test;
 9import org.springframework.beans.factory.annotation.Autowired;
10import org.springframework.boot.test.context.SpringBootTest;
11
12import java.util.Arrays;
13import java.util.List;
14
15@SpringBootTest(classes = Application.class)
16@Slf4j
17class ApplicationTests {
18
19	@Autowired
20	private BannerService bannerService;
21
22	@Autowired
23	private BannerMapper bannerMapper;
24
25	/**
26	 * 根据主键ID查找
27	 */
28	@Test
29	public void testSelectById(){
30		BannerDO bannerDO = bannerMapper.selectById(1);
31		log.info("bannerDO:{}",bannerDO);
32	}
33
34	/**
35	 * 批量查找根据主键
36	 */
37	@Test
38	public void selectBatchIds(){
39		List<BannerDO> bannerDOS = bannerMapper.selectBatchIds(Arrays.asList(1, 2));
40		log.info("bannerDOS:{}",bannerDOS);
41	}
42
43	/**
44	 * 选择1条
45	 */
46	@Test
47	public void selectOne(){
48		BannerDO bannerDO = bannerMapper.selectOne(new QueryWrapper<BannerDO>().eq("id",1));
49		log.info("bannerDO:{}",bannerDO);
50	}
51
52	/**
53	 * 统计行数
54	 */
55	@Test
56	public void selectCount(){
57		int size = bannerMapper.selectCount(null);
58		log.info("size:{}",size);
59	}
60
61	/**
62	 * 查询所有数据
63	 */
64	@Test
65	public void testBannerList(){
66		List<BannerDO> list = bannerService.list();
67		log.info("轮播图列表:{}",list);
68	}
69
70}
71

新增

 1	/**
 2	 * 新增
 3	 */
 4	@Test
 5	public void testAdd(){
 6		BannerDO bannerDO = new BannerDO();
 7		bannerDO.setImg("xxx");
 8		bannerDO.setUrl("xdclass.net");
 9		bannerMapper.insert(bannerDO);
10		log.info("轮播图:{}", bannerDO);
11	}

删除

  • 根据 id 删除
1	/**
2	 * 根据id删除
3	 */
4	@Test
5	public void testDeleteId(){
6		//影响行数
7		int rows = bannerMapper.deleteById(4);
8		log.info("rows:{}",rows);
9	}
  • 条件删除
 1    /**
 2     * 通用删除操作 deleteByMap  map要写列名条件 不能是实体属性名
 3     */
 4    @Test
 5    public void testCommonDeleteByMap() {
 6        Map<String, Object> columnMap = new HashMap<>();
 7        columnMap.put("weight",12);
 8        columnMap.put("url","bbb");
 9        int result=bannerMapper.deleteByMap(columnMap);
10        System.out.println("*******************"+result);
11    }

更新

  • queryWrapper 更新操作
1BannerDO bannerDO = new BannerDO();
2bannerDO.setImg("iiiii");
3//空字段不会更新,只会更新设置的字段
4bannerMapper.update(bannerDO,new QueryWrapper<BannerDO>().eq("id","1"));
  • updateWrapper 更新操作
1UpdateWrapper updateWrapper = new UpdateWrapper();
2//设置要更新的字段和值,key是db的属性名称
3updateWrapper.set("img","uuuu");
4//条件
5updateWrapper.eq("id",1);
6
7bannerMapper.update(null,updateWrapper);

查询封装类 QueryWrapper 比较 API

QueryWrapper 介绍

  • 可以封装 SQL 对象,包括 where 条件,order by 排序,select 哪些字段等等
  • 查询包装类,可以封装多数查询条件,泛型指定返回的实体类
1List<BannerDO> list = bannerMapper.selectList(new QueryWrapper<BannerDO>());
  • 核心 API

    • eq 等于
    • ne 不等于
    • gt 大于
    • ge 大于等于
    • lt 小于
    • le 小于等于
    • or 拼接 or
    • between 两个值中间
    • notBetween 不在两个值中间
    • like 模糊匹配
    • notLike 不像
    • likeLeft 左匹配
    • likeRight 右边匹配
    • isNull 字段为空
    • in in 查询
    • groupBy 分组
    • orderByAsc 升序
    • orderByDesc 降序
    • having having 查询
1	@Test
2	public void testQueryWrapper(){
3		QueryWrapper queryWrapper = new QueryWrapper();
4		queryWrapper.eq("id", 1);
5		queryWrapper.ne("url", "bbbc.com");
6		List list = bannerMapper.selectList(queryWrapper);
7		log.info("list:{}",list); // list:[BannerDO(id=1, img=https://file.xdclass.net/video/2020/alibabacloud/zx-lbt.jpeg, url=https://m.xdclass.net/#/member, weightAAA=1, createTime=null)]
8	}

配置分页插件

新建配置类

 1package net.xdclass.shopmanager.config;
 2
 3import com.baomidou.mybatisplus.annotation.DbType;
 4import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
 5import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
 6import org.springframework.context.annotation.Bean;
 7import org.springframework.context.annotation.Configuration;
 8
 9@Configuration
10public class MybatisPlusPageConfig {
11
12        /*  旧版本配置
13      @Bean
14      public PaginationInterceptor paginationInterceptor(){
15        return new PaginationInterceptor();
16      }*/
17
18
19    /**
20     * 新的分页插件
21     */
22    @Bean
23    public MybatisPlusInterceptor mybatisPlusInterceptor() {
24        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
25        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
26        return interceptor;
27    }
28
29}
30
31

测试分页

 1	/***
 2	 * 测试分页
 3	 */
 4	@Test
 5	public void testPage() {
 6		QueryWrapper<BannerDO> wrapper = new QueryWrapper<>();
 7		wrapper.eq("weight",4);
 8		//第1页,每页2条
 9		Page<BannerDO> page = new Page<>(1, 2);
10		IPage<BannerDO> iPage = bannerMapper.selectPage(page, wrapper);
11		System.out.println("总条数"+iPage.getTotal());
12		System.out.println("总页数"+iPage.getPages());
13		//获取当前数据
14		System.out.println(iPage.getRecords().toString());
15	}

MyBatis plus 自定义 XML SQL 脚本

Mapper 类中增加方法

 1package net.xdclass.shopmanager.mapper;
 2
 3import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 4import net.xdclass.shopmanager.model.BannerDO;
 5
 6import java.util.List;
 7
 8public interface BannerMapper extends BaseMapper<BannerDO> {
 9    List<BannerDO> list();
10}
11

新建 XML src\main\resources\mapper\BannerMapper.xml

1<?xml version="1.0" encoding="UTF-8"?>
2<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
3<!--这个名称空间是Mapper接口的路径,记得修改-->
4<mapper namespace="net.xdclass.shopmanager.mapper.BannerMapper">
5    <select id="list" resultType="net.xdclass.shopmanager.model.BannerDO">
6        select * from banner
7    </select>
8</mapper>

配置文件告诉 mapper.xml 路径(如果采用默认路径可以不配)

1#默认配置路径
2mybatis-plus.mapper-locations=classpath*:/mapper/*Mapper.xml

测试

1	@Test
2	public void testList(){
3		List<BannerDO> list = bannerMapper.list();
4		log.info("list:{}",list);
5	}

MyBatis plus 全局配置案例

配置 Myabits 的全局配置文件

  • 注意:config-location 和 configuration 不能同时出现,需要注释配置文件里的相关配置
 1#配置文件
 2server.port=8081
 3#==============================数据库相关配置
 4spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
 5spring.datasource.url=jdbc:mysql://192.168.0.114:3306/xd_shop?useUnicode=true&characterEncoding=utf-8&useSSL=false
 6spring.datasource.username=root
 7spring.datasource.password=xdclass.net
 8
 9#开启控制台打印sql
10#mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
11
12#配置mybatis plus打印sql日志
13#mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
14
15#配置最新全局配置文件!!!!
16mybatis-plus.config-location = classpath:mybatis-config.xml
  • 创建 mybatis-config.xml
 1<?xml version="1.0" encoding="UTF-8" ?>
 2<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
 3<configuration>
 4
 5    <settings>
 6    <!--控制台输出日志-->
 7        <setting name="logImpl" value="STDOUT_LOGGING"/>
 8    </settings>
 9  
10</configuration>
  • 配置文件配置 自定义 SQL 的包扫描
1mybatis-plus.type-aliases-package= net.xdclass.shop.model
  • XML 改为
1<!--旧-->
2<select id="list" resultType="net.xdclass.shop.model.BannerDO">
3     select * from banner
4</select>
5
6<!--新-->
7<select id="list" resultType="BannerDO">
8     select * from banner
9</select>
  • MyBatis plus 下划线转驼峰配置,默认就是 true
1mybatis-plus.configuration.map-underscore-to-camel-case=true
  • 配置全局默认主键类型,实体类就不用加 @TableId(value = "id", type = IdType.AUTO)
1mybatis-plus.global-config.db-config.id-type=auto

性能优化之指定 select 字段查询

面试题:select * 和 select 指定字段的区别

  • 网络 IO 问题
1select * 会查出所有的字段,有些是不需要的,当应用程序和服务器不在同一个局域网时,字段过多会影响网络传输的性能
  • 索引问题
1在 指定字段有索引的情况下,mysql是可以不用读data,直接使用index里面的值就返回结果的。
2但是一旦用了select *,就会有其他列需要从磁盘中读取才会返回结果,这样就造成了额外的性能开销
  • MybatisPlus 指定查询字段
1bannerMapper.selectList(new QueryWrapper<BannerDO>().select("id","name"));

ActiveRecord

  • 什么是 ActiveRecord(只做简单了解即可)
1Active Record(活动记录),是一种领域模型模式,特点是一个模型类对应关系型数据库中的一个表,而模型类的一个实例对应表中的一行记录。
  • MyBatis Plus 对 AR 有一定支持, 在 MP 中开启 AR,仅需要实体类继承 Model 类即可
 1@Data
 2//表名映射,用于新增才需要
 3@TableName("banner")
 4public class BannerDO extends Model<BannerDO> {
 5
 6    @TableId(value = "id", type = IdType.AUTO)
 7    private Integer id;
 8
 9    private String img;
10
11    private String url;
12
13    private Integer weight;
14}
  • 使用
1BannerDO bannerDO = new BannerDO();
2BannerDO b = bannerDO.selectOne(new QueryWrapper<BannerDO>().eq("id","1"));
3System.out.println(b);

使用建议

  • 业务逻辑比较简单,当类基本上和数据库中的表一一对应时, ActiveRecord 是非常方便的, 即业务逻辑大多数是对单表操作,简单,直观 一个类就包括了数据访问和业务逻辑.
  • ActiveRecord 虽然有业务逻辑, 但基本上都是基于单表的. 跨表逻辑一般会放到当发生跨表的操作时, 往往会配合使用事务脚本(Transaction Script)中.
  • 如果对象间的关联越来越多, 你的事务脚本越来越庞大, 重复的代码越来越多, 就不建议使用了
  • 模型容易混乱,ActiveRecord 保存了数据, 使它有时候看上去像数据传输对象(DTO). 但是 ActiveRecord 有数据库访问能力, 所以所以分布式或者大型项目基本不用
    • POJO: model/domain/dto/vo/bo/do

数据库高并发乐观锁

  • 什么是乐观锁
1每次去拿数据的时候都认为别人不会修改,更新的时候会判断是别人是否回去更新数据,通过版本来判断,如果数据被修改了就拒绝更新
2
3Java里面大量使用CAS, CAS这个是属于乐观锁,性能较悲观锁有很大的提高
4AtomicXXX 等原子类底层就是CAS实现,一定程度比synchonized好,因为后者是悲观锁
5
6小结:悲观锁适合写操作多的场景,乐观锁适合读操作多的场景,乐观锁的吞吐量会比悲观锁多

image-20200212185212328

  • 数据库的乐观锁
1大多是基于数据版本 (Version)记录机制实现。何谓数据版本?即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通
2
3过为数据库表增加一个 “version” 字段来 实现。 读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。此时,将提交数据的版本数据与数据,库表对应记录的当前版本信息进行比对,如果提交的数据 版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据

MybatisPlus 乐观锁插件使用

  • MyBatis Plus 里面自带一个插件,可以帮我们轻松实现乐观锁
  • 使用:实体类增加 version 属性配置
1@Version
2private Integer version;
  • 数据库增加 version 版本字段
1CREATE TABLE `banner` (
2  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
3  `img` varchar(524) DEFAULT NULL COMMENT '图片',
4  `url` varchar(524) DEFAULT NULL COMMENT '跳转地址',
5  `weight` int(11) DEFAULT NULL COMMENT '权重',
6  `version` int(11) DEFAULT '1' COMMENT '乐观锁版本号',
7  `deleted` int(11) DEFAULT '0' COMMENT '0是未删除,1是已经删除',
8  PRIMARY KEY (`id`)
9) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8mb4;
  • 增加乐观锁插件
 1 @Bean
 2 public MybatisPlusInterceptor mybatisPlusInterceptor() {
 3        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
 4        //分页插件
 5        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
 6
 7        //乐观锁插件
 8        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
 9        return interceptor;
10}
  • 使用
1//先根据ID找记录,得到 id 和 version
2BannerDO bannerDO = new BannerDO();
3bannerDO.setVersion(1);//旧版本号,即查询出来的版本号
4bannerDO.setId(1);
5bannerDO.setUrl("xdclass.net");
6bannerMapper.updateById(bannerDO);

注意

  • 乐观锁数据类型支持 int、integer、long、timestamp
  • 仅支持 updateById 和 update 方法

MybatisPlus 逻辑删除配置

  • 什么是逻辑删除
1很多互联网公司在数据库设计规范中都加入了逻辑删除的强制规定,运营人员可以分析和审查数据,也方便将数据沉淀下来用于商业分析
2
3比如用户删除了订单,只不过是更新了标记,不会真正的物理删除。
  • 数据量过多,也会采用数据仓库,通过监听应用数据库的数据数据变化,进行迁移到数据仓库
  • MybatisPlus 如何使用
    • 数据库增加 deleted 字段,0 是未删除,1 表示删除
    • 实体类增加属性配置 @TableLogic 或者 在配置文件增加指定
1@TableLogic
2private Integer deleted;
  • 配置文件新增配置
1#删除是1
2mybatis-plus.global-config.db-config.logic-delete-value=1
3#未删除是0
4mybatis-plus.global-config.db-config.logic-not-delete-value=0
5
6#如果java实体类没加注解@TableLogic,则可以配置这个,推荐这里配置
7mybatis-plus.global-config.db-config.logic-delete-field=deleted

验证

  • deleteById 删除后就是,结果就是更新 字段 delete = 1
  • 查询的时候会自动拼接上 deleted=0 的检索条件

Mybatis-plus-generator 代码自动生成工具

  • Mybatis-plus-generator 介绍
    • AutoGenerator 是 MyBatis-Plus 的代码生成器,通过 AutoGenerator 可以快速生成 Entity、Mapper、Mapper XML、Service、Controller 等各个模块的代码,极大的提升了开发效率。
    • 底层是模板引擎技术,可以自定义生成的 Java 类模板
    • 大家以前或多或少用过基础版 mybatis-genarator
  • 进阶版 mybatis-plus-genarator 实战
    • 添加依赖
 1    <!-- 代码自动生成依赖 begin -->
 2        <dependency>
 3            <groupId>com.baomidou</groupId>
 4            <artifactId>mybatis-plus-generator</artifactId>
 5            <version>3.4.1</version>
 6        </dependency>
 7        <!-- velocity -->
 8        <dependency>
 9            <groupId>org.apache.velocity</groupId>
10            <artifactId>velocity-engine-core</artifactId>
11            <version>2.0</version>
12        </dependency>
13        <!-- 代码自动生成依赖 end-->
  • 代码(标记 TODO 的记得修改)
  1package net.xdclass.shopmanager;
  2
  3import com.baomidou.mybatisplus.annotation.DbType;
  4import com.baomidou.mybatisplus.annotation.IdType;
  5import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
  6import com.baomidou.mybatisplus.generator.AutoGenerator;
  7import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
  8import com.baomidou.mybatisplus.generator.config.GlobalConfig;
  9import com.baomidou.mybatisplus.generator.config.PackageConfig;
 10import com.baomidou.mybatisplus.generator.config.StrategyConfig;
 11import com.baomidou.mybatisplus.generator.config.rules.DateType;
 12import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
 13import org.apache.commons.lang3.StringUtils;
 14
 15import java.util.Scanner;
 16
 17/**
 18 * 小滴课堂,愿景:让技术不再难学
 19 *
 20 * @Description
 21 * @Author 二当家小D
 22 * @Remark 有问题直接联系我,源码-笔记-技术交流群
 23 * @Version 1.0
 24 **/
 25
 26public class MyBatisPlusGenerator {
 27
 28    public static void main(String[] args) {
 29        //1. 全局配置
 30        GlobalConfig config = new GlobalConfig();
 31        // 是否支持AR模式
 32        config.setActiveRecord(true)
 33                // 作者
 34                .setAuthor("二当家小D")
 35                // 生成路径,最好使用绝对路径,window路径是不一样的
 36                //TODO  TODO  TODO  TODO
 37                .setOutputDir("E:\\demo\\src\\main\\java")
 38                // 文件覆盖
 39                .setFileOverride(true)
 40                // 主键策略
 41                .setIdType(IdType.AUTO)
 42
 43                .setDateType(DateType.ONLY_DATE)
 44                // 设置生成的service接口的名字的首字母是否为I,默认Service是以I开头的
 45                .setServiceName("%sService")
 46
 47                //实体类结尾名称
 48                .setEntityName("%sDO")
 49
 50                //生成基本的resultMap
 51                .setBaseResultMap(true)
 52
 53                //不使用AR模式
 54                .setActiveRecord(false)
 55
 56                //生成基本的SQL片段
 57                .setBaseColumnList(true);
 58
 59        //2. 数据源配置
 60        DataSourceConfig dsConfig = new DataSourceConfig();
 61        // 设置数据库类型
 62        dsConfig.setDbType(DbType.MYSQL)
 63                .setDriverName("com.mysql.cj.jdbc.Driver")
 64                //TODO  TODO  TODO  TODO
 65                .setUrl("jdbc:mysql://192.168.31.101:50000/xd_shop?useSSL=false")
 66                .setUsername("root")
 67                .setPassword("123456");
 68
 69        //3. 策略配置globalConfiguration中
 70        StrategyConfig stConfig = new StrategyConfig();
 71
 72        //全局大写命名
 73        stConfig.setCapitalMode(true)
 74                // 数据库表映射到实体的命名策略
 75                .setNaming(NamingStrategy.underline_to_camel)
 76
 77                //使用lombok
 78                .setEntityLombokModel(true)
 79
 80                //使用restcontroller注解
 81                .setRestControllerStyle(true)
 82
 83                // 生成的表, 支持多表一起生成,以数组形式填写
 84                //TODO  TODO  TODO  TODO 两个方式,直接写,或者使用命令行输入
 85                .setInclude("product","banner","address","coupon","product_order");
 86                //.setInclude(scanner("表名,多个英文逗号分割").split(","));
 87
 88        //4. 包名策略配置
 89        PackageConfig pkConfig = new PackageConfig();
 90        pkConfig.setParent("net.xdclass.shopmanager")
 91                .setMapper("mapper")
 92                .setService("service")
 93                .setController("controller")
 94                .setEntity("model")
 95                .setXml("mapper");
 96
 97        //5. 整合配置
 98        AutoGenerator ag = new AutoGenerator();
 99        ag.setGlobalConfig(config)
100                .setDataSource(dsConfig)
101                .setStrategy(stConfig)
102                .setPackageInfo(pkConfig);
103
104        //6. 执行操作
105        ag.execute();
106        System.out.println("======= 小滴课堂 Done 相关代码生成完毕  ========");
107    }
108
109    /**
110     * <p>
111     * 读取控制台内容
112     * </p>
113     */
114    public static String scanner(String tip) {
115        Scanner scanner = new Scanner(System.in);
116        StringBuilder help = new StringBuilder();
117        help.append("请输入" + tip + ":");
118        System.out.println(help.toString());
119        if (scanner.hasNext()) {
120            String ipt = scanner.next();
121            if (StringUtils.isNotBlank(ipt)) {
122                return ipt;
123            }
124        }
125        throw new MybatisPlusException("请输入正确的" + tip + "!");
126    }
127}
128

自动化生成代码-加入项目

  • 对比生成的代码进行配置
    • 数据库连接和库名称
    • 需要生成的表
    • 生成的路径
  • 拷贝自动生成的代码进入到项目
    • model 类拷贝
    • mapper 类拷贝
    • mapper XML 脚本拷贝
    • service 和 controller 不拷贝
  • 注意
    • 使用起来和普通版的 MyBatis generator 一样,但是这个纯代码,不用复杂 XML 配置
    • 任何框架,不要使用过多的侵入或者框架定制化深的内容,防止后续改动耦合性高,成本大

总结

  • 优点
 1无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
 2
 3损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
 4
 5强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
 6
 7内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
 8
 9内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
10
11内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作
  • 缺点
1项目映入了第三方包,未来升级存在一定的兼容性问题
2
3社区相对新生-文档缺乏相关的信息, 或者更新不及时

项目使用建议

  • 任何框架或技术肯定有利也有弊,看的角度和结合团队实际情况
  • 高内聚-低解耦肯定是软件设计思想必须要遵守的原则,所以业务代码可以适当使用 MyBatisPlus 好的功能
    • 好用的:通用 crud、自动生成工具、分页查询
    • 有点耦合但也不错的功能:逻辑删除、乐观锁等
    • AR 则不怎么建议使用
  • 偏业务型项目、管理后端项目等推荐使用,和 jpa 类似

作者:Soulboy