Alwa|

Mr·Shi

园龄:14年3个月粉丝:0关注:2

Mybatis Plus使用教程

Mybatis-Plus

快速开始

  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)
);
  1. 向数据库中添加数据
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');
  1. 创建一个SpringBoot项目并添加依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>Latest Version</version>
</dependency>
  1. 配置数据库连接
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# mysql 8 需要配置时区,不然会出现启动报错的情况 serverTimezone=GMT%2B8
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?serverTimezone=GMT%2B8&useSSL=true&useUnicode=true&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=233031
  1. 编写实体类
/*用户实体类*/
public class User {
private Long id;
private String name;
private Integer age;
private String email;
//构造方法
//GET、Set方法
}
  1. 编写UserMapper
/*在对应的Mapper上面继承基本的类 BaseMapper*/
@Repository
public interface UserMapper extends BaseMapper<User> {
/*所有的CRUD已经编写完成*/
}
//写@Repository注解,需要在主类添加MapperScan扫描mapper包
//写@Mapper则不需要

配置日志

在启动@Test需要显示Sql的细节需要配置日志

#配置日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

CRUD扩展

插入操作(insert)

//测试插入
@Test
public void testInsert(){
User user = new User();
user.setName("派大星学Java");
user.setAge(16);
user.setEmail("none-j@qq.com");
int insert = userMapper.insert(user);//帮我们自动生成id
System.out.println(insert);//受影响的行数
System.out.println(user);//发现,id会自动回填
}

数据库插入的id的默认值为:全局的唯一id

主键生成策略

默认 ID_WORKER 全局唯一

  • 雪花算法:snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID。其核心思想是:使用41bit作为毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID),12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生4096个ID),最后有一个符号,永远是0。可以保证几乎是全球唯一!

主键自增

我们需要配置主键自增:

  1. 实体类字段上@TableId(type = IdType.AUTO)
  2. 数据库字段一定要是自增!

其他主键策略

IdType.AUTO //数据库id自增
IdType.NONE //未设置主键
IdType.INPUT //手动输入,一旦手动输入id之后,就需要自己设置id了
IdType.ASSIGN_ID //分布式ID策略,生成的主键是32位的字符串,不能排序
IdType.ASSIGN_UUID //分布式ID策略,生成的是Long类型的数字,可排序,跟服务器时间有关系,类似雪花算法。
IdType.ID_WORKER //默认的全局唯一id
IdType.UUID //全局唯一id UUID
IdType.ID_WORKER_STR //ID_WORKER 字符串表示法

简化配置

如果要在项目中的每一个模型类上都需要使用相同的生成策略,稍微比较繁琐,我们可以在配置文件中添加内容来使用统一的配置:

mybatis-plus:
global-config:
db-config:
id-type: assign_id

配置完成之后,每个模型的注解ID策略都将成为assign_id

数据库表与模型关系的映射关系

MP会默认将模型类的类名首字母小写作为表名使用,假如数据库名称都以tbl_开头,那么我们就需要将所有的模型类上添加@TableName,配置起来还是比较繁琐,简化方式可以在配置文件中配置如下内容:

mybatis-plus:
global-config:
db-config:
table-prefix: tbl_

设置前缀的内容,这样MP就会拿tbl_加上模型类的首字母小写,就刚好组装成数据库的表名。

更新操作(update)

//更新操作
@Test
public void updateTest(){
User user = new User();
user.setId(5L);
user.setName("我想创建公众号");
user.setAge(16);
int i = userMapper.updateById(user);
System.out.println(i);
}

自动填充

创建时间、修改时间!这些个操作一遍都是自动化完成的,我们 不希望手动更新!

阿里巴巴开发手册:所有的数据库表:gmt_create、gmt_modified几乎所有的表都要配置上!而且需要自动化!

方式一:数据库级别(工作中不允许更改数据库)

给时间字段增加默认值,

方式二:代码级别

  1. 删除数据库中的默认值、更新操作!
  2. 实体类字段属性需要增加注解
//字段添加填充内容
@TableField(fill = FieldFill.INSERT)
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
  1. 编写处理器来处理这个注解即可!
@Component
public class MyDateObjectHandler 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);
}
}

乐观锁

乐观锁:故名思议十分乐观,它总是认为不会出现问题,无论干什么不去上锁!如果出了问题,再次更新值测试

悲观锁:故名思议十分悲观,它总是认为总是出现问题,无论干什么都会上锁!再去操作!

乐观锁实现方式:

  • 取出记录时,获取当前version
  • 更新时,带上这个version
  • 执行更新时, set version = newVersion where version = oldVersion
  • 如果version不对,就更新失败
--A
update user set name = "wumao",version = version + 1
where id = 2 and version = 1
--B 线程抢先完成,这个时候 version = 2,会导致A修改失败
update user set name = "wumao",version = version + 1
where id = 2 and version = 1

MP的乐观锁插件

  1. 给数据库中加入version字段
  2. 给实体类加上对应的字段
@Version //乐观锁Version的注解
private Integer version;
  1. 注册组件
