1.快速入门
官方入门地址:https://mp.baomidou.com/guide/#%E7%89%B9%E6%80%A7
一般学习步骤:
- 导入对应的依赖
- 研究依赖如何配置
- 代码如何编写
- 提高扩展技术
1.1 创建数据库
DELETE FROM user;
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');
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)
);
注意: 一般真是开发中包括以下几个字段:
version (乐观锁)
deleted(逻辑删除)
gmt_create
gmt_modified
1.2 初始化项目(springboot初始化)
1.3 导入需要的相应的依赖
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
<!-- myabatis-puls属于自己开的发的开源的-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.0.5</version>
</dependency>
注意的问题:使用mybatis属于节省代码量,尽量不要同时导入mybatis和mybatispuls,避免造成版本差异冲突的问题。
1.4 依赖的相应配置(链接数据库,这里与mybatis是相同的)
# 配置数据库的链接(注意是mysql5 或者是MySQL8 ,是8的话需要添加时区,同时驱动的版本也不一致)
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.url=jdbc:mysql://localhost:3306/mybatispuls?useSSL=fasle&useUnicode=true&characterEncoding=utf-8
# 这里配置的是myaql8的数据库驱动,其是向下进行兼容的
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
1.5 使用myabtis-puls之后步骤(pojo-mapper接口-使用)
(传统的方式:pojo-dao(连接myabatis,配置mapper.xml)-service-controller)
pojo
package com.xuexi.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private Long id;
private String name;
private Integer age;
private String email;
}
mapper
package com.xuexi.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.xuexi.pojo.User;
import org.springframework.stereotype.Repository;
// 在对应的接口mapper上继承BaseMapper<T>
@Repository //加上注解表示他是dao层
public interface UserMapper extends BaseMapper<User> {
//所的基础CRUD已经编写好了,不需要再进行mapper.xml操作
}
主启动类(添加扫描)
package com.xuexi;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@MapperScan("com.xuexi.mapper")
@SpringBootApplication
public class MybatisPulsApplication {
public static void main(String[] args) {
SpringApplication.run(MybatisPulsApplication.class, args);
}
}
测试类(测试一下我们的基本程序)
package com.xuexi;
import com.xuexi.mapper.UserMapper;
import com.xuexi.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
class MybatisPulsApplicationTests {
// 继承了basemappper的所有方法.同时我们也可以编写自己的扩展方法
@Autowired
private UserMapper userMapper;
@Test
void contextLoads() {
// List<T> selectList(@Param("ew") Wrapper<T> var1);
//这里的Wrapper是一个条件构造器,如果没有写为null即可
List<User> users = userMapper.selectList(null);
users.forEach(System.out::println);
}
}
结果
2.配置日志
(由于使用的mybatis无法看到具体发出的sql,因此配置日志)
# 配置数据库的链接(注意是mysql5 或者是MySQL8 ,是8的话需要添加时区,同时驱动的版本也不一致)
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.url=jdbc:mysql://localhost:3306/mybatispuls?useSSL=FALSE&useUnicode=true&characterEncoding=utf-8
# 这里配置的是myaql8的数据库驱动,其是向下进行兼容的
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
# 日志的配置 这里是直接输出到桌面(其他的需要配置依赖)
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
3.CRUD扩展
3.1插入
@Test
void userAdd() {
User user = new User();
user.setName("hlb");
user.setAge(23);
user.setEmail("hlsunmoon@163.com");
int result = userMapper.insert(user);
System.out.println(result);
System.out.println(user);
}
发现一个问题:它会自动帮你填充数据库(默认插入的数据库,全局唯一的id)
3.2 主键生成策略
雪花算法
snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID。生成的是一个64位的二进制正整数,然后转换成10进制的数。snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID。生成的是一个64位的二进制正整数,然后转换成10进制的数。
package com.baomidou.mybatisplus.annotation;
public enum IdType {
AUTO(0), // 自增(记得数据库表也需要进行相应的设置)
NONE(1), // 不做任何的输入
INPUT(2), //手动的输入
ID_WORKER(3),// 默认全局唯一ID
UUID(4),//全局唯一ID
ID_WORKER_STR(5);// 字符串表示法
private int key;
private IdType(int key) {
this.key = key;
}
public int getKey() {
return this.key;
}
}
3.3 更新
@Test
void updataUser() {
User user = new User();
user.setId(5L);
user.setName("tom");
int i = userMapper.updateById(user);
System.out.println(i);
}
发现其会自动拼接 sql (动态sql)
3.4 自动填充
数据库级别(工作中不允许进行这样的操作)
在原来的表上添加两个字段gmt_create、gmt_modified(这里我们使用create_time、update_time)(如果数据库的版本太低了的话,是设置不了默认的时间current_time)
再次进行插入操作测试(更新一下你得pojo)
private Date createTime;
private Date updateTime;
代码级别
A. 上述一样,在数据库中添加两个字段,然后再代码中给那两个字段添加上注解
// 字段填充内容
@TableField(fill = FieldFill.INSERT)
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
B. 让编辑器来处理我们的注解即可(handler)
package com.xuexi.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.util.Date;
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
// 插入时的填充策略
@Override
public void insertFill(MetaObject metaObject) {
log.info("inser fill");
this.setFieldValByName("createTime", new Date(), metaObject);
this.setFieldValByName("updateTime", new Date(), metaObject);
}
//更新时的填充策略
@Override
public void updateFill(MetaObject metaObject) {
this.setFieldValByName("updateTime", new Date(), metaObject);
}
}
4.乐观锁机制
- 乐观锁:顾名思义便是表明十分乐观,认为任何时候都不会出现问题,无论什么时候都不会进行上锁的操作,出现问题是,再次更新测试值!(根据的是version版本)
- 悲观锁:顾名思义表明的是十分悲观,认为什么时候都会出现问题,因此,无论什么时候都会上锁
关于乐观锁机制:
当要更新一条记录的时候,希望这条记录没有被别人更新
乐观锁实现方式:
- 取出记录时,获取当前version
- 更新时,带上这个version
- 执行更新时, set version = newVersion where version = oldVersion
- 如果version不对,就更新失败
乐观锁:1.查询,获得版本号,version = 1
--A
update user set name = 'hkk',version = version+1
where id = 2 and version = 1
--B 线程抢先完成,这个时候version = 2,会导致A线程的修改失败
update user set name = 'hkk',version = version+1
where id = 2 and version = 1
4.1 乐观锁建立
A、数据库表中添加version字段,默认值设置为1
B、添加相应的字段
@Version //表明这里是一个乐观锁
private Integer version;
C、编写相应的组件
package com.xuexi.config;
import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@MapperScan("com.xuexi.mapper") //扫描mapper
@EnableTransactionManagement //事务管理处理
@Configuration //代表配置类
public class MyBatisPulsConfig {
// 注册乐观锁插件(官方的开发文档已经给出)
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
}
D、进行测试
// 测试乐观锁成功
@Test
public void testOptimisticLocker1(){
// 1. 查询一个员工
User user = userMapper.selectById(1L);
// 2.修改员工的信息
user.setName("zhangsan");
user.setEmail("643767@qq.com");
// 3.执行更新的流程
userMapper.updateById(user);
}
// 测试乐观锁失败得情况(多线程得的情况下)
@Test
public void testOptimisticLocker2(){
// 线程 1
User user1 = userMapper.selectById(1L);
user1.setName("zhangsan11");
user1.setEmail("643767@qq.com");
// 模拟另外一个线程 执行插队的操作
User user2 = userMapper.selectById(1L);
user2.setName("zhangsan222");
user2.setEmail("643767@qq.com");
userMapper.updateById(user2);
// 自旋锁来自多次尝试提交
userMapper.updateById(user1);//没有乐观锁的情况下,数据的值将会被当前的操作所覆盖
}
5、查询的一些操作
5.1 基础查询
//测试查询
@Test
public void testSelectById(){
User user = userMapper.selectById(1L);
System.out.println(user);
}
//测试批量查询
@Test
public void testSelectBatchIds(){
List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3));
users.forEach(System.out::println);
}
//按条件查询map
@Test
public void testSelectByMap(){
HashMap<String, Object> map = new HashMap<>();
map.put("name", "toms");
List<User> users = userMapper.selectByMap(map);
users.forEach(System.out::println);
}
5.2 分页查询(看官网给出的文档--官网是最新的形式)
1. 原始的limit进行分页
2.PageHandler插件分页
3.MP内置的插件
A、 配置拦截器
// 分页插件
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
B、测试分页
//分页查询操作
@Test
public void testSelectByPage(){
Page<User> page = new Page<>();
userMapper.selectPage(page, null);
page.getRecords().forEach(System.out::println);
System.out.println(page.getTotal());
}
6、删除操作
6.1 基础删除
相应的操作与查询是一致的
@Test
public void testDelete(){
userMapper.deleteById(1400716576671444993L);
}
6.2 逻辑删除
物理删除:从数据库中直接移除
逻辑删除:数据库中并没有真正的移除,只是通过一个变量使其失效!deleted = 1
A、在数据库添加一个deleted字段,并设置默认值为0
B、添加字段
@TableLogic
private Integer deleted;
C、配置插件
//逻辑删除插件
@Bean
public ISqlInjector sqlInjector() {
return new LogicSqlInjector();
}
D、配置文件中添加配置
# 配置逻辑删除信息
mybatis-plus.global-config.db-config.logic-delete-value=1
mybatis-plus.global-config.db-config.logic-not-delete-value=0
E、测试(删除的时候变成更新操作、查询的时候会自动带上deleted = 0)
@Test
public void testDeleteBylogic(){
userMapper.deleteById(1400716576671444995L);
}
7、性能插件
A、导入插件
//sql性能监视分析插件
@Bean
@Profile({"dev","test"})// 设置dev 和 test 环境开启,保证我们的效率
public PerformanceInterceptor ptorerformanceInterceptor(){
PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
performanceInterceptor.setMaxTime(100);//设置sql 最大的运行时间
performanceInterceptor.setFormat(true);//sql 的格式化
return performanceInterceptor;
}
B、配置开发环境、
# 配置为开发的环境
spring.profiles.active=dev
C、进行测试
8、条件查询器Wrapper
举例说明几种查询方式,详细的见官方文档
@Test
void test1(){
// 查询name不为空,并且不为空,年龄大于22
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.isNotNull("name")
.isNotNull("email")
.ge("age",22);
List<User> users = userMapper.selectList(wrapper);
users.forEach(System.out::println);
}
@Test
void test2(){
//查询名字为XXX
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("name", "hlb");
User user = userMapper.selectOne(wrapper);
System.out.println(user);
}
@Test
void test3(){
//查询年龄区间
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.between("age","20","24");
List<User> users = userMapper.selectList(wrapper);
users.forEach(System.out::println);
}
@Test
void test4(){
// 模糊查询
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.like("name", "c");
List<User> users = userMapper.selectList(wrapper);
users.forEach(System.out::println);
}
@Test
void test5(){
// 子查询(联表查询)
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.inSql("id","select id from user where id<4");
List<User> users = userMapper.selectList(wrapper);
users.forEach(System.out::println);
}
9、代码生成器
A、首席按导入我们需要的依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>com.spring4all</groupId>
<artifactId>spring-boot-starter-swagger</artifactId>
<version>1.5.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.3</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.31</version>
</dependency>
<dependency>
<groupId>com.ibeetl</groupId>
<artifactId>beetl</artifactId>
<version>3.3.2.RELEASE</version>
</dependency>
B、编写我们代码生成器代码
package com.xuexi.springboot;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
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.po.TableFill;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import java.util.ArrayList;
public class generateCode {
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("hlb");
gc.setOpen(false);// 是否打开资源管理器(文件夹)
gc.setSwagger2(true); //实体属性 Swagger2 注解
gc.setFileOverride(false);// 是否覆盖
gc.setServiceName("%sService");// 去掉service I 的前缀
mpg.setGlobalConfig(gc);// 配置完成之后放入我们的全局配置当中
// 数据源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://localhost:3306/mybatispuls?useUnicode=true&useSSL=false&characterEncoding=utf8");
dsc.setDriverName("com.mysql.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("123456");
dsc.setDbType(DbType.MYSQL);
mpg.setDataSource(dsc);
// 包配置
PackageConfig pc = new PackageConfig();
pc.setModuleName("blog");//创建的子包名字
pc.setParent("com.xuexi");//创建位于哪个目录下
pc.setEntity("pojo");
pc.setMapper("mapper");
pc.setService("service");
pc.setController("controller");
mpg.setPackageInfo(pc);
// 策略配置(乐观锁、逻辑删除、)
StrategyConfig strategy = new StrategyConfig();
strategy.setInclude("user"); // 需要映射的表对象,可以同时写入多个表
strategy.setNaming(NamingStrategy.underline_to_camel);// 驼峰命名
strategy.setColumnNaming(NamingStrategy.underline_to_camel);
strategy.setEntityLombokModel(true);
// 逻辑删除
strategy.setLogicDeleteFieldName("deleted");// 逻辑填充的时候 想到自动填充的字段
// 自动填充
TableFill create_time = new TableFill("create_time", FieldFill.INSERT);
TableFill update_time = new TableFill("update_time", FieldFill.UPDATE);
ArrayList<TableFill> TableFills = new ArrayList<>();
TableFills.add(create_time);
TableFills.add(update_time);
strategy.setTableFillList(TableFills);
// 乐观锁
strategy.setVersionFieldName("version");
strategy.setRestControllerStyle(true);
strategy.setControllerMappingHyphenStyle(true); //localhost:8080/hello_id_1
mpg.setStrategy(strategy);
mpg.execute();
}
}
到现在,mybatis-puls结束学习,本学习笔记的完成是根据相应的学习视频完成,需要学习的根据下方链接直达
https://www.bilibili.com/read/cv5702420