官方API https://mp.baomidou.com/
狂神说 https://gitee.com/kuangstudy/openclass/raw/master/%E7%8B%82%E7%A5%9E%E8%AF%B4MyBatisPlus%E8%AE%B2%E8%A7%A3/MyBatisPlus.pdf
快速入门
依赖
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.2.RELEASE</version><relativePath/></parent>
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.3.2</version></dependency><dependency><groupId>com.h2database</groupId><artifactId>h2</artifactId><scope>runtime</scope></dependency></dependencies>
建表
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--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');
继承接口(核心)
import com.baomidou.mybatisplus.core.mapper.BaseMapper;public interface UserMapper extends BaseMapper<User> {}
启动类
@MapperScan("com.sms.dao")
@SpringBootApplication@MapperScan("com.sms.dao")public class SpringBootQuickStartApplication {public static void main(String[] args) {SpringApplication.run(SpringBootQuickStartApplication.class, args);}}
数据库连接配置
#数据库相关配置spring.datasource.username = rootspring.datasource.password = 123456spring.datasource.url = jdbc:mysql://localhost:3306/mybatisplusspring.datasource.driver-class-name = com.mysql.cj.jdbc.Driver
CRUD
配置日志
sql全部被基本Mapper接口底层操作完了,我们看不见,所以我们需要用日志来细看,这里用的是自带的一个日志。当然要用slf4j,log4j都可以
# 配置日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
新增
@Test
public void testInsert(){
User user = new User();
user.setName("狂神说Java");
user.setAge(3);
user.setEmail("24736743@qq.com");
int result = userMapper.insert(user); // 帮我们自动生成id
System.out.println(result); // 受影响的行数
System.out.println(user); // 发现,id会自动回填
}

发现主键自动回填,”雪花算法”。
另外相关的有,自增id,uuid,redis,zookeeper
修改
// 测试更新
@Test
public void testUpdate(){
User user = new User();
// 通过条件自动拼接动态sql
user.setId(6L);
user.setName("关注公众号:狂神说");
user.setAge(18);
// 注意:updateById 但是参数是一个 对象!
int i = userMapper.updateById(user);
System.out.println(i);
}
查询
// 测试查询
@Test
public void testSelectById(){
User user = userMapper.selectById(1L);
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","狂神说Java");
map.put("age",3);
List<User> users = userMapper.selectByMap(map);
users.forEach(System.out::println);
}
分页查询
逻辑删除
CRUD(额外补充)
自动填充
阿里巴巴开发手册:所有的数据库都需要配置 gmt_create,gmt_modified,因为我们要追踪每一条数据是什么时候创建,什么时候修改的。
ps:gmt - greenwich mean time 格林威治时间
1.数据库级别(工作中不允许修改)
直接在字段上加上时间函数 current_timestamp
2.代码级别(推荐)
//在插入和插入更新的时候,自动填充内容
@TableField(fill = FieldFill.INSERT)
@TableField(fill = FieldFill.INSERT_UPDATE)
package com.sms.config;
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 // 一定不要忘记把处理器加到IOC容器中!
public class MyMetaObjectHandler implements MetaObjectHandler {
// 插入时的填充策略
@Override
public void insertFill(MetaObject metaObject) {
log.info("start insert fill.....");
// setFieldValByName(String fieldName, Object fieldVal, MetaObject metaObject
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);
}
}
主键生成策略
https://www.cnblogs.com/haoxinyue/p/5208136.html
1.主键自增
· @TableId(type = IdType.AUTO)
· 数据库字段要自增
public enum IdType {
AUTO(0), // 数据库id自增 !!
NONE(1), // 未设置主键
INPUT(2), // 手动输入
ID_WORKER(3), // 默认的全局唯一id !!
UUID(4), // 全局唯一id uuid
ID_WORKER_STR(5); //ID_WORKER 字符串表示法
}
上锁(并发问题)
乐观锁很乐观,它不会去上锁,出现问题了,就再次更新值
悲观锁很悲观,它什么都上锁才操作
1.乐观锁
概念
- 它会先看version是多少
- 然后再一个update语句中,同时判定version是否被别的线程动过,也就是version是不是它之前看到的那个
set version = newVersion where version = oldVersion
- 如果不是,说明有线程抢先插队了,它就更新失败 ```sql 乐观锁:1、先查询,获得版本号 version = 1 — A update user set name = “kuangshen”, version = version + 1 where id = 2 and version = 1 — B 线程抢先完成,这个时候 version = 2,会导致 A 修改失败! update user set name = “kuangshen”, version = version + 1 where id = 2 and version = 1
<a name="qRNRJ"></a>
#### 配置
实体类
```sql
// 扫描我们的 mapper 文件夹
@MapperScan("com.kuang.mapper")
@EnableTransactionManagement
@Configuration // 配置类
public class MyBatisPlusConfig {
// 注册乐观锁插件
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
}
对应字段
@Version //乐观锁Version注解
private Integer version;
测试一下
// 测试乐观锁失败!多线程下
@Test
public void testOptimisticLocker2(){
// 线程 1
User user = userMapper.selectById(1L);
user.setName("kuangshen111");
user.setEmail("24736743@qq.com");
// 模拟另外一个线程执行了插队操作
User user2 = userMapper.selectById(1L);
user2.setName("kuangshen222");
user2.setEmail("24736743@qq.com");
userMapper.updateById(user2);
// 自旋锁来多次尝试提交!
userMapper.updateById(user); // 如果没有乐观锁就会覆盖插队线程的值!
}