@MapperScan("com.pdx.mapper") //扫描mapper文件夹
@EnableTransactionManagement
@Configuration //配置类
public class MyBatisPlusConfig {
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
}
  1. 测试乐观锁
//测试乐观锁
//成功案例
@Test
public void versionTest(){
User user = userMapper.selectById(1L);
user.setName("派大星");
user.setEmail("admin@qq.com");
userMapper.updateById(user);
}
//乐观锁失败案例----多线程
@Test
public void OptimisticLockerTest(){
User user = userMapper.selectById(1L);
user.setName("派大星111");
user.setEmail("admin@qq.com");
//模拟另外一个线程执行了插队操作
User user2 = userMapper.selectById(1L);
user.setName("派大星222");
user.setEmail("admin@qq.com");
userMapper.updateById(user2);
userMapper.updateById(user);
}

查询操作

//查询操作
@Test
public void testSelect(){
User user = userMapper.selectById(1L);
System.out.println(user);
}
//批量查询
@Test
public void testBatchList(){
List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3));
users.forEach(System.out::println);
}
//按条件查询 map操作
@Test
public void testSelectMap(){
HashMap<String, Object> map = new HashMap<>();
map.put("name","派大星");
map.put("age",16);
List<User> users = userMapper.selectByMap(map);
users.forEach(System.out::println);
}

分页查询

  1. 原始的limit 进行分页
  2. pageHelper 第三方插件
  3. MP内置了分页插件

使用

  1. 配置拦截器
//分页插件
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
  1. 分页查询
//分页查询
@Test
public void PageTest(){
//参数一:当前页
//参数二:页的大小
//使用了分页插件之后,所有的分页操作也变得简单!
Page<User> page = new Page<>(1,5);
IPage<User> pages = userMapper.selectPage(page, null);
pages.getRecords().forEach(System.out::println);
}

删除操作

//删除操作
@Test
public void deletTest(){
userMapper.deleteById(1398260764485095426L);
}
//批量删除
@Test
public void deletBatchTest(){
userMapper.deleteBatchIds(Arrays.asList(1398201429172178946L,5));
}
@Test
public void deletByMap(){
HashMap<String, Object> map = new HashMap<>();
map.put("name","我想创建公众号");
userMapper.deleteByMap(map);
}

物理删除:从数据库中直接移除

逻辑删除:在数据库中没有被移除,而是通过一个变量让他无效!delete = 0 —> delete = 1

MP中的逻辑删除配置

  1. 在数据库中增加一个deleted字段
  2. 在pojo中增加新的属性
@TableLogic //逻辑删除
private Integer deleted;
  1. 配置
@Bean //逻辑删除组件
public ISqlInjector sqlInjector(){
return new LogicSqlInjector();
}
#配置逻辑删除 1 删除 0 未删除
mybatis-plus.global-config.db-config.logic-delete-value=1
mybatis-plus.global-config.db-config.logic-not-delete-value=0
  1. 测试
//逻辑删操作
@Test
public void deleteLogic(){
int i = userMapper.deleteById(1L);
System.out.println(i);
}

性能分析插件

我们在平时的开发中,会遇到一些慢SQL,测试!Druid…

作用:性能分析拦截器,用于输出每条SQL语句及其执行时间

MP也提供了性能分析插件,如果超过这个时间就停止运行!

  1. 导入插件
/*
* SQL执行效率插件
* */
@Bean
@Profile({"dev","test"})//设置dev test 环境开启,保证我们的效率
public PerformanceInterceptor performanceInterceptor(){
PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
performanceInterceptor.setMaxTime(100);//ms 设置SQL执行的最大时间,如果超过了则不执行
performanceInterceptor.setFormat(true);//是否格式化代码
return performanceInterceptor;
}

记住,要在SpringBoot中配置环境为dev或者test环境

  1. 测试
@Test
void contextLoads() {
List<User> users = userMapper.selectList(null);
for (User user : users) {
System.out.println(user);
}
}

条件构造器(十分重要)

构造器分很多种,有Wrapper、QueryWrapper、LambdaQueryWrapper等

Demo1:

@Test
public void wapperTest(){
//查询name不为空的用户,并且邮箱不为空的用户,年龄大于12
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.isNotNull("name").isNotNull("email").ge("age", 12);
userMapper.selectList(wrapper).forEach(System.out::println);
}

Demo2:

@Test
void test2(){
//查询名字为五毛
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(User::getName, "派大星");
User user = userMapper.selectOne(wrapper);
System.out.println(user);
}

不列举太多,其他请参考下图

img

select 设置需要查询的字段
例: 指定查询主键,名字,年龄字段

select("id""name""age")

例: 查询以test开头的属性

select(i ‐> i.getProperty().startsWith("test"))

例:查询User对象中出除manager_id和create_time外其它所有字段的数据

select(User.class, info ‐> !info.getColumn().equals("manager_id") && !info.getColumn().equals("create_time"))

本文作者:Mr·Shi

本文链接:https://www.cnblogs.com/shijiangtao/p/17124654.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Mr·Shi  阅读(168)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起