共计 11448 个字符,预计需要花费 29 分钟才能阅读完成。
为简化开发而生
Mybatis 简化 JDBC 操作
MyBatis-Plus(简称 MP)是一个 MyBatis 的加强工具,在 MyBatis 的根底上只做加强不做扭转,为简化开发、提高效率而生。
1、个性
- 无侵入 :只做加强不做扭转,引入它不会对现有工程产生影响,如丝般顺滑
- 损耗小 :启动即会主动注入根本 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 操作智能剖析阻断,也可自定义拦挡规定,预防误操作
2、反对数据库
- mysql、mariadb、oracle、db2、h2、hsql、sqlite、postgresql、sqlserver
- 达梦数据库、虚谷数据库、人大金仓数据库
3、疾速开始
1、创立数据库
DROP TABLE IF EXISTS user;
CREATE TABLE user
(id BIGINT(20) NOT NULL COMMENT '主键 ID',
name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
age INT(11) NULL DEFAULT NULL COMMENT '年龄',
email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
PRIMARY KEY (id)
);
INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, 'test1@baomidou.com'),
(2, 'Jack', 20, 'test2@baomidou.com'),
(3, 'Tom', 28, 'test3@baomidou.com'),
(4, 'Sandy', 21, 'test4@baomidou.com'),
(5, 'Billie', 24, 'test5@baomidou.com');
2、新建 Spring Boot 我的项目
-
导入依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <!--mybatis-plus--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.3.1.tmp</version> </dependency>
-
连贯数据库
spring: datasource: url: jdbc:mysql://localhost:3306/mybatisplus?useSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT #useSSL 平安连贯 useUnicode 编码 characterEncoding 编码格局 serverTimezone 时区 username: root password: 100104 driver-class-name: com.mysql.cj.jdbc.Driver
-
创立实体类 User
@Data @AllArgsConstructor @NoArgsConstructor public class User { private Long id; private String name; private Integer age; private String email; }
-
实现接口 UserMapper
//@Mapper @Repository // 代表长久层 public interface UserMapper extends BaseMapper<User> {// 所有的 CRUD 曾经编写实现}
-
在 Spring Boot 启动类中增加
@MapperScan
注解,扫描 Mapper 文件夹@SpringBootApplication @MapperScan("com.xiaobear.mapper") // 扫描文件夹 public class MybatisplusApplication {public static void main(String[] args) {SpringApplication.run(MybatisplusApplication.class, args); } }
-
测试
@SpringBootTest class MybatisplusApplicationTests { @Autowired private UserMapper userMapper; @Test void contextLoads() { // 查问所有用户 List<User> list = userMapper.selectList(null); list.forEach(System.out::println); } }
4、配置日志
应用默认控制台输入日志
# 配置日志
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
5、CRUD 扩大
Insert
// 测试插入
@Test
public void testInsert(){User user = new User();
user.setName("小熊");
user.setAge(18);
user.setEmail("2861184805@qq.com");
int insert = userMapper.insert(user); // 主动生成 id
System.out.println(insert);
System.out.println(user);
}
}
后果
主键生成策略
雪花算法:Twitter 利用 zookeeper 实现了一个全局 ID 生成的服务 Snowflake:github.com/twitter/sno…:
snowflake 是 Twitter 开源的分布式 ID 生成算法,后果是一个 long 型的 ID。其核心思想是:应用 41bit 作为毫秒数,10bit 作为机器的 ID(5 个 bit 是数据中心,5 个 bit 的机器 ID),12bit 作为毫秒内的流水号(意味着每个节点在每毫秒能够产生 4096 个 ID),最初还有一个符号位,永远是 0
主键自增
咱们配置主键自增
- 实体类字段上加上 @TableId(type = IdType.AUTO)
- 数据库字段上肯定要自增
- 再次测试即可
public enum IdType {AUTO(0), // 数据库 id 自增
NONE(1), // 未设置主键
INPUT(2), // 手动输出
ASSIGN_ID(3), // 默认全局 id
ASSIGN_UUID(4), // 全局惟一 id
@Deprecated
ID_WORKER(3),
@Deprecated
ID_WORKER_STR(3), //ID_WORKER 字符串表示法
@Deprecated
UUID(4);
private final int key;
private IdType(int key) {this.key = key;}
public int getKey() {return this.key;}
}
update
@Test
public void testupdate(){
// 通过条件主动拼接动静 sql
User user = new User();
user.setId(6L);
user.setName("你是最棒的");
int i = userMapper.updateById(user); //updateById 参数是一个对象
System.out.println(i);
}
}
主动填充
数据库级别(工作中不应用)
1、在表中字段减少 create_time、update_time
2、通过测试插入方法
private Date createTime;
private Date updateTime;
3、查看后果
[外链图片转存失败, 源站可能有防盗链机制, 倡议将图片保留下来间接上传 (img-b4eqQLIz-1662093452834)(MybatisPlus 学习笔记 Images/image-20200414134824719.png)]
代码级别
1、实体类属性上减少注解
@TableField(fill = FieldFill.INSERT)
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
2、实现元对象处理器接口:com.baomidou.mybatisplus.core.handlers.MetaObjectHandler
自定义实现类 MyMetaObjectHandler
@Component // 退出到 IOC 容器里
@Slf4j
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {log.info("start insert fill ....");
this.setFieldValByName("createTime",new Date(),metaObject);
this.setFieldValByName("updateTime",new Date(),metaObject);
}
@Override
public void updateFill(MetaObject metaObject) {log.info("start update fill ....");
this.setFieldValByName("updateTime",new Date(),metaObject);
}
}
3、测试插入,察看工夫
乐观锁
非常乐观,它总是认为不会呈现问题,无论干什么都不上锁,如果呈现了问题,再次更新值测试!
乐观锁实现形式:
- 取出记录时,获取以后 version
- 更新时,带上这个 version
- 执行更新时,set version = newVersion where version = oldVersion
- 如果 version 不对,就更新失败
1、给数据库新增字段 verison,默认值为 1
2、实体类新增字段
@Version // 乐观锁注解
private Integer version;
3、注册插件
@Configuration
@MapperScan("com.xiaobear.mapper")
public class MybatisPlusConfig {
// 注册乐观锁插件
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {return new OptimisticLockerInterceptor();
}
}
4、测试
@Test
public void testOptimisticLocker(){
// 查问用户信息
User user = userMapper.selectById(1L);
// 批改信息
user.setName("xiaobear");
user.setAge(2);
// 执行
int update = userMapper.updateById(user);
System.out.println(update);
}
// 测试失败
@Test
public void testOptimisticLocker2(){User user = userMapper.selectById(1L);
user.setName("xiaobear");
user.setAge(2);
User user2 = userMapper.selectById(1L);
user2.setName("xiaobear111");
user2.setAge(10);
// 模仿另一个线程进行插队操作
int update = userMapper.updateById(user);
int update2 = userMapper.updateById(user2);
System.out.println(update);
System.out.println(update2);
}
乐观锁
非常乐观,它总是认为会呈现问题,无论干什么都会上锁,再去操作!
查问操作
// 单个查问
@Test
public void testSelect(){User user = userMapper.selectById(2L);
System.out.println(user);
}
// 批量查问
@Test
public void testSelectByBatchId(){List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3));
users.forEach(System.out::println);
}
// 条件查问 map
@Test
public void testSelectByBatchIds(){HashMap<String, Object> map = new HashMap<>();
map.put("name","xiaobear");
List<User> users = userMapper.selectByMap(map);
users.forEach(System.out::println);
}
分页查问
分页插件
// 分页插件
@Bean
public PaginationInterceptor paginationInterceptor() {return new PaginationInterceptor();
/* PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
// 设置申请的页面大于最大页后操作,true 调回到首页,false 持续申请 默认 false
// paginationInterceptor.setOverflow(false);
// 设置最大单页限度数量,默认 500 条,-1 不受限制
// paginationInterceptor.setLimit(500);
// 开启 count 的 join 优化, 只针对局部 left join
paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));
return paginationInterceptor;*/
}
测试
// 测试分页插件
@Test
public void testPage(){
// 参数一:当前页 参数二:页面大小
Page<User> page = new Page<>(1,5);
userMapper.selectPage(page,null);
page.getRecords().forEach(System.out::println);
System.out.println(page.getTotal());
}
删除操作
// 测试删除
@Test
public void deleteById(){int i = userMapper.deleteById(1L);
System.out.println(i);
}
// 测试 id 批量删除
@Test
public void deleteById2(){userMapper.deleteBatchIds(Arrays.asList(1L,2L,3L));
}
// 通过 map 删除
@Test
public void testDeleteMap(){HashMap<String, Object> map = new HashMap<>();
map.put("name","小熊");
userMapper.deleteByMap(map);
}
逻辑删除
物理删除:从数据库中间接删除
逻辑删除:在数据库没有移除,而是通过一个变量来让他生效!避免数据失落,相似回收站
数据库增加字段,实体类上加上字段
@TableLogic
private Integer deleted;
测试删除、查问
6、性能剖析插件
性能剖析拦截器,用于输入每条 SQL 语句及其执行工夫
/**
* SQL 执行效率插件
*/
@Bean
@Profile({"dev","test"})// 设置 dev test 环境开启
public PerformanceInterceptor performanceInterceptor() {return new PerformanceInterceptor();
}
7、条件结构器 wrapper
@Autowired
private UserMapper userMapper;
@Test
void contextLoads() {QueryWrapper<User> wrapper = new QueryWrapper<> ();
wrapper
.isNotNull("name")
.isNotNull("email")
.ge("age",3);
userMapper.selectList(wrapper).forEach(System.out::println);
}
@Test
void test(){QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("name","Tom"); // 查问名字
User user = userMapper.selectOne(wrapper); // 查问一个数据
System.out.println(user);
}
@Test
void test2(){
// 查问年龄 10-20
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.between("age",10,20);
Integer count = userMapper.selectCount(wrapper);
System.out.println(count);
}
@Test
void test3(){
// 含糊查问
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper
.notLike("name","e")
.likeRight("email","t");
List<Map<String, Object>> maps = userMapper.selectMaps(wrapper);
maps.forEach(System.out::println);
}
@Test
void test4(){
//
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.inSql("id","select id form user where id<3");
List<Object> objects = userMapper.selectObjs(wrapper);
objects.forEach(System.out::println);
}
8、代码生成器
public class XiaoBearCode {public static void main(String[] args) {AutoGenerator mpg = new AutoGenerator();
// 全局配置
GlobalConfig gc = new GlobalConfig();
String projectPath = System.getProperty("user.dir");
gc.setOutputDir(projectPath + "/src/main/java");
gc.setAuthor("xiaobear");
gc.setOpen(false);
// gc.setSwagger2(true); 实体属性 Swagger2 注解
mpg.setGlobalConfig(gc);
// 数据源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://localhost:3306/mybatisplus?useSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT");
// dsc.setSchemaName("public");
dsc.setDriverName("com.mysql.cj.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("100104");
mpg.setDataSource(dsc);
// 包配置
PackageConfig pc = new PackageConfig();
pc.setModuleName("blog");
pc.setParent("com.xiaobear");
pc.setEntity("pojo");
pc.setMapper("mapper");
pc.setService("com/xiaobear/service");
pc.setServiceImpl("com.xiaobear/Service/Impl");
pc.setController("com/xiaobear/controller");
mpg.setPackageInfo(pc);
// 策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setNaming(NamingStrategy.underline_to_camel);
strategy.setColumnNaming(NamingStrategy.underline_to_camel);
strategy.setEntityLombokModel(true); // 主动 lombok
strategy.setRestControllerStyle(true);
// 公共父类
strategy.setSuperControllerClass("你本人的父类控制器, 没有就不必设置!");
// 写于父类中的公共字段
strategy.setSuperEntityColumns("id");
strategy.setInclude("user");// 映射的表
strategy.setLogicDeleteFieldName("deleted"); // 逻辑删除字段
// 主动填充策略
TableFill gmt_create = new TableFill("gmt_create", FieldFill.INSERT);
TableFill gmt_modified = new TableFill("gmt_strate", FieldFill.INSERT);
ArrayList<TableFill> list = new ArrayList<>();
list.add(gmt_create);
list.add(gmt_modified);
strategy.setTableFillList(list);
// 乐观锁
strategy.setVersionFieldName("version");
strategy.setRestControllerStyle(true); // 驼峰
strategy.setControllerMappingHyphenStyle(true); //localhost:8080/hello_id_1
strategy.setTablePrefix(pc.getModuleName() + "_");
mpg.setStrategy(strategy);
mpg.setTemplateEngine(new FreemarkerTemplateEngine());
mpg.execute(); // 执行}
}
谬误:
19:39:38.943 [main] DEBUG com.baomidou.mybatisplus.generator.AutoGenerator - ========================== 筹备生成文件...==========================
Exception in thread "main" java.lang.NoClassDefFoundError: freemarker/template/Configuration
at com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine.init(FreemarkerTemplateEngine.java:41)
at com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine.init(FreemarkerTemplateEngine.java:34)
at com.baomidou.mybatisplus.generator.AutoGenerator.execute(AutoGenerator.java:103)
at com.xiaobear.XiaoBearCode.main(XiaoBearCode.java:66)
Caused by: java.lang.ClassNotFoundException: freemarker.template.Configuration
at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:355)
at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
... 4 more
解决:
导入模板引擎依赖
<dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.30</version> </dependency>