updateWrapper) {
return ServiceImpl.retBool(baseMapper.update(entity, updateWrapper));
}
/**
*
* 判断数据库操作是否成功
*
*
* 注意!! 该方法为 Integer 判断,不可传入 int 基本类型
*
*
* @param result 数据库操作返回影响条数
* @return boolean
*/
protected static boolean retBool(Integer result) {
return SqlHelper.retBool(result);
}
/**
*
* 判断数据库操作是否成功
*
*
* @param result 数据库操作返回影响条数
* @return boolean
*/
public static boolean retBool(Integer result) {
return null != result && result >= 1;
}
```
哈哈,是不是我们自己也会这样写啊!
## 查询
接下来,我们一起讨论下查询吧。
MP 3.x,查询接口发生了很大的变化,反正我是不喜欢的,你就弄一个什么开头啊,到时候,我一点就知道有哪些方法了,他这里有 `list*`, `get*`,反正就是一个字——没必要。
先看下接口说明:
```java
/**
*
* 查询列表
*
*
* @param queryWrapper 实体对象封装操作类
* {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
*/
List list(Wrapper queryWrapper);
/**
*
* 根据 ID 查询
*
*
* @param id 主键ID
*/
T getById(Serializable id);
/**
*
* 根据 Wrapper,查询一条记录
*
*
* @param queryWrapper 实体对象封装操作类
* {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
*/
T getOne(Wrapper queryWrapper);
```
嗯,差不多了吧,这样需要注意这样一个方法:
```java
/**
*
* 从list中取第一条数据返回对应List中泛型的单个结果
*
*
* @param list
* @param
* @return
*/
public static E getObject(List list) {
if (CollectionUtils.isNotEmpty(list)) {
int size = list.size();
if (size > 1) {
SqlHelper.logger.warn(
String.format("Warn: execute Method There are %s results.", size));
}
return list.get(0);
}
return null;
}
```
**下面说下分页的问题**
根据官网的说法,需要借助插件,这我们是可以理解。
在Spring Boot启动类里面添加:
```java
/**
* 分页插件
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
```
这样就可以使用他提供的分页接口了:
```java
/**
*
* 翻页查询
*
*
* @param page 翻页对象
* @param queryWrapper 实体对象封装操作类
* {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
*/
IPage page(IPage page, Wrapper queryWrapper);
```
我们去看一下:
```java
@Override
public IPage page(IPage page, Wrapper queryWrapper) {
queryWrapper = (Wrapper) SqlHelper.fillWrapper(page, queryWrapper);
return baseMapper.selectPage(page, queryWrapper);
}
/**
*
* 填充Wrapper
*
*
* @param page 分页对象
* @param wrapper SQL包装对象
*/
@SuppressWarnings("unchecked")
public static Wrapper> fillWrapper(IPage> page, Wrapper> wrapper) {
if (null == page) {
return wrapper;
}
if (ArrayUtils.isEmpty(page.ascs())
&& ArrayUtils.isEmpty(page.descs())
&& ObjectUtils.isEmpty(page.condition())) {
return wrapper;
}
QueryWrapper qw;
if (null == wrapper) {
qw = new QueryWrapper<>();
} else {
qw = (QueryWrapper) wrapper;
}
// 排序
if (ArrayUtils.isNotEmpty(page.ascs())) {
qw.orderByAsc(page.ascs());
}
if (ArrayUtils.isNotEmpty(page.descs())) {
qw.orderByDesc(page.descs());
}
// MAP 参数查询
if (ObjectUtils.isNotEmpty(page.condition())) {
qw.allEq(page.condition());
}
return qw;
}
/**
*
* 根据 entity 条件,查询全部记录(并翻页)
*
*
* @param page 分页查询条件(可以为 RowBounds.DEFAULT)
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
IPage selectPage(IPage page, @Param(Constants.WRAPPER) Wrapper queryWrapper);
```
分页的代码大抵就是这样,我之前也自己写过,思路还是相当来说比较简单,关键是看你的查询添加如何封装,分页类如何构造。
这里有一点说明:
分页从 **`1`** 开始 !!!
## 枚举类
1、实现 接口
```java
/**
*
* 自定义枚举接口
*
*
* @author hubin
* @since 2017-10-11
*/
public interface IEnum {
/**
* 枚举数据库存储值
*/
T getValue();
}
```
2、实现注意
```
@Override
public Integer getValue() {
return this.value;
}
@JsonValue
public String getDesc() {
return desc;
}
```
这是Jackson的写法,我没用FastJson,所以用的伙伴,去官网看一下:[FastJson看官网](http://mp.baomidou.com/#/enum?id=%E4%BA%8C%E3%80%81fastjson)。
3:被忘了在配置文件中添加扫描:
```yaml
mybatis-plus:
# 扫描枚举类 # 支持统配符 * 或者 ; 分割
type-enums-package: com.fengwenyi.mp3demo.enums
```
差不多了吧,好像
## 逻辑删除
1、代码生成器中配置:
```java
new StrategyConfig().setLogicDeleteFieldName("is_delete") // 逻辑删除属性名称
```
或者,你可以手写,参考:
```java
@ApiModelProperty(value = "是否逻辑删除(true:删除;false:正常(默认))")
@TableLogic
private Boolean isDelete;
```
2、自定义数据库的值:
```yaml
mybatis-plus:
global-config:
db-config:
#逻辑删除配置
logic-delete-value: 1
logic-not-delete-value: 0
```
## 逻辑删除
## 乐观锁
## SQL性能分析
## MyBatis-Plus-Example
MyBatis-Plus的代码都会上传到github上
https://github.com/fengwenyi/MyBatis-Plus-Example
## 参考资料
* [MyBatis-Plus](http://mp.baomidou.com/#/)
* [MyBatis-Plus 使用枚举自动关联注入](https://www.imooc.com/article/details/id/29760)
* [mybatis-plus插件使用的一些问题](https://www.jianshu.com/p/a5c9bab9584a)
* [设计模式之Builder模式](https://www.jianshu.com/p/e2a2fe3555b9)
* [修复Long类型太长,而Java序列化JSON丢失精度问题的方法](https://www.jianshu.com/p/fbcdcfc7cd12)
================================================
FILE: doc/01-SpringBoot整合MyBatis-Plus.md
================================================
================================================
FILE: doc/02-mybatis-plus-example.sql
================================================
/*
Navicat Premium Data Transfer
Source Server : localhost.01-192.168.16.128
Source Server Type : MySQL
Source Server Version : 80021
Source Host : 192.168.16.128:3306
Source Schema : mybatis-plus-example
Target Server Type : MySQL
Target Server Version : 80021
File Encoding : 65001
Date: 07/03/2021 18:15:28
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for shop_category
-- ----------------------------
DROP TABLE IF EXISTS `shop_category`;
CREATE TABLE `shop_category` (
`id` bigint(0) NOT NULL COMMENT '主键ID',
`name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '商品类别名称',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin ROW_FORMAT = Dynamic;
-- ----------------------------
-- Table structure for shop_goods
-- ----------------------------
DROP TABLE IF EXISTS `shop_goods`;
CREATE TABLE `shop_goods` (
`id` bigint(0) NOT NULL COMMENT '主键ID',
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '商品名称',
`category_id` bigint(0) DEFAULT NULL COMMENT '商品类别ID',
`stock_num` bigint(0) DEFAULT NULL COMMENT '库存数量',
`price` decimal(9, 4) DEFAULT NULL COMMENT '商品单价',
`flag` tinyint(1) DEFAULT NULL COMMENT '上下架。0:下架;1:上架。默认0。',
`delete_status` tinyint(1) DEFAULT NULL COMMENT '逻辑删除状态。0:正常;1:删除。默认0。',
`create_time` datetime(0) DEFAULT NULL COMMENT '创建时间',
`create_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '创建人',
`update_time` datetime(0) DEFAULT NULL COMMENT '更新时间',
`update_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '修改人',
`version` int(0) DEFAULT NULL COMMENT '版本。默认:0。',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS = 1;
================================================
FILE: doc/03-MyBatis-Plus代码生成器的使用.md
================================================
================================================
FILE: doc/04-CRUD.md
================================================
# CRUD
- 增加(Create)
- 检索(Retrieve)
- 更新(Update)
- 删除(Delete)
对于MyBatis-Plus而言,增删改查,有三种方式实现。
1、使用MyBatis-Plus提供的服务接口。
2、使用MyBatis的Mapper接口。
3、使用Mybatis-Plus提供的AR特性,Model可进行CRUD操作。
AR即为ActiveRecord,是一种领域模型模式,一个模型类对应一个表。通过实体类对象直接进行表的CRUD操作。
## MyBatis-Plus服务接口
[CategoryRepositoryTests](../src/test/java/com.fengwenyi.mybatisplusexample.CategoryRepositoryTests)
### 数据添加
```
mpXxxService.save(entity);
```
### 数据删除
```
mpXxxService.removeById(entity.getId());
```
### 数据查询
```
mpXxxService.list(queryWrapper);
```
### 数据修改
```
mpXxxService.updateById(entity);
```
## MyBatis数据库操作Mapper接口
[CategoryMapperTests](../src/test/java/com.fengwenyi.mybatisplusexample.CategoryMapperTests)
### 数据添加
```
xxxMapper.insert(entity);
```
### 数据删除
```
xxxMapper.deleteById(entity);
```
### 数据查询
```
xxxMapper.selectList(queryWrapper);
```
### 数据修改
```
xxxMapper.updateById(entity);
```
## Mybatis-Plus提供的AR
[CategoryModelTests](../src/test/java/com.fengwenyi.mybatisplusexample.CategoryModelTests)
### 数据添加
```
xxxModel.insert();
```
### 数据删除
```
xxxModel.deleteById();
```
### 数据修改
```
xxxModel.updateById();
```
================================================
FILE: doc/05-mybatis知识点.md
================================================
================================================
FILE: doc/06-MyBatis-Plus条件查询.md
================================================
# MyBatis-Plus条件查询
## Wrapper
### QueryWrapper
查询条件构造器
### LambdaQueryWrapper
Lambda的使用
### LambdaQueryChainWrapper
链式查询
================================================
FILE: doc/07-MyBatis-Plus分页查询.md
================================================
================================================
FILE: doc/08-MyBatis-Plus数据库枚举实现.md
================================================
# 枚举
================================================
FILE: doc/09-MyBatis-Plus乐观锁.md
================================================
# 乐观锁
添加拦截器
```
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); // 乐观锁插件
```
乐观锁字段注解:
```
@Version
```
================================================
FILE: doc/10-MyBatis-Plus多数据源(动态).md
================================================
================================================
FILE: doc/11-MyBatis-Plus连表查询.md
================================================
================================================
FILE: doc/12-使用p6spy-SQL打印和性能分析.md
================================================
================================================
FILE: doc/13-MyBatis-Plus逻辑删除.md
================================================
================================================
FILE: doc/14-MyBatis-Plus数据安全保护.md
================================================
================================================
FILE: doc/15-MyBatis-Plus字段填充.md
================================================
# 自动填充
@TableField(.. fill = FieldFill.INSERT)
```
/**
* 默认不处理
*/
DEFAULT,
/**
* 插入填充字段
*/
INSERT,
/**
* 更新填充字段
*/
UPDATE,
/**
* 插入和更新填充字段
*/
INSERT_UPDATE
```
实现元对象处理器接口:com.baomidou.mybatisplus.core.handlers.MetaObjectHandler
```
注意事项:
- 填充原理是直接给entity的属性设置值!!!
- 注解则是指定该属性在对应情况下必有值,如果无值则入库会是null
- MetaObjectHandler提供的默认方法的策略均为:如果属性有值则不覆盖,如果填充值为null则不填充
- 字段必须声明TableField注解,属性fill选择对应策略,该声明告知Mybatis-Plus需要预留注入SQL字段
- 填充处理器MyMetaObjectHandler在 Spring Boot 中需要声明@Component或@Bean注入
- 要想根据注解FieldFill.xxx和字段名以及字段类型来区分必须使用父类的strictInsertFill或者strictUpdateFill方法
- 不需要根据任何来区分可以使用父类的fillStrategy方法
```
还需要再研究研究
================================================
FILE: doc/version/3.2.1.md
================================================
# 3.2.1
| 项 | 说明 |
| --- | --- |
| 构建时间 | 2021.02.02 |
| 发布时间 | |
| 版本号 | 3.2.1 |
## 新特性
## 优化
## 删除
## 文档
## 开发者
================================================
FILE: pom.xml
================================================
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.4.2
com.fengwenyi
MyBatis-Plus-Example
3.2.1-BUILD
jar
MyBatis-Plus-Example
Spring Boot 整合 MyBatis Plus 实例
1.8
2.9.2
2.1.1
3.4.2
1.2.59
2.3.1
org.springframework.boot
spring-boot-starter-web
mysql
mysql-connector-java
runtime
org.projectlombok
lombok
true
org.springframework.boot
spring-boot-starter-test
test
com.baomidou
mybatis-plus-boot-starter
${mybatis-plus.version}
io.springfox
springfox-swagger2
${swagger2.version}
io.springfox
springfox-swagger-ui
${swagger2.version}
com.fengwenyi
JavaLib
${JavaLib.version}
com.fengwenyi
api-result
${api-result.version}
p6spy
p6spy
3.9.1
org.springframework.boot
spring-boot-maven-plugin
================================================
FILE: src/main/java/com/fengwenyi/mybatisplusexample/MybatisPlusExampleApplication.java
================================================
package com.fengwenyi.mybatisplusexample;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MybatisPlusExampleApplication {
public static void main(String[] args) {
SpringApplication.run(MybatisPlusExampleApplication.class, args);
}
}
================================================
FILE: src/main/java/com/fengwenyi/mybatisplusexample/config/MyBatisPlusConfiguration.java
================================================
package com.fengwenyi.mybatisplusexample.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author Erwin Feng
* @since 2021-03-08
*/
@Configuration
@MapperScan("com.fengwenyi.mybatisplusexample.mapper")
public class MyBatisPlusConfiguration {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); // 分页插件
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); // 乐观锁插件
return interceptor;
}
}
================================================
FILE: src/main/java/com/fengwenyi/mybatisplusexample/entity/CategoryEntity.java
================================================
package com.fengwenyi.mybatisplusexample.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableField;
import java.io.Serializable;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
*
*
*
*
* @author Erwin Feng
* @since 2021-03-07
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("shop_category")
public class CategoryEntity extends Model {
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
/**
* 商品类别名称
*/
@TableField("name")
private String name;
@Override
protected Serializable pkVal() {
return this.id;
}
}
================================================
FILE: src/main/java/com/fengwenyi/mybatisplusexample/entity/GoodsEntity.java
================================================
package com.fengwenyi.mybatisplusexample.entity;
import java.math.BigDecimal;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import java.time.LocalDateTime;
import java.io.Serializable;
import com.fengwenyi.mybatisplusexample.entity.enums.GoodsFlagEnum;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
*
*
*
*
* @author Erwin Feng
* @since 2021-03-07
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("shop_goods")
public class GoodsEntity extends Model {
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
/**
* 商品名称
*/
@TableField("name")
private String name;
/**
* 商品类别ID
*/
@TableField("category_id")
private Long categoryId;
/**
* 库存数量
*/
@TableField("stock_num")
private Long stockNum;
/**
* 商品单价
*/
@TableField("price")
private BigDecimal price;
/**
* 上下架。0:下架;1:上架。默认0。
*/
@TableField("flag")
private GoodsFlagEnum flag;
/**
* 逻辑删除状态。0:正常;1:删除。默认0。
*/
@TableField("delete_status")
@TableLogic
private Boolean deleteStatus;
/**
* 创建时间
*/
@TableField(value = "create_time", fill = FieldFill.INSERT)
private LocalDateTime createTime;
/**
* 创建人
*/
@TableField(value = "create_by", fill = FieldFill.INSERT)
private String createBy;
/**
* 更新时间
*/
@TableField(value = "update_time", fill = FieldFill.UPDATE)
private LocalDateTime updateTime;
/**
* 修改人
*/
@TableField(value = "update_by", fill = FieldFill.UPDATE)
private String updateBy;
/**
* 版本。默认:0。
*/
@TableField("version")
@Version
private Integer version;
@Override
protected Serializable pkVal() {
return this.id;
}
}
================================================
FILE: src/main/java/com/fengwenyi/mybatisplusexample/entity/enums/GoodsFlagEnum.java
================================================
package com.fengwenyi.mybatisplusexample.entity.enums;
import com.baomidou.mybatisplus.annotation.IEnum;
import lombok.Getter;
/**
* @author Erwin Feng
* @since 2021-03-08
*/
@Getter
public enum GoodsFlagEnum implements IEnum {
DOWN(0, "下架"),
UP(1, "上架"),
;
private final Integer value;
private final String desc;
GoodsFlagEnum(Integer value, String desc) {
this.value = value;
this.desc = desc;
}
@Override
public Integer getValue() {
return this.value;
}
}
================================================
FILE: src/main/java/com/fengwenyi/mybatisplusexample/handler/MyBatisPlusAutoFillMetaObjectHandler.java
================================================
package com.fengwenyi.mybatisplusexample.handler;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
/**
* @author Erwin Feng
* @since 2021-04-01
*/
@Slf4j
@Component
public class MyBatisPlusAutoFillMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
metaObject.setValue("createTime", LocalDateTime.now());
// log.info("start insert fill ....");
// this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now()); // 起始版本 3.3.0(推荐使用)
// 或者
// this.strictUpdateFill(metaObject, "createTime", () -> LocalDateTime.now(), LocalDateTime.class); // 起始版本 3.3.3(推荐)
// 或者
// this.fillStrategy(metaObject, "createTime", LocalDateTime.now()); // 也可以使用(3.3.0 该方法有bug)
}
@Override
public void updateFill(MetaObject metaObject) {
metaObject.setValue("updateTime", LocalDateTime.now());
// log.info("start update fill ....");
// this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now()); // 起始版本 3.3.0(推荐)
// 或者
// this.strictUpdateFill(metaObject, "updateTime", LocalDateTime::now, LocalDateTime.class); // 起始版本 3.3.3(推荐)
// 或者
// this.fillStrategy(metaObject, "updateTime", LocalDateTime.now()); // 也可以使用(3.3.0 该方法有bug)
}
}
================================================
FILE: src/main/java/com/fengwenyi/mybatisplusexample/mapper/ICategoryMapper.java
================================================
package com.fengwenyi.mybatisplusexample.mapper;
import com.fengwenyi.mybatisplusexample.entity.CategoryEntity;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
*
* Mapper 接口
*
*
* @author Erwin Feng
* @since 2021-03-07
*/
public interface ICategoryMapper extends BaseMapper {
}
================================================
FILE: src/main/java/com/fengwenyi/mybatisplusexample/mapper/IGoodsMapper.java
================================================
package com.fengwenyi.mybatisplusexample.mapper;
import com.fengwenyi.mybatisplusexample.entity.GoodsEntity;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
*
* Mapper 接口
*
*
* @author Erwin Feng
* @since 2021-03-07
*/
public interface IGoodsMapper extends BaseMapper {
}
================================================
FILE: src/main/java/com/fengwenyi/mybatisplusexample/repository/MPCategoryRepository.java
================================================
package com.fengwenyi.mybatisplusexample.repository;
import com.fengwenyi.mybatisplusexample.entity.CategoryEntity;
import com.baomidou.mybatisplus.extension.service.IService;
/**
*
* 服务类
*
*
* @author Erwin Feng
* @since 2021-03-07
*/
public interface MPCategoryRepository extends IService {
}
================================================
FILE: src/main/java/com/fengwenyi/mybatisplusexample/repository/MPGoodsRepository.java
================================================
package com.fengwenyi.mybatisplusexample.repository;
import com.fengwenyi.mybatisplusexample.entity.GoodsEntity;
import com.baomidou.mybatisplus.extension.service.IService;
/**
*
* 服务类
*
*
* @author Erwin Feng
* @since 2021-03-07
*/
public interface MPGoodsRepository extends IService {
}
================================================
FILE: src/main/java/com/fengwenyi/mybatisplusexample/repository/impl/CategoryRepositoryImpl.java
================================================
package com.fengwenyi.mybatisplusexample.repository.impl;
import com.fengwenyi.mybatisplusexample.entity.CategoryEntity;
import com.fengwenyi.mybatisplusexample.mapper.ICategoryMapper;
import com.fengwenyi.mybatisplusexample.repository.MPCategoryRepository;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
*
* 服务实现类
*
*
* @author Erwin Feng
* @since 2021-03-07
*/
@Service
public class CategoryRepositoryImpl extends ServiceImpl implements MPCategoryRepository {
}
================================================
FILE: src/main/java/com/fengwenyi/mybatisplusexample/repository/impl/GoodsRepositoryImpl.java
================================================
package com.fengwenyi.mybatisplusexample.repository.impl;
import com.fengwenyi.mybatisplusexample.entity.GoodsEntity;
import com.fengwenyi.mybatisplusexample.mapper.IGoodsMapper;
import com.fengwenyi.mybatisplusexample.repository.MPGoodsRepository;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
*
* 服务实现类
*
*
* @author Erwin Feng
* @since 2021-03-07
*/
@Service
public class GoodsRepositoryImpl extends ServiceImpl implements MPGoodsRepository {
}
================================================
FILE: src/main/resources/application-dev.yml
================================================
#spring
spring:
datasource:
# driver-class-name: com.mysql.jdbc.Driver
# url: jdbc:mysql://192.168.16.128:3306/mybatis-plus-example
username: root
# password: kU#m5eHY5iTiQj#q
password: 123456
driver-class-name: com.p6spy.engine.spy.P6SpyDriver
url: jdbc:p6spy:mysql://192.168.16.128:3306/mybatis-plus-example
# url: mpw:pBZqJb+r/StFGyRopKJyhZN8dvstxaXxubewECBMWM3e7XK+719AUXlC1y1Cu14i1MwqEdiJbBa+sEwFzyWEgA==
# username: mpw:hjR022j+cjKFE+35FLTQgg==
# password: mpw:kzLGIBmi4hT+dPmqnXLAIw==
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
logback:
logDir: log/dev
logging:
level:
com.fengwenyi.mybatis_plus_example.service.impl: trace
com.fengwenyi.mybatis_plus_example.controller: trace
================================================
FILE: src/main/resources/application-prod.yml
================================================
================================================
FILE: src/main/resources/application-test.yml
================================================
================================================
FILE: src/main/resources/application.yml
================================================
#app
server:
port: 8080
spring:
application:
name: mybatis-plus-example
profiles:
active: dev
#mybatis
mybatis-plus:
# xml
mapper-locations: classpath:mapper/*Mapper.xml
# 实体扫描,多个package用逗号或者分号分隔
type-aliases-package: com.fengwenyi.mybatisplusexample.entity
# 扫描枚举类 # 支持统配符 * 或者 ; 分割
type-enums-package: com.fengwenyi.mybatisplusexample.entity.enums
global-config:
db-config:
#数据库大写下划线转换
capital-mode: true
#逻辑删除配置
# logic-delete-field: delete_status # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)
logic-delete-value: 1 # 逻辑删除
logic-not-delete-value: 0 # 正常
configuration:
map-underscore-to-camel-case: true
cache-enabled: false
default-enum-type-handler: org.apache.ibatis.type.EnumOrdinalTypeHandler
logback:
appName: mybatis-plus-example
fileType: log
================================================
FILE: src/main/resources/logback-spring.xml
================================================
${CONSOLE_LOG_PATTERN}
UTF-8
debug
${logDir}/${appName}-debug.${fileType}
%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
UTF-8
${logDir}/${appName}-debug-%d{yyyy-MM-dd}.%i.${fileType}
500MB
30
debug
ACCEPT
DENY
${logDir}/${appName}-info.${fileType}
%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
UTF-8
${logDir}/${appName}-info-%d{yyyy-MM-dd}.%i.${fileType}
500MB
30
info
ACCEPT
DENY
${logDir}/${appName}-warn.${fileType}
%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
UTF-8
${logDir}/${appName}-warn-%d{yyyy-MM-dd}.%i.${fileType}
500MB
30
warn
ACCEPT
DENY
${logDir}/${appName}-error.${fileType}
%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
UTF-8
${logDir}/${appName}-error-%d{yyyy-MM-dd}.%i.${fileType}
500MB
30
error
ACCEPT
DENY
================================================
FILE: src/main/resources/mapper/CategoryMapper.xml
================================================
================================================
FILE: src/main/resources/mapper/GoodsMapper.xml
================================================
================================================
FILE: src/main/resources/spy.properties
================================================
#3.2.1以上使用
modulelist=com.baomidou.mybatisplus.extension.p6spy.MybatisPlusLogFactory,com.p6spy.engine.outage.P6OutageFactory
#3.2.1以下使用或者不配置
#modulelist=com.p6spy.engine.logging.P6LogFactory,com.p6spy.engine.outage.P6OutageFactory
# 自定义日志打印
logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger
#日志输出到控制台
appender=com.baomidou.mybatisplus.extension.p6spy.StdoutLogger
# 使用日志系统记录 sql
#appender=com.p6spy.engine.spy.appender.Slf4JLogger
# 设置 p6spy driver 代理
deregisterdrivers=true
# 取消JDBC URL前缀
useprefix=true
# 配置记录 Log 例外,可去掉的结果集有error,info,batch,debug,statement,commit,rollback,result,resultset.
excludecategories=info,debug,result,commit,resultset
# 日期格式
dateformat=yyyy-MM-dd HH:mm:ss
# 实际驱动可多个
#driverlist=org.h2.Driver
# 是否开启慢SQL记录
outagedetection=true
# 慢SQL记录标准 2 秒
outagedetectioninterval=2
================================================
FILE: src/test/java/com/fengwenyi/mybatisplusexample/CategoryMapperTests.java
================================================
package com.fengwenyi.mybatisplusexample;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fengwenyi.mybatisplusexample.entity.CategoryEntity;
import com.fengwenyi.mybatisplusexample.mapper.ICategoryMapper;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import javax.annotation.Resource;
import java.util.List;
/**
*
* MyBatis Mapper CRUD
*
* @author Erwin Feng
* @since 2021-04-01
*/
@Component
@Slf4j
public class CategoryMapperTests extends MybatisPlusExampleApplicationTests {
private CategoryEntity entity;
@Resource
private ICategoryMapper categoryMapper;
// 创建数据
private void create() {
entity = new CategoryEntity().setName("category test data");
categoryMapper.insert(entity);
}
// 清除数据
private void clear() {
categoryMapper.deleteById(entity.getId());
}
@Test
public void testAdd() {
entity = new CategoryEntity().setName("category test data");
int resultNum = categoryMapper.insert(entity);
Assert.isTrue(resultNum == 1, "data add test failure");
clear();
}
@Test
public void testDelete() {
create();
int resultNum = categoryMapper.deleteById(entity.getId());
Assert.isTrue(resultNum == 1, "data delete test failure");
}
@Test
public void testUpdate() {
create();
entity.setName("category update");
int resultNum = categoryMapper.updateById(entity);
Assert.isTrue(resultNum == 1, "data update test failure");
clear();
}
@Test
public void testQuery() {
create();
List categoryEntityList = categoryMapper.selectList(new QueryWrapper<>());
for (CategoryEntity entity : categoryEntityList) {
log.info(entity.toString());
}
clear();
}
}
================================================
FILE: src/test/java/com/fengwenyi/mybatisplusexample/CategoryModelTests.java
================================================
package com.fengwenyi.mybatisplusexample;
import com.fengwenyi.mybatisplusexample.entity.CategoryEntity;
import org.junit.jupiter.api.Test;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
/**
*
* model test
*
*
* CRUD
*
*
* @author Erwin Feng
* @since 2021-03-30
*/
@Component
public class CategoryModelTests extends MybatisPlusExampleApplicationTests {
private CategoryEntity model;
// 创建数据
private void create() {
model = new CategoryEntity().setName("category test data");
model.insert();
}
// 清除数据
private void clear() {
model.deleteById();
}
@Test
public void testAdd() {
model = new CategoryEntity().setName("category test data");
boolean testResult = model.insert();
Assert.isTrue(testResult, "data add test failure");
clear();
}
@Test
public void testDelete() {
create();
boolean testResult = model.deleteById();
Assert.isTrue(testResult, "data delete test failure");
}
@Test
public void testUpdate() {
create();
model.setName("category update");
boolean testResult = model.updateById();
Assert.isTrue(testResult, "data update test failure");
clear();
}
}
================================================
FILE: src/test/java/com/fengwenyi/mybatisplusexample/CategoryRepositoryTests.java
================================================
package com.fengwenyi.mybatisplusexample;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fengwenyi.mybatisplusexample.entity.CategoryEntity;
import com.fengwenyi.mybatisplusexample.repository.MPCategoryRepository;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import java.util.List;
/**
*
* MPCategoryRepository test
*
*
* CRUD
*
*
* @author Erwin Feng
* @since 2021-03-08
*/
@Component
@Slf4j
public class CategoryRepositoryTests extends MybatisPlusExampleApplicationTests {
@Autowired
private MPCategoryRepository mpCategoryRepository;
private CategoryEntity entity;
// 创建数据
private void create() {
entity = new CategoryEntity().setName("category test data");
mpCategoryRepository.save(entity);
}
// 清除数据
private void clear() {
mpCategoryRepository.removeById(entity);
}
@Test
public void testAdd() {
entity = new CategoryEntity().setName("category test data");
boolean testResult = mpCategoryRepository.save(entity);
Assert.isTrue(testResult, "data add test failure");
clear();
}
@Test
public void testDelete() {
create();
boolean testResult = mpCategoryRepository.removeById(entity.getId());
Assert.isTrue(testResult, "data delete test failure");
}
@Test
public void testDeleteByWrapper() {
create();
LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper()
.eq(CategoryEntity::getName, entity.getName())
;
boolean testResult = mpCategoryRepository.remove(queryWrapper);
Assert.isTrue(testResult, "data delete by wrapper test failure");
}
@Test
public void testUpdate() {
create();
entity.setName("category update");
boolean testResult = mpCategoryRepository.updateById(entity);
Assert.isTrue(testResult, "data update test failure");
clear();
}
@Test
public void testQuery() {
create();
// 根据主键ID查询
mpCategoryRepository.getById(entity.getId());
// 查询所有
List list = mpCategoryRepository.list();
// 添加查询
LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper()
.eq(CategoryEntity::getName, entity.getName())
;
mpCategoryRepository.list(queryWrapper);
// 分页查询
int currentPage = 1;
int pageSize = 10;
Page categoryPage = mpCategoryRepository.page(new Page<>(currentPage, pageSize), queryWrapper);
long current = categoryPage.getCurrent();
long size = categoryPage.getSize();
long pages = categoryPage.getPages();
List categoryList = categoryPage.getRecords();
long total = categoryPage.getTotal();
clear();
}
}
================================================
FILE: src/test/java/com/fengwenyi/mybatisplusexample/GoodsRepositoryTests.java
================================================
package com.fengwenyi.mybatisplusexample;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fengwenyi.mybatisplusexample.entity.CategoryEntity;
import com.fengwenyi.mybatisplusexample.entity.GoodsEntity;
import com.fengwenyi.mybatisplusexample.entity.enums.GoodsFlagEnum;
import com.fengwenyi.mybatisplusexample.repository.MPCategoryRepository;
import com.fengwenyi.mybatisplusexample.repository.MPGoodsRepository;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
/**
* @author Erwin Feng
* @since 2021-03-08
*/
@Component
@Slf4j
public class GoodsRepositoryTests extends MybatisPlusExampleApplicationTests {
@Autowired
private MPCategoryRepository mpCategoryRepository;
@Autowired
private MPGoodsRepository mpGoodsRepository;
@Test
public void testAdd() {
LambdaQueryWrapper categoryQueryWrapper = new LambdaQueryWrapper()
.eq(CategoryEntity::getName, "家电")
;
List categoryEntityList = mpCategoryRepository.list(categoryQueryWrapper);
CategoryEntity categoryEntity = categoryEntityList.get(0);
GoodsEntity goodsEntity = new GoodsEntity()
.setName("平板电脑")
.setPrice(new BigDecimal("4699.00"))
.setStockNum(10000L)
.setFlag(GoodsFlagEnum.UP)
.setCategoryId(categoryEntity.getId())
.setCreateBy("admin")
;
mpGoodsRepository.save(goodsEntity);
}
@Test
public void testQuery() {
List goodsEntityList = mpGoodsRepository.list();
for (GoodsEntity goodsEntity : goodsEntityList) {
log.info(goodsEntity.toString());
log.info(goodsEntity.getFlag().getValue() + "");
}
}
@Test
public void testUpdate() {
LambdaQueryWrapper goodsQueryWrapper = new LambdaQueryWrapper().eq(GoodsEntity::getName, "平板电脑");
List goodsEntityList = mpGoodsRepository.list(goodsQueryWrapper);
GoodsEntity goodsEntity = goodsEntityList.get(0);
goodsEntity.setPrice(new BigDecimal("6499.00"));
mpGoodsRepository.updateById(goodsEntity);
}
@Test
void testQueryTime() {
LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper()
.lt(GoodsEntity::getCreateTime, LocalDateTime.parse("2021-04-08 10:00:00")) // where create_time < 2021-04-08 10:00:00
.gt(GoodsEntity::getCreateTime, LocalDateTime.parse("2021-04-09 10:00:00")) // where create_time > 2021-04-09 10:00:00
;
List list = mpGoodsRepository.list(queryWrapper);
}
}
================================================
FILE: src/test/java/com/fengwenyi/mybatisplusexample/MPWTests.java
================================================
package com.fengwenyi.mybatisplusexample;
import com.baomidou.mybatisplus.core.toolkit.AES;
import com.fengwenyi.javalib.util.PrintUtils;
import org.junit.jupiter.api.Test;
/**
* @author Erwin Feng
* @since 2021-03-31
*/
public class MPWTests {
@Test
public void test() {
// 生成 16 位随机 AES 密钥
String randomKey = AES.generateRandomKey();
PrintUtils.info(randomKey);
String prefix = "mpw:";
// 随机密钥加密
String url = "jdbc:p6spy:mysql://192.168.16.128:3306/mybatis-plus-example";
String result =prefix + AES.encrypt(url, randomKey);
PrintUtils.info(result);
String username = "root";
result =prefix + AES.encrypt(username, randomKey);
PrintUtils.info(result);
String password = "123456";
result =prefix + AES.encrypt(password, randomKey);
PrintUtils.info(result);
/*
2021-03-31 00:57:49.494 INFO com.fengwenyi.mybatisplusexample.MPWTests#test : ba8a2cea8df4929f
2021-03-31 00:57:49.871 INFO com.fengwenyi.mybatisplusexample.MPWTests#test : mpw:pBZqJb+r/StFGyRopKJyhZN8dvstxaXxubewECBMWM3e7XK+719AUXlC1y1Cu14i1MwqEdiJbBa+sEwFzyWEgA==
2021-03-31 00:57:49.871 INFO com.fengwenyi.mybatisplusexample.MPWTests#test : mpw:hjR022j+cjKFE+35FLTQgg==
2021-03-31 00:57:49.871 INFO com.fengwenyi.mybatisplusexample.MPWTests#test : mpw:kzLGIBmi4hT+dPmqnXLAIw==
*/
}
}
================================================
FILE: src/test/java/com/fengwenyi/mybatisplusexample/MybatisPlusExampleApplicationTests.java
================================================
package com.fengwenyi.mybatisplusexample;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class MybatisPlusExampleApplicationTests {
@Test
public void contextLoads() {
}
}