1、配置
1、application.properties
mysql8.0以上,springboot 2.1,配置文件发生变化
#mysql
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=137171
#mysql日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
2、lombok 简化实体类
1、 添加lombok依赖
<!--lombok:用于简化实体类-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
2、@Data
在实体类上面加@Data注解,表示属性的get、set、toString等方法自动注入
import lombok.Data;
@Data
public class User {
private Long id;
private String name;
private Integer age;
private String email;
}
封装get、set、toString等方法,简化实体类
3、BaseMapper
映射接口继承BaseMapper<实体类>,该类中封装了单表的CRUD,后续可以调用这些方法
public interface UserMapper extends BaseMapper<User> {
}
4、@MapperScan
放在主入口类上面,用于扫描mapper接口。后面都会单独设置一个配置类,在配置上面设置 @Configuration注解,表示在主入口类运行时,该配置类也运行。
@MapperScan("com.zh.mapper") //扫描mapper接口
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
类似这样
2、主键生成策略
1、AUTO 自增长
在主键属性上面加 @TableId(type = IdType.AUTO)
public class User {
//指定主键使用数据库ID自增策略
@TableId(type = IdType.AUTO)
private Integer id;
}
2、UUID 随机唯一值
每次生成随机唯一值,在主键属性上加 @TableId(type = IdType.UUID)
优点:
1、简单,代码方便。
2、生成ID性能非常好,基本不会有性能问题。
3、全球唯一,在遇见数据迁移,系统数据合并,或者数据库变更等情况下,可以从容应对。
缺点:
1、**没有排序,无法保证趋势递增**。
2、`UUID`往往是使用字符串存储,**查询的效率比较低**
3、自带策略(snowflake)
1、 ID_WORKER
生成19位值,数字类型使用这种策略,比如long。在主键上面加:@TableId(type = IdType.ID_WORKER)
public class User {
@TableId(type = IdType.ID_WORKER)
private Integer id;
}
2、 ID_WORKER_STR
生成19位值,字符串类型使用这种类型。在主键上面加:@TableId(type = IdType.ID_WORKER_STR)
4、input
自定义输入值
5、redis生成ID
1、 当使用数据库来生成ID性能不够要求的时候,我们可以尝试使用Redis来生成ID。这主要依赖于Redis是单线程的,所以也可以用生成全局唯一的ID。可以用Redis的原子操作 INCR和INCRBY来实现。
2、 可以使用Redis集群来获取更高的吞吐量。假如一个集群中有5台Redis。可以初始化每台Redis的值分别是1,2,3,4,5,然后步长都是5。各个Redis生成的ID为:
A:1,6,11,16,21
B:2,7,12,17,22
C:3,8,13,18,23
D:4,9,14,19,24
E:5,10,15,20,25
3、 这个,随便负载到哪个机确定好,未来很难做修改。但是3-5台服务器基本能够满足器上,都可以获得不同的ID。但是步长和初始值一定需要事先需要了。使用Redis集群也可以防止单点故障的问题。另外,比较适合使用Redis来生成每天从0开始的流水号。比如订单号=日期+当日自增长号。可以每天在Redis中生成一个Key,使用INCR进行累加。
优点:
不依赖于数据库,灵活方便,且性能优于数据库。
数字ID天然排序,对分页或者需要排序的结果很有帮助。
缺点:
如果系统中没有Redis,还需要引入新的组件,增加系统复杂度。
需要编码和配置的工作量比较大。
https://www.cnblogs.com/haoxinyue/p/5208136.html
3、自动填充
有些数据会使用相同的方式填充,例如记录的创建时间,更新时间
1、添加表字段
数据类型是 datetime
2、实体类中添加属性
3、测试类中手动添加时间值方式
4、自动填充
不需要将值手动set到对象里面
1、@TableField ( fill = FieldFill.INSERT )
@TableField ( fill = FieldFill.INSERT ) 表示插入数据时,该字段实现自动填充
@TableField(fill = FieldFill.INSERT_UPDATE) 表示插入和修改数据的时候,该字段实现自动填充
public class User {
private Long id;
private String name;
private Integer age;
private String email;
//create_time
@TableField(fill = FieldFill.INSERT)
private Date createTime;
//update_time
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
}
2、MetaObjectHandler
创建处理器类MyMetaObjectHandler,实现MetaObjectHandler接口,重写接口中两方法
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
//使用添加操作时,该方法执行
@Override
public void insertFill(MetaObject metaObject) {
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加1,不同时操作失败
1、版本控制
数据库中添加version字段,实体类中添加version属性,在属性上面加 @Version 注解
//版本号
@TableField(fill = FieldFill.INSERT)
@Version
private Integer version;
2、乐观锁插件
在config包下创建一个 config 配置类
@Configuration // 配置类
@MapperScan("com.zh.mapper") // 扫描mapper接口
public class MyConfig {
//乐观锁插件
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
}
3、测试乐观锁,先查后改
//测试乐观锁,先查后改
@Test
public void testOptimisticLocker(){
//根据ID查询
User user = userMapper.selectById(2l);
//执行修改操作
user.setAge(20);
userMapper.updateById(user);
}
5、查询
1、根据ID查询
//根据ID查询 返回对象
User user = userMapper.selectById(2l);
2、多ID批量查询
//多ID批量查询 返回集合
@Test
public void testSelect(){
List<User> users = userMapper.selectBatchIds(Arrays.asList(1l, 2l, 1336131603264266241l));
System.out.println(users);
}
3、分页查询
1、在 配置类config 中导入分页插件代码
//分页插件
@Bean
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));
return paginationInterceptor;
}
2、创建page对象,调用 selectPage方法
//分页查询
@Test
public void testPage(){
//创建page对象,传入参数表示:当前页,每页显示记录数
Page<User> page = new Page<>(1, 2);
//调用分页查询方法,把数据封装到page对象里面
userMapper.selectPage(page,null);
System.out.println(page.getCurrent());//当前页
System.out.println(page.getRecords());//每页数据list集合
System.out.println(page.getSize());//每页显示记录数
System.out.println(page.getTotal());//总记录数
System.out.println(page.getPages());//总页数
System.out.println(page.hasNext());//是否有下一页
System.out.println(page.hasPrevious());//是否有上一页
}
6、删除
1、物理删除
调用deleteById方法
//物理删除
@Test
public void testDeleteById() {
int result = userMapper.deleteById(1l);
System.out.println("删除:" + result + "条数据");
}
//批量物理删除
@Test
public void testDeleteBatchIds() {
int result = userMapper.deleteBatchIds(Arrays.asList(1, 2));
System.out.println("批量删除:" + result + "条数据");
}
2、逻辑删除
假删除,将对应数据中代表是否被删除字段状态修改为“被删除状态”,之后在数据库中仍旧能看到此条数据记录
1、 @TableLogic
表添加deeted字段,对应实体类添加属性,属性上面加 @TableLogic 注解
//逻辑删除
@TableLogic
private Integer deleted;
2、配置application.properties
# 全局逻辑删除字段
mybatis-plus.global-config.db-config.logic-delete-field=flag
# 逻辑已删除值
mybatis-plus.global-config.db-config.logic-delete-value=1
# 逻辑未删除值
mybatis-plus.global-config.db-config.logic-not-delete-value=0
3、开发环境
#环境配置 dev:开发,test:测试,prod:生产
spring.profiles.active=dev
7、QueryWrapper 条件构造器
复杂条件查询
1、ge、gt、le、lt、isNull、isNotNull
ge/gt/le/lt:表示大于,大于等于,小于,小于等于
//实现复杂查询
@Test
public void testSelectQuery(){
//创建QueryWrapper对象
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.ge("age",30);
List<User> users = userMapper.selectList(wrapper);
System.out.println(users);
}
2、eq、ne
等于,不等于
wrapper.eq("age",30);
3、between、notBetween
包含大小写边界
wrapper.between("age",30,70);
4、like、notLike、likeLeft、likeRight
wrapper.like("name","立");
5、orderByDesc
wrapper.orderByDesc("id");
6、last
表示直接拼接到sql后面
wrapper.last("limit 2");
7、指定要查询的列
wrapper.select("id","name");