- 第一天内容
- 一、Mybatis-plus的使用
- 1. 创建数据库
- 2. 创建SpringBoot项目,添加依赖
- 3. 添加mysql的相关配置
- 4. 创建entity文件夹,并创建User实体
- 5. 创建mapper文件夹,并创建UserMapper接口
- 6. 在测试类中注入UserMapper对象,并简单查询一下是否成功
- 7. 添加在控制台输出sql日志的配置
- 二、添加记录
- 1. 操作步骤
- 2. MP的主键生成策略
- 三、 更新记录
- 1. 操作
- 2. 自动填充功能·
- a. 在字段上面添加自动填充注解
- b. 实现元对象处理器接口(一定要加@Component注解)
- 四、乐观锁(模拟修改冲突并配置乐观锁)
- 1. 模拟修改冲突
- 2. 创建产品表,并添加记录
- 3. 创建实体类
- 4. 创建ProductMapper
- 5. 模拟冲突
- 6. 乐观锁
- 五、 查询记录
- 1. 基本的查询功能
- 2. 分页查询
- 3. 返回指定的列,使用Page
正常创建流程,字符编码使用utf8mb4,排序规则依然使用general-cl。
# 创建数据库表
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. 创建SpringBoot项目,添加依赖
3. 添加mysql的相关配置com.baomidou mybatis-plus-boot-starter 3.3.1 mysql mysql-connector-java runtime org.projectlombok lombok true
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/数据库名?serverTimezone=GMT%2B8 spring.datasource.username=用户名 spring.datasource.password=密码4. 创建entity文件夹,并创建User实体
package com.example.demo.entity;
import lombok.Data;
@Data
public class User {
private Long id;
private String name;
private Integer age;
private String email;
}
5. 创建mapper文件夹,并创建UserMapper接口
# 继承了baseMapper接口,从而实现CRUD的功能,另外要注意加入注解 package com.example.demo.mapper; import com.baomidou.mybatisplus.core.mapper.baseMapper; import com.example.demo.entity.User; import org.springframework.stereotype.Repository; @Repository public interface UserMapper extends baseMapper6. 在测试类中注入UserMapper对象,并简单查询一下是否成功{ }
@Autowired
private UserMapper userMapper;
@Test
void contextLoads() {
List users = userMapper.selectList(null);
users.forEach(System.out::println);
}
7. 添加在控制台输出sql日志的配置
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl二、添加记录 1. 操作步骤
package com.example.demo;
import com.example.demo.entity.User;
import com.example.demo.mapper.UserMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class CRUDTest {
@Autowired
private UserMapper userMapper;
@Test
public void testInsert(){
User user = new User();
user.setName("小A");
user.setAge(22);
user.setEmail("ss");
int result = userMapper.insert(user);
System.out.println("影响的行数:" + result);
System.out.println("用户的ID:" + user.getId());
}
}
此时插入的id值为:1459034582838120449,显然不是加1.因此牵扯到mybatis中主键生成策略。
策略1: 按照id的范围来分表,比如1-9999存储在表1,10000-19999存储在表2,以此类推。这样做的缺点为如果每个表中的数据量少,则数据表多。
策略2: hash策略。id%n的数为存放的表。这样在扩充表时,需要重新排布数据。
雪花算法-分布式ID生成器: 能够保证不同表的主键的不重复性,以及相同表中主键的有序性。
# 默认的主键生成策略,使用了雪花算法 @TableId(type = IdType.ASSIGN_ID) private String id;
# 自增策略 @TableId(type = IdType.AUTO) private String id;
全局配置主键生成策略
mybatis-plus.global-config.db-config.id-type=auto三、 更新记录 1. 操作
@Test
public void updateUser(){
User user = new User();
user.setName("my baby");
user.setId(7L); // 因为是long类型的数据
int result = userMapper.updateById(user);
System.out.println(result);
}
阿里巴巴的代码规范要求每个表中都要有id、create_time、update_time,修改表结构。这样就需要在改变记录时更新时间。可以使用手动改变记录的时间值,然后更新到表中。也可以使用==自动填充功能
==。
@TableField(fill = FieldFill.INSERT) private Date createTime; @TableField(fill = FieldFill.INSERT_UPDATE) private Date updateTime;b. 实现元对象处理器接口(一定要加@Component注解)
package com.example.demo.handler;
import com.baomidou.mybatisplus.core.handlers.metaObjectHandler;
import org.apache.ibatis.reflection.metaObject;
import org.springframework.stereotype.Component;
import java.util.Date;
@Component
public class MymetaObjectHandler implements metaObjectHandler {
@Override
public void insertFill(metaObject metaObject) {
System.out.println("insertFill====");
this.setFieldValByName("createTime",new Date(),metaObject);
this.setFieldValByName("updateTime",new Date(),metaObject);
}
@Override
public void updateFill(metaObject metaObject) {
System.out.println("updateFill=====");
this.setFieldValByName("updateTime",new Date(),metaObject);
}
}
四、乐观锁(模拟修改冲突并配置乐观锁)
1. 模拟修改冲突
一件商品,成本价是80元,售价是100元。老板先是通知小李,说你去把商品价格增加50元。小李正在玩游戏,耽搁了一个小时。正好一个小时后,老板觉得商品价格增加到150元,价格太高,可能会影响销量。又通知小王,你把商品价格降低30元。
此时,小李和小王同时操作商品后台系统。小李操作的时候,系统先取出商品价格100元;小王也在操作,取出的商品价格也是100元。小李将价格加了50元,并将100+50=150元存入了数据库;小王将商品减了30元,并将100-30=70元存入了数据库。是的,如果没有锁,小李的操作就完全被小王的覆盖了。
现在商品价格是70元,比成本价低10元。几分钟后,这个商品很快出售了1千多件商品,老板亏1多万。
CREATE TABLE product( id BIGINT(20) NOT NULL COMMENT '主键ID', name VARCHAR(30) NULL DEFAULT NULL COMMENT '商品名称', price INT(11) DEFAULT 0 COMMENT '价格', version INT(11) DEFAULT 0 COMMENT '乐观锁版本号', PRIMARY KEY (id)); INSERT INTO product (id, NAME, price) VALUES (1, '外星人笔记本', 100);3. 创建实体类
package com.example.demo.entity;
import com.baomidou.mybatisplus.annotation.Version;
import lombok.Data;
@Data
public class Product {
private Long id;
private String name;
private Integer price;
private Integer version;
}
4. 创建ProductMapper
package com.example.demo.mapper; import com.baomidou.mybatisplus.core.mapper.baseMapper; import com.example.demo.entity.Product; import org.springframework.stereotype.Repository; @Repository public interface ProductMapper extends baseMapper5. 模拟冲突{ }
@Autowired
private ProductMapper productMapper;
@Test
public void testConcurrentUpdate() {
//1、 小李获取数据
Product p1 = productMapper.selectById(1L);
System.out.println("小李取出的价格" + p1.getPrice());
// 2、 小王获取数据
Product p2 = productMapper.selectById(1L);
System.out.println("小王取出的价格" + p2.getPrice());
// 3、小李加了50元存入数据库
p1.setPrice(p1.getPrice() + 50);
productMapper.updateById(p1);
// 4、小王减了30元存入数据库
p2.setPrice(p2.getPrice() - 30);
int i = productMapper.updateById(p2);
if (i==0) {
System.out.println("小王更新失败");
//发起重试
p2 = productMapper.selectById(1L);
p2.setPrice(p2.getPrice() - 30);
productMapper.updateById(p2);
}
//5、其他人看到的结果.最后的结果
Product p3 = productMapper.selectById(1L);
System.out.println("" + "最后的结果" + p3.getPrice());
}
输出结果为70.
6. 乐观锁首先在version字段上加@Version注解
@Version private Integer version;
第二步 创建乐观锁配置文件
package com.example.demo.config;
import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
//做事务处理
@EnableTransactionManagement
//配置类
@Configuration
public class MybatisPlusConfig {
@Bean
//乐观锁插件
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
}
之后再执行测试文件,则更新为120.
五、 查询记录 1. 基本的查询功能@Test
public void selectBatch(){
//根据id的数组进行查询
List users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3));
users.forEach(System.out::println);
}
@Test
public void selectByMap(){
// 将查询条件组合为一个map进行查询
HashMap map = new HashMap<>();
map.put("name","Jone");
map.put("age",18);
List users = userMapper.selectByMap(map);
users.forEach(System.out::println);
}
2. 分页查询
首先配置分页插件,在MybatisPlusConfig中添加下列代码
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
测试
@Test
public void testSelectPage(){
Page page = new Page<>(1, 5);
Page pageParam = userMapper.selectPage(page, null);
List records = pageParam.getRecords();
records.forEach(System.out::println);
System.out.println(pageParam.getPages());//总页数
System.out.println(pageParam.getTotal());//总记录数
System.out.println(pageParam.getCurrent());//当前页码号
System.out.println(pageParam.getSize());//每页记录数
System.out.println(pageParam.hasNext());//是否有下一页
System.out.println(pageParam.hasPrevious());//是否有上一页
}
3. 返回指定的列,使用Page


