资料下载
https://atgfwacnz-my.sharepoint.com/:f:/g/personal/gtfonedriver_365vip_eu_org/EiXUA7XZ5dBEpNS0o_m9og0BCib9dy2vQjztVuJbf4APMg?e=HNwCS2
简介:开发环境准备和说明
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
简介:介绍javaee框架开发和实体类POJO
简介:讲解lombok的介绍和安装
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.16</version>
<scope>provided</scope>
</dependency>
<!--https://mvnrepository.com/artifact/org.projectlombok/lombok/1.18.16-->
<!--scope=provided,说明它只在编译阶段生效,不需要打入包中, Lombok在编译期将带Lombok注解的Java文件正确编译为完整的Class文件-->
简介:讲解lombok的常见注解Set/Get实战
@Setter
@Getter
public class UserDO {
/**
* 不想生成 get方法
*/
@Getter(AccessLevel.NONE)
private int age;
/**
* 控制访问权限
*/
@Getter(AccessLevel.PROTECTED)
private int salary;
/**
* final 只会生成get
*/
private final String name="小红";
/**
* 下面两个静态成员变量不会生成set/get方法
*/
static Date createTime = new Date();
private static final String address = "广东省广州市";
}
简介:讲解Lombok非空判断和构造函数注解
public void login(@NotNull String pwd){
}
简介:讲解JSR介绍和lombok原理讲解
JSR 269: Pluggable Annotation Processing API
实现在Javac编译阶段利用“Annotation Processor”对自定义的注解进行预处理后生成真正在JVM上面执行的“Class文件
地址:https://www.jcp.org/en/jsr/detail?id=269
JSR是Java Specification Requests的缩写,意思是Java 规范提案。
是指向JCP(Java Community Process)提出新增一个标准化技术规范的正式请求。
任何人都可以提交JSR,以向Java平台增添新的API和服务。JSR已成为Java界的一个重要标准。
Javac 解析成AST抽象语法树后, Lombok根据自己编写的注解处理器,动态地修改 AST增加新的节点(即Lombok自定义注解所需要生成的代码),最终生成JVM可执行的字节码Class文件
可以看编译后的在target目录下的class文件
使用Annotation Processing自定义注解是在编译阶段进行修改
JDK的反射技术是在运行时动态修改
结论:反射更加灵活一些但是带来的性能损耗更加大
简介:讲解lombok的toString()注解
@ToString(exclude = {"age"})
@ToString(of = {"name"})
简介:重温Java核心知识hashcode和equal方法
//判断地址是否⼀样
//⾮空判断和class类型判断
//强转
//对象⾥⾯的字段⼀⼀匹配
解析
如果两个对象相等,那么它们的hashCode()值一定相同(这里的相等是指,通过equals()比较两个对象时返回true) 如果两个对象hashCode()相等,它们并不一定相等。在散列表中hashCode()相等,即两个键值对的哈希值相等。 然而哈希值相等,并不一定能得出键值对相等,就出现所谓的哈希冲突场景,还需判断equals⽅法判断对象是否相等
应用场景:当向集合中插⼊对象时,如何判别在集合中是否已经存在该对象,⽐如Set确保存储对象的 唯⼀,并判断是不是同个对象呢?
依据hashCode和equals进⾏判断
所以Set存储的对象必须重写这两个⽅法 判断两个对象是否⼀样
⾸先判断插⼊obj的hashcode值是否存在,hashcode值不存在则直 接插⼊集合
值存在则还需判断equals⽅法判断对象是否相等
简介:玩转lombok的EqualsAndHashCode注解
@EqualsAndHashCode(exclude = {"age"})
@EqualsAndHashCode(of = {"name"})
简介:玩转lombok的data注解
简介:玩转设计模式之建造者模式和lombok的@Builder注解
简介:玩转lombok的@Log日志注解
** Lombok课程总结-优缺点适合场景**
@Setter/@Getter
@NonNull
@NoArgsConstructor
@AllArgsConstructor
@RequiredArgsConstructor
@ToString
@EqualsAndHashCode
@Data
@Builder
@Log
@Slf4j
简介:增强版ORM框架 mybatis plus介绍
无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
内置性能分析插件:可输出 Sql 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作
简介:使用新版SpringBoot2.x整合MybatisPlus + Lombok
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--mybatis plus和springboot整合-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.1</version>
</dependency>
server.port=8081
#==============================数据库相关配置========================================
spring.datasource.driver-class-name =com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/class_shop?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.username =root
spring.datasource.password =123456
简介:SpringBoot整合Mybatis plus项目实战
@Data
@AllArgsConstructor //会生成一个包含所有变量
@NoArgsConstructor //生成一个无参数的构造方法
public class JsonData {
/**
* 状态码 0 表示成功,1表示处理中,-1表示失败
*/
private Integer code;
/**
* 数据
*/
private Object data;
/**
* 描述
*/
private String msg;
/**
* 成功,传入数据
* @return
*/
public static JsonData buildSuccess() {
return new JsonData(0, null, null);
}
/**
* 成功,传入数据
* @param data
* @return
*/
public static JsonData buildSuccess(Object data) {
return new JsonData(0, data, null);
}
/**
* 失败,传入描述信息
* @param msg
* @return
*/
public static JsonData buildError(String msg) {
return new JsonData(-1, null, msg);
}
/**
* 失败,传入描述信息,状态码
* @param msg
* @param code
* @return
*/
public static JsonData buildError(String msg, Integer code) {
return new JsonData(code, null, msg);
}
}
@Data
@TableName("banner")//表名映射
public class BannerDO {
private Integer id;
private String img;
private String url;
private Integer weight;
}
@RestController
@RequestMapping("api/v1/banner")
public class BannerController {
@Autowired
private BannerService bannerService;
@RequestMapping("list")
public JsonData list() {
List<BannerDO> list = bannerService.list();
return JsonData.buildSuccess(list);
}
}
public interface BannerService {
List<BannerDO> list();
}
@Service
public class BannerServiceImpl implements BannerService {
@Autowired
private BannerMapper bannerMapper;
@Override
public List<BannerDO> list() {
return bannerMapper.selectList(new QueryWrapper<>());
}
}
public interface BannerMapper extends BaseMapper<BannerDO> {
}
简介:项目集成Spring Boot Test单元测试+控制台数据sql
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
@SpringBootTest(classes = TestApplication.class)
@Slf4j
class BannerTest {
@Autowired
private BannerService bannerService;
@Test
public void testBannerList(){
List<BannerDO> list = bannerService.list();
log.info("轮播图列表:{}",list);
}
}
#配置mybatis plus打印sql日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
简介:介绍MybaitsPlus核心类BaseMapper
/**
* Mapper 继承该接口后,无需编写 mapper.xml 文件,即可获得CRUD功能
* <p>这个 Mapper 支持 id 泛型</p>
*
* @author hubin
* @since 2016-01-23
*/
public interface BaseMapper<T> extends Mapper<T> {
/**
* 插入一条记录
*
* @param entity 实体对象
*/
int insert(T entity);
/**
* 根据 ID 删除
*
* @param id 主键ID
*/
int deleteById(Serializable id);
/**
* 根据 columnMap 条件,删除记录
*
* @param columnMap 表字段 map 对象
*/
int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
/**
* 根据 entity 条件,删除记录
*
* @param queryWrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)
*/
int delete(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 删除(根据ID 批量删除)
*
* @param idList 主键ID列表(不能为 null 以及 empty)
*/
int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
/**
* 根据 ID 修改
*
* @param entity 实体对象
*/
int updateById(@Param(Constants.ENTITY) T entity);
/**
* 根据 whereEntity 条件,更新记录
*
* @param entity 实体对象 (set 条件值,可以为 null)
* @param updateWrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)
*/
int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper<T> updateWrapper);
/**
* 根据 ID 查询
*
* @param id 主键ID
*/
T selectById(Serializable id);
/**
* 查询(根据ID 批量查询)
*
* @param idList 主键ID列表(不能为 null 以及 empty)
*/
List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
/**
* 查询(根据 columnMap 条件)
*
* @param columnMap 表字段 map 对象
*/
List<T> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
/**
* 根据 entity 条件,查询一条记录
*
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 Wrapper 条件,查询总记录数
*
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 entity 条件,查询全部记录
*
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 Wrapper 条件,查询全部记录
*
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 Wrapper 条件,查询全部记录
* <p>注意: 只返回第一个字段的值</p>
*
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 entity 条件,查询全部记录(并翻页)
*
* @param page 分页查询条件(可以为 RowBounds.DEFAULT)
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
<E extends IPage<T>> E selectPage(E page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 Wrapper 条件,查询全部记录(并翻页)
*
* @param page 分页查询条件
* @param queryWrapper 实体对象封装操作类
*/
<E extends IPage<Map<String, Object>>> E selectMapsPage(E page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
}
QueryWrapper介绍
List<BannerDO> list = bannerMapper.selectList(new QueryWrapper<BannerDO>());
简介:介绍MybaitsPlus多案例查询API实战
@SpringBootTest(classes = TestApplication.class)
@Slf4j
class BannerTest {
@Autowired
private BannerService bannerService;
@Autowired
private BannerMapper bannerMapper;
/**
* id查找
*/
@Test
public void testSelectById(){
BannerDO bannerDO = bannerMapper.selectById(1);
log.info("bannerDO: {}",bannerDO);
}
/**
* 批量查找
*/
@Test
public void testSelectBatchIds(){
List<BannerDO> list = bannerMapper.selectBatchIds( Arrays.asList(1,2));
log.info("bannerDO: {}",list);
}
/**
* 选择1条
*/
@Test
public void testSelectOne(){
BannerDO bannerDO = bannerMapper.selectOne(new QueryWrapper<BannerDO>().eq("id",1));
log.info("bannerDO: {}",bannerDO);
}
/**
* 统计行数
*/
@Test
public void testSelectCount(){
int size = bannerMapper.selectCount(null);
log.info("bannerDO: {}",size);
}
/***
* 查找全部数据
*/
@Test
public void testBannerList(){
List<BannerDO> list = bannerService.list();
log.info("轮播图列表:{}",list);
}
}
简介:讲解 Mybatis plus 常用注解
value 用于定义非主键字段名,用于别名匹配,假如java对象属性和数据库属性不一样
exist 用于指明是否为数据表的字段, true 表示是,false 为不是,假如某个java属性在数据库没对应的字段则要标记为faslse
fill 用于指定字段填充策略(FieldFill,用的不多)
字段填充策略:一般用于填充 创建时间、修改时间等字段
FieldFill.DEFAULT 默认不填充
FieldFill.INSERT 插入时填充
FieldFill.UPDATE 更新时填充
FieldFill.INSERT_UPDATE 插入、更新时填充。
简介: 案例实战 Mybatis Plus 新增测试用例编写
简介: 案例实战 MybatisPlus 多种update更新操作
简介:介绍MybaitsPlus核心查询条件类QueryWrapper的比较API讲解
简介:介绍QueryWrapper的模糊查询和其他API讲解
/***
* 新增
*/
@Test
public void testAdd(){
BannerDO bannerDO = new BannerDO();
bannerDO.setImg("xxxxx");
bannerDO.setUrl("xdcalss.net");
bannerMapper.insert(bannerDO);
log.info("轮播图:{}",bannerDO);
}
@Test
public void testDeleteId(){
int rows = bannerMapper.deleteById(4);
log.info("rows:{}",rows);
}
@Test
public void testDeleteByMap(){
Map<String,Object> columnMap = new HashMap<>();
columnMap.put("weight",12);
columnMap.put("url","bbb");
int rows = bannerMapper.deleteByMap(columnMap);
log.info("rows:{}",rows);
}
/**
* 更新
*/
@Test
public void testUpdate(){
BannerDO bannerDO = new BannerDO();
bannerDO.setUrl("taobao.com");
int rows = bannerMapper.update(bannerDO,new QueryWrapper<BannerDO>().eq("id",1));
log.info("rows:{}",rows);
}
/**
* 更新
*/
@Test
public void testUpdateWrapper(){
UpdateWrapper updateWrapper = new UpdateWrapper();
updateWrapper.set("url","aaaa.com");
updateWrapper.eq("id",1);
int rows = bannerMapper.update(null,updateWrapper);
log.info("rows:{}",rows);
}
/**
* * eq 等于
* * ne 不等于
* * gt 大于
* * ge 大于等于
* * lt 小于
* * le 小于等于
* * or 拼接or
* * between 两个值中间
* * notBetween 不在两个值中间
*/
@Test
public void testQueryWrapper1(){
//SELECT id,img,url,weight AS weightAAA FROM banner WHERE (id = ? AND url <> ?)
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.eq("id",1);
queryWrapper.or();
queryWrapper.ne("url","bbbc.com");
bannerMapper.selectList(queryWrapper);
}
/**
* * like 模糊匹配
* * notLike 不像
* * likeLeft 左匹配
* * likeRight 右边匹配
* * isNull 字段为空
* * in in查询
* * groupBy 分组
* * orderByAsc 升序
* * orderByEdsc 降序
* * having having查询
*/
@Test
public void testQueryWrapper2(){
QueryWrapper queryWrapper = new QueryWrapper();
// queryWrapper.like("url","bbb");
// queryWrapper.notLike("img","cccc");
//SELECT id,img,url,weight AS weightAAA FROM banner WHERE (url LIKE ? AND img NOT LIKE ?)
//queryWrapper.likeLeft("url","bbb");
//queryWrapper.likeRight("img","cccc");
queryWrapper.isNull("img");
queryWrapper.in("url",Arrays.asList("aaaa","bbbb"));
queryWrapper.orderByDesc("id");
//SELECT id,img,url,weight AS weightAAA FROM banner WHERE (img IS NULL AND url IN (?,?)) ORDER BY id DESC
bannerMapper.selectList(queryWrapper);
}
/**
* 测试分页功能
*/
@Test
public void testPage(){
// QueryWrapper<BannerDO> queryWrapper = new QueryWrapper();
// queryWrapper.eq("weight",4);
//第一页,每页3条, 如果是第一页则直接一个问号,获取条数
Page<BannerDO> page = new Page<>(2,2);
IPage<BannerDO> iPage = bannerMapper.selectPage(page,null);
log.info("总条数:{}",iPage.getTotal());
log.info("总页数:{}",iPage.getPages());
log.info("数据:{}",iPage.getRecords());
}
简介: 案例实战 Mybatis plus 分页插件配置
@Configuration
public class MybatisPlusPageConfig {
/* 旧版本配置
@Bean
public PaginationInterceptor paginationInterceptor(){
return new PaginationInterceptor();
}*/
/**
* 新的分页插件
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
/***
* 测试分页
*/
@Test
public void testPage() {
// QueryWrapper<BannerDO> queryWrapper = new QueryWrapper<>();
Page<BannerDO> bannerDOPage = new Page<>(1, 2);
IPage<BannerDO> iPage = bannerMapper.selectPage(bannerDOPage, null);
log.info("总条数:{}", iPage.getTotal());
log.info("总页数:{}", iPage.getPages());
log.info("数据:{}", iPage.getRecords());
}
简介: 案例实战 Mybatis plus 自定义sql脚本
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--这个名称空间是Mapper接口的路径,记得修改-->
<mapper namespace="net.classes.mapper.BannerMapper">
</mapper>
#配置plus打印sql日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
#默认配置路径
mybatis-plus.mapper-locations=classpath*:/mapper/*Mapper.xml
简介:讲解 Mybatis plus全局配置案例
#配置文件
server.port=8081
#==============================数据库相关配置
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://192.168.0.114:3306/xd_shop?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=xdclass.net
#开启控制台打印sql
#mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
#配置mybatis plus打印sql日志
#mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
#配置最新全局配置文件!!!!
mybatis-plus.config-location = classpath:mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<!--控制台输出日志-->
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
</configuration>
mybatis-plus.type-aliases-package= net.xdclass.shop.model
<!--旧-->
<select id="list" resultType="net.xdclass.shop.model.BannerDO">
select * from banner
</select>
<!--新-->
<select id="list" resultType="BannerDO">
select * from banner
</select>
mybatis-plus.configuration.map-underscore-to-camel-case=true
mybatis-plus.global-config.db-config.id-type=auto
简介: 性能优化之指定select字段查询
bannerMapper.selectList(new QueryWrapper<BannerDO>().select("id","name"));
简介: 讲解什么是ActiveRecord和使用
@Data
//表名映射,用于新增才需要
@TableName("banner")
public class BannerDO extends Model<BannerDO> {
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
private String img;
private String url;
private Integer weight;
}
/***
* 领域活动
*/
@Test
public void testModelAR() {
BannerDO bannerDO = new BannerDO();
List<BannerDO> bannerDOS = bannerDO.selectList(null);
bannerDOS.stream().forEach(obj-> System.out.println(obj));
}
简介: 讲解高并发里面的乐观锁介绍
每次去拿数据的时候都认为别人不会修改,更新的时候会判断是别人是否回去更新数据,通过版本来判断,如果数据被修改了就拒绝更新
Java里面大量使用CAS, CAS这个是属于乐观锁,性能较悲观锁有很大的提高
AtomicXXX 等原子类底层就是CAS实现,一定程度比synchonized好,因为后者是悲观锁
小结:悲观锁适合写操作多的场景,乐观锁适合读操作多的场景,乐观锁的吞吐量会比悲观锁多
大多是基于数据版本 (Version)记录机制实现。何谓数据版本?即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通
过为数据库表增加一个 “version” 字段来 实现。 读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。此时,将提交数据的版本数据与数据,库表对应记录的当前版本信息进行比对,如果提交的数据 版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据
简介: 讲解MybatisPlus乐观锁插件使用
@Version
private Integer version;
CREATE TABLE `banner` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`img` varchar(524) DEFAULT NULL COMMENT '图片',
`url` varchar(524) DEFAULT NULL COMMENT '跳转地址',
`weight` int(11) DEFAULT NULL COMMENT '权重',
`version` int(11) DEFAULT '1' COMMENT '乐观锁版本号',
`deleted` int(11) DEFAULT '0' COMMENT '0是未删除,1是已经删除',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8mb4;
/**
* 分页假乐观锁
* @return
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
//分页插件
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
//乐观锁插件
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
/***
* 乐观锁测试
*/
@Test
public void testOptimi() {
BannerDO bannerDO = new BannerDO();
bannerDO.setVersion(2);//旧版本号,即查询出来的版本号
bannerDO.setId(1);
bannerDO.setUrl("baidu.com");
bannerMapper.updateById(bannerDO);
}
简介: 讲解MybatisPlus 逻辑删除配置
很多互联网公司在数据库设计规范中都加入了逻辑删除的强制规定,运营人员可以分析和审查数据,也方便将数据沉淀下来用于商业分析
比如用户删除了订单,只不过是更新了标记,不会真正的物理删除。
// @TableLogic
private Integer deleted;
#删除是1
mybatis-plus.global-config.db-config.logic-delete-value=1
#未删除是0
mybatis-plus.global-config.db-config.logic-not-delete-value=0
#如果java实体类没加注解@TableLogic,则可以配置这个,推荐这里配置
mybatis-plus.global-config.db-config.logic-delete-field=deleted
简介:介绍Mybatis-plus-generator代码自动化生成工具
<!-- 代码自动生成依赖 begin -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.4.1</version>
</dependency>
<!-- velocity -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.0</version>
</dependency>
<!-- 代码自动生成依赖 end-->
package db;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import org.junit.platform.commons.util.StringUtils;
import java.util.Scanner;
public class MyBatisPlusGenerator {
public static void main(String[] args) {
//1. 全局配置
GlobalConfig config = new GlobalConfig();
// 是否支持AR模式
config.setActiveRecord(true)
// 作者
.setAuthor("gaobei")
// 生成路径,最好使用绝对路径,window路径是不一样的
//TODO TODO TODO TODO
.setOutputDir("/Users/class/Desktop/demo/src/main/java")
// 文件覆盖
.setFileOverride(true)
// 主键策略
.setIdType(IdType.AUTO)
.setDateType(DateType.ONLY_DATE)
// 设置生成的service接口的名字的首字母是否为I,默认Service是以I开头的
.setServiceName("%sService")
//实体类结尾名称
.setEntityName("%sDO")
//生成基本的resultMap
.setBaseResultMap(true)
//不使用AR模式
.setActiveRecord(false)
//生成基本的SQL片段
.setBaseColumnList(true);
//2. 数据源配置
DataSourceConfig dsConfig = new DataSourceConfig();
// 设置数据库类型
dsConfig.setDbType(DbType.MYSQL)
.setDriverName("com.mysql.cj.jdbc.Driver")
//TODO TODO TODO TODO
.setUrl("jdbc:mysql://127.0.0.1:3306/product?useSSL=false")
.setUsername("root")
.setPassword("123456");
//3. 策略配置globalConfiguration中
StrategyConfig stConfig = new StrategyConfig();
//全局大写命名
stConfig.setCapitalMode(true)
// 数据库表映射到实体的命名策略
.setNaming(NamingStrategy.underline_to_camel)
//使用lombok
.setEntityLombokModel(true)
//使用restcontroller注解
.setRestControllerStyle(true)
// 生成的表, 支持多表一起生成,以数组形式填写
//TODO TODO TODO TODO 两个方式,直接写,或者使用命令行输入
//.setInclude("product","product_task","banner");
.setInclude(scanner("表名,多个英文逗号分割").split(","));
//4. 包名策略配置
PackageConfig pkConfig = new PackageConfig();
pkConfig.setParent("net.classes")
.setMapper("mapper")
.setService("service")
.setController("controller")
.setEntity("model")
.setXml("mapper");
//5. 整合配置
AutoGenerator ag = new AutoGenerator();
ag.setGlobalConfig(config)
.setDataSource(dsConfig)
.setStrategy(stConfig)
.setPackageInfo(pkConfig);
//6. 执行操作
ag.execute();
System.out.println("======= Done 相关代码生成完毕 ========");
}
/**
* <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 + "!");
}
}
简介:生成的代码加入项目说明和自动化工具思考
简介:MyBatisPlus课程总结和应用场景
无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作
项目映入了第三方包,未来升级存在一定的兼容性问题
社区相对新生-文档缺乏相关的信息, 或者更新不及时
简介:接口文档在实际开发中的那些坑和OpenApi规范介绍
OpenAPI规范经过Reverb Technologies和SmartBear等公司多年的发展,OpenAPI计划拥有该规范(捐赠之后),OpenAPI Initiative在GitHub上托管社区驱动的规范。
规范是一种与语言无关的格式,用于描述RESTful Web服务,应用程序可以解释生成的文件,这样才能生成代码、生成文档并根据其描述的服务创建模拟应用。
开放API规范(OAS)是一种无需编写实际API代码就可以记录API的方法。 这是一种开放源代码格式,可以用来描述API。 在此过程中,我们可以使用JSON或YAML格式。
OpenAPI文档有三个必需的部分或对象,也可以增加其他模块:
1. openapi - OpenAPI规范版本的语义版本号
2. info - 有关API的元数据
3. paths - API的可用路径和操作
简介:自动化接口文档生成解决方案介绍
/**
* @apiGroup Product
* @api {GET} /product/{id} 查询一个产品
* @apiDescription 接口描述xxx
* @apiParam {String} id 产品id(必填*)
* @apiSuccessExample SuccessExample
* HTTP/1.1 200
* {
* id: 'xxx',
* name: 'xxx',
* desc: 'xxxx'
* }
* @apiErrorExample ErrorExample
*/
@GetMapping("/{id}")
public Product detail(@PathVariable String id)
{
return JsonData.buildSuccess();
}
RestController
@RequestMapping("api/v1/user")
@Api(tags = "用户模块",value = "用户UserController")
public class UserController {
@Autowired
private BannerService bannerService;
@ApiOperation("分页用户列表")
@GetMapping("list")
public JsonData list(){
List<BannerDO> list = bannerService.list();
return JsonData.buildSuccess(list);
}
}
简介:SpringFox和自动化接口文档生成工具Swagger介绍
简介:新版Springboot2.x整合Swagger3.x
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
<!--如果SpringBoot版本大于2.3则需要引入下面依赖-->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
启动类添加
@EnableKnife4j
spring.application.name=mou-service
# ===== 自定义swagger配置 ===== #
swagger.enable=true
swagger.application-name= ${spring.application.name}
swagger.application-version=1.0
#swagger.application-description=mou平台管理后端接口文档
swagger.application-description=1024shop api info
import io.swagger.annotations.ApiOperation;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.oas.annotations.EnableOpenApi;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
@Component
@EnableOpenApi
@ConfigurationProperties("swagger")
@Data
public class SwaggerConfiguration {
/**
* 是否开启swagger,生产环境一般关闭,所以这里定义一个变量
*/
private Boolean enable;
/**
* 项目应用名
*/
private String applicationName;
/**
* 项目版本信息
*/
private String applicationVersion;
/**
* 项目描述信息
*/
private String applicationDescription;
@Bean
public Docket docket() {
return new Docket(DocumentationType.OAS_30).pathMapping("/")
// 定义是否开启swagger,false为关闭,可以通过变量控制,线上关闭
.enable(enable)
//配置api文档元信息
.apiInfo(apiInfo())
// 选择哪些接口作为swagger的doc发布
.select()
//apis() 控制哪些接口暴露给swagger,
// RequestHandlerSelectors.any() 所有都暴露
// RequestHandlerSelectors.basePackage("net.classes.*") 指定包位置
// withMethodAnnotation(ApiOperation.class)标记有这个注解 ApiOperation
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder().title(applicationName).description(applicationDescription).contact(new Contact("开发人员", "https://baidu.com", "652133917@qq.com")).version(applicationVersion).build();
}
}
简介:新版Springboot2.x整合Swagger3.x
@Api(tags = "用户模块",value = "用户UserController")
public class UserController {
}
@ApiOperation("分页用户列表")
@GetMapping("list")
public JsonData list(){
return JsonData.buildSuccess();
}
@ApiOperation("用户登录")
@PostMapping("login")
public JsonData login(
@ApiParam(name = "phone", value = "手机号",example = "13888888888")
@RequestParam("phone") String phone,
@ApiParam(name = "pwd", value = "密码",example = "123456")
@RequestParam("pwd")String pwd){
return JsonData.buildSuccess();
}
@ApiOperation("删除用户")
@DeleteMapping("/delete/{id}")
public JsonData deleteById(@PathVariable int id) {
return JsonData.buildSuccess();
}
@ApiIgnore
@ApiOperation("删除用户")
@DeleteMapping("/delete/{id}")
public JsonData deleteById(@PathVariable int id) {
return JsonData.buildSuccess();
}
简介:讲解Swagger3.x对象注解ApiModel讲解
@Data
@ApiModel("用户基本信息")
public class SaveUserRequest {
private int age;
private String pwd;
@ApiModelProperty(value ="【必填】邮箱",required = true)
private String email;
@ApiModelProperty("【必填】手机号")
private String phone;
@ApiModelProperty(value="创建时间")
private Date createTime;
}
简介:讲解Swagger3.x响应接口和测试面板
@ApiOperation("用户登录")
@PostMapping("login")
@ApiResponses({
@ApiResponse(responseCode = CodeStatus.SUCCESS, description = "保存成功"),
@ApiResponse(responseCode = CodeStatus.FAIL, description = "保存失败")
})
public JsonData login(
@ApiParam(name = "phone", value = "手机号",example = "13888888888")
@RequestParam("phone") String phone,
@ApiParam(name = "pwd", value = "密码",example = "123456")
@RequestParam("pwd")String pwd){
return JsonData.buildSuccess();
}
简介:项目中使用Swagger整合接口文档常见问题