IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> MyBaitsPlus快速入门,阿里java技术专家面试 -> 正文阅读

[Java知识库]MyBaitsPlus快速入门,阿里java技术专家面试


UserMapper接口


//继承BaseMapper基本类,接口里面已经写了很多的crud方法

@Mapper

public interface UserMapper extends BaseMapper

{}


测试


@SpringBootTest

class SpringBootDaoApplicationTests

{

//继承了BaseMapper,所有的方法都来自于父类,我们页可以编写自己的扩展方法

@Autowired

UserMapper userMapper;

@Test

void contextLoads()

{

//参数是一个Wrapper,条件构造器,这里我们先不使用 null

//查询全部用户

List users = userMapper.selectList(null);

users.forEach(System.out::println);

}

}

在这里插入图片描述


@Mapper注解和@MapperScan注解

======================================================================================

1、@Mapper注解:

作用:在接口类上添加了@Mapper,在编译之后会生成相应的接口实现类

添加位置:接口类上面

@Mapper

public interface UserDAO {

//代码

}

如果想要每个接口都要变成实现类,那么需要在每个接口类上加上@Mapper注解,比较麻烦,解决这个问题用@MapperScan

2、@MapperScan

作用:指定要变成实现类的接口所在的包,然后包下面的所有接口在编译之后都会生成相应的实现类

添加位置:是在Springboot启动类上面添加,

@SpringBootApplication

@MapperScan(“com.winter.dao”)

public class SpringbootMybatisDemoApplication {

public static void main(String[] args) {

SpringApplication.run(SpringbootMybatisDemoApplication.class, args);

}

}

添加@MapperScan(“com.winter.dao”)注解以后,com.winter.dao包下面的接口类,在编译之后都会生成相应的实现类


配置日志

===================================================================

#开启日志功能

mybatis-plus:

configuration:

log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #控制台输出


@TableId注解

=========================================================================

这个注解表示表的主键

@NoArgsConstructor

@AllArgsConstructor

@Data

public class User

{

String name;

Integer age;

@TableId(value=“id”,type = IdType.AUTO)

Integer id;

}

接受两个参数

value = 主键列名

type = 主键类型

可选类型:

在这里插入图片描述

**使用@TableId注解时,类型为: type = IdType.AUTO 数据库也需要设置自增

否则会出 Cause: java.sql.SQLException: Field ‘id’ doesn’t have a default value**


插入操作

===================================================================

//测试插入

@Test

public void testInsert(){

User user = new User();

user.setName(“淮城一只猫”);

user.setAge(5);

user.setEmail(“2424496907@qq.com”);

int result = userMapper.insert(user); //自动生成id

System.out.println(result); //受影响的行数

System.out.println(user); //发现id自动回填

}


主键生成策略

=====================================================================

默认使用ID_WORKER,全局唯一id----雪花算法

分布式系统唯一id生成方案汇总

在这里插入图片描述


雪花算法(默认使用):


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


主键自增


我们需要配置注解自增:

  • 实体类字段上:@TableId(type = IdType.AUTUO)

  • 数据库字段一定要自增


其余的策略解释


public enum IdType {

AUTO(0), //id自增

NONE(1), //未设置主键

INPUT(2), //手动输入,一旦手动输入后,就需要自己去写id,否则id为空

ID_WORKER(3), //默认值,全局唯一id

UUID(4), //全局唯一id,uuid

ID_WORKER_STR(5); //ID_WORKER的字符串表示法

}


更新操作

===================================================================

//测试更新

@Test

public void testUpdate(){

User user = new User();

user.setId(6L);

user.setName(“我的博客叫:淮城一只猫”);

user.setAge(6);

user.setEmail(“2424496907@qq.com”);

//注意:updateById参数是一个对象

int result = userMapper.updateById(user); //自动生成id

System.out.println(result); //受影响的行数

}


自动填充

===================================================================

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

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


方式一:数据库级别(工作中不建议这么做)


1.在表中新增字段create_time、update_time

在这里插入图片描述

2. 再次测试插入方法,需要先把实体类同步!

private Date creteTime;

private Date updateTime;


mysql日期相关的知识点


mysql中的日期类型小结笔记

MySQL-datetime类型的列设置默认值为CURRENT_TIMESTAMP

MySQL中datetime字段的默认值CURRENT_TIMESTAMP


方式二:代码级别


1.删除数据库中的默认值、更新操作

在这里插入图片描述

2.在实体类字段属性上需要注释

//字段必须声明TableField注解,属性fill选择对应策略,该声明告知Mybatis-Plus需要预留注入SQL字段

// 注意!这里需要标记为填充字段

@TableField(fill = FieldFill.INSERT)

private Date creteTime;

@TableField(fill = FieldFill.INSERT_UPDATE)

private Date updateTime;

策略枚举如下:

public enum FieldFill {

/**

  • 默认不处理

*/

DEFAULT,

/**

  • 插入填充字段

*/

INSERT,

/**

  • 更新填充字段

*/

UPDATE,

/**

  • 插入和更新填充字段

*/

INSERT_UPDATE

}

3.自定义实现类 MyMetaObjectHandler(实现元对象处理器接口)

@Slf4j

@Component//填充处理器MyMetaObjectHandler在 Spring Boot 中需要声明@Component或@Bean注入

public class MyMetaObjectHandler implements MetaObjectHandler

{

//插入时填充策略

@Override

public void insertFill(MetaObject metaObject) {

log.info(“start insert fill …”);

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);

}

}

4.测试

@SpringBootTest

class SpringBootDaoApplicationTests

{

//继承了BaseMapper,所有的方法都来自于父类,我们页可以编写自己的扩展方法

@Autowired

UserMapper userMapper;

@Test

void contextLoads()

{

User user=new User();

user.setAge(18);

user.setName(“hhhh”);

int ret = userMapper.insert(user);

System.out.println(user);

}

}

在这里插入图片描述


乐观锁

==================================================================

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

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

乐观锁实现方式:

  • 取出记录时,获取当前version

  • 更新时,带上这个version

  • 执行更新时, set version = newVersion where version = oldVersion

  • 如果version不对,就更新失败


测试MP乐观锁插件


1.数据库中添加version字段,默认值为1

在这里插入图片描述


2.在实体类的字段上加上@Version注解

@Version //乐观锁注解

private Integer version;

说明:

  • 支持的数据类型只有:int,Integer,long,Long,Date,Timestamp,LocalDateTime

  • 整数类型下 newVersion = oldVersion + 1

  • newVersion 会回写到 entity 中

  • 仅支持 updateById(id) 与 update(entity, wrapper) 方法

  • 在 update(entity, wrapper) 方法下, wrapper 不能复用!!!

3.配置插件

@MapperScan("c

《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》

【docs.qq.com/doc/DSmxTbFJ1cmN1R2dB】 完整内容开源分享

om.Mapper")

@EnableTransactionManagement //自动管理事务(默认也是开启的)

@Configuration //配置类

public class MybaitsPlusConfig {

//注册乐观锁插件

@Bean

public MybatisPlusInterceptor mybatisPlusInterceptor() {

MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();

mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());

return mybatisPlusInterceptor;

}

}

4.测试

@SpringBootTest

class SpringBootDaoApplicationTests

{

//继承了BaseMapper,所有的方法都来自于父类,我们页可以编写自己的扩展方法

@Autowired

UserMapper userMapper;

//测试乐观锁成功!

@Test

public void testOptimisticLocker1() {

//1.查询用户信息

User user = userMapper.selectById(276);

//2.修改用户信息

user.setName(“aaa”);

user.setAge(18);

//3.执行更新操作

userMapper.updateById(user);

}

//测试乐观锁失败!多线程下

@Test

public void testOptimisticLocker2() {

//线程1

User user1 = userMapper.selectById(276);

user1.setName(“aaa”);

//模拟另外一个线程执行插队操作

User user2 = userMapper.selectById(276);

user2.setName(“bbb”);

userMapper.updateById(user2);

//自旋锁多次操作尝试提交

userMapper.updateById(user1);

}

}

在这里插入图片描述


查询操作

===================================================================

@SpringBootTest

class SpringBootDaoApplicationTests

{

//继承了BaseMapper,所有的方法都来自于父类,我们页可以编写自己的扩展方法

@Autowired

UserMapper userMapper;

//测试查询

@Test

public void testSelectById() {

User user = userMapper.selectById(276);

System.out.println("===========================");

System.out.println(user);

}

//测试批量查询

@Test

public void testSelectByBatchId()

{

List users = userMapper.selectBatchIds(Arrays.asList(270, 271, 272));

System.out.println("===========================");

users.forEach(System.out::println);

}

//条件查询之一 使用map操作

@Test

public void testSelectBatchIds() {

HashMap<String, Object> map = new HashMap<>();

//自定义查询,同时满足map集合中的所有条件

map.put(“name”,“bbb”);

map.put(“age”,“18”);

List users = userMapper.selectByMap(map);

System.out.println("===========================");

users.forEach(System.out::println);

}

}

在这里插入图片描述


分页查询

===================================================================

分页在网站中使用非常多!

  • 原始limit进行分页

  • pageHelper第三方插件

  • MP其实也内置了分页插件


1.配置分页插件


//Spring boot方式

@Configuration

@MapperScan(“com.baomidou.cloud.service..mapper”)

public class MybatisPlusConfig {

// 旧版

@Bean

public PaginationInterceptor paginationInterceptor() {

PaginationInterceptor paginationInterceptor = new PaginationInterceptor();

// 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求 默认false

// paginationInterceptor.setOverflow(false);

// 设置最大单页限制数量,默认 500 条,-1 不受限制

// paginationInterceptor.setLimit(500);

// 开启 count 的 join 优化,只针对部分 left join

paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));

return paginationInterceptor;

}

// 最新版

@Bean

public MybatisPlusInterceptor mybatisPlusInterceptor() {

MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();

interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));

return interceptor;

}

}

  1. setMaxLimit: 设置最大分页数

  2. setOverflow:是否对超过最大分页时做溢出处理,默认false不处理,即直接丢弃溢出的数据,为true时,怎么把溢出数据放入到下一个分页中。

  3. setDbType:设置数据库类型以匹配不同方言

  4. setDialect: 设置分页方言

  5. setOptimizeJoin:优化Join分页语句,默认true


2.直接使用Page对象即可


//测试分页查询

@Test

public void testPage() {

//参数一:当前页

//参数二:页面大小

//使用了分页插件之后,所有的分页操作页变得简单了

Page page = new Page<>(1,5);

//第二个参数是查询条件

userMapper.selectPage(page,null);

page.getRecords().forEach(System.out::println);

System.out.println(page.getTotal());

}

在这里插入图片描述

分页查询常用的方法:

@Test

public void testPage() {

Page page = new Page<>(1,1);

List emps =

employeeMapper.selectPage(page, null);

System.out.println(emps);

System.out.println("=获取分页相关的一些信息========");

System.out.println(“总条数:” +page.getTotal());

System.out.println("当前页码: "+ page.getCurrent());

System.out.println(“总页码:” + page.getPages());

System.out.println(“每页显示的条数:” + page.getSize());

System.out.println("是否有上一页: " + page.hasPrevious());

System.out.println("是否有下一页: " + page.hasNext());

//将查询的结果封装到page对象中

page.setRecords(emps);

}

在这里插入图片描述

在这里插入图片描述

如果返回类型是IPage,那么分页返回的IPage对象与传入IPage的对象是同一个


好用的工具===》Arrays用法总结

Arrays用法总结


删除操作

===================================================================

//通过id删除

@Test

public void testDeleteById() {

userMapper.deleteById(174);

}

//通过id批量删除

@Test

public void testDeleteBatchId() {

userMapper.deleteBatchIds(Arrays.asList(177, 178));

}

//通过map删除

@Test

public void testDeleteMap() {

HashMap<String, Object> map = new HashMap<>();

map.put(“name”, “大忽悠1号”);

userMapper.deleteByMap(map);

}


逻辑删除


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

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

管理员可以查看被删除的记录!防止数据的丢失,类似于回收站!


说明

这里mybaitsPlus提供的逻辑删除功能,只对其默认提供给我们的增删改查的slq语句生效,如果是我们自己写的,则不会拥有其功能

只对自动注入的sql起效:

插入: 不作限制

查找: 追加where条件过滤掉已删除数据,且使用 wrapper.entity 生成的where条件会忽略该字段

更新: 追加where条件防止更新到已删除数据,且使用 wrapper.entity 生成的where条件会忽略该字段

删除: 转变为 更新


例如:

删除: update user set deleted=1 where id = 1 and deleted=0 (如果走了自动注入sql的删除操作,那么其实执行的是更新操作,即将deleted值变为1,即逻辑删除掉了)

查找: select id,name,deleted from user where deleted=0 (查找的时候只会查找出没有被逻辑删除掉的用户)


字段类型支持说明:

支持所有数据类型(推荐使用 Integer,Boolean,LocalDateTime)

如果数据库字段使用datetime,逻辑未删除值和已删除值支持配置为字符串null,另一个值支持配置为函数来获取值如now()


附录:

逻辑删除是为了方便数据恢复和保护数据本身价值等等的一种方案,但实际就是删除。

如果你需要频繁查出来看就不应使用逻辑删除,而是以一个状态去表示。


测试一下:

1.在数据表中增加deleted字段

在这里插入图片描述

2. 实体类中同步属性

//逻辑删除字段

@TableLogic

private Integer deleted;

3. 配置

mybatis-plus:

global-config:

db-config:

logic-delete-field: flag # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)

logic-delete-value: 1 # 逻辑已删除值(默认为 1)

logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)

4.测试

@SpringBootTest

class SpringBootDaoApplicationTests

{

//继承了BaseMapper,所有的方法都来自于父类,我们页可以编写自己的扩展方法

@Autowired

UserMapper userMapper;

//通过id删除

@Test

public void testDeleteById()

{

userMapper.deleteById(174);

}

}

在这里插入图片描述

在这里插入图片描述


结合P6Spy进行SQL性能分析

===============================================================================

我们在开发中,会遇到一些慢sql,我们有必要把它揪出来 。测试!druid…

MP也提供性能分析插件,如果超过这个时间就停止运行!官方3.1.0以上版本推荐使用p6spy!

? P6Spy 是一个可以用来在应用程序中拦截和修改数据操作语句的开源框架。 通过 P6Spy 我们可以对 SQL 语句进行拦截,相当于一个 SQL 语句的记录器,这样我们可以用它来作相关的分析,比如性能分析。

注意:该插件有性能损耗,建议平时开发测试时使用,不建议生产环境使用。


1.导入依赖


p6spy

p6spy

3.9.0

2.接着编辑 application.properties 文件,更换数据库连接驱动


P6Spy 工作原理:P6Spy 通过劫持 JDBC 驱动,在调用实际 JDBC 驱动前拦截调用的目标语,达到 SQL 语句日志记录的目的。

spring:

datasource: #是否使用安全连接

#mysal 8驱动不同com.mysql.cj.jdbc.Driver,还需要增加时区的配置 serverTimezone=GMT%2B8

url: jdbc:p6spy:mysql://localhost:3306/tx?userSSL=false&useUnicode=true&characterEncoding=utf-8

username: root

password: 123456

driver-class-name: com.p6spy.engine.spy.P6SpyDriver

profiles:

active: dev #激活开发环境

3.最后创建 spy.properties 配置文件即可:

#3.2.1以上使用

modulelist=com.baomidou.mybatisplus.extension.p6spy.MybatisPlusLogFactory,com.p6spy.engine.outage.P6OutageFactory

#3.2.1以下使用或者不配置

#modulelist=com.p6spy.engine.logging.P6LogFactory,com.p6spy.engine.outage.P6OutageFactory

自定义日志打印

logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger

#日志输出到控制台

appender=com.baomidou.mybatisplus.extension.p6spy.StdoutLogger

使用日志系统记录 sql

#appender=com.p6spy.engine.spy.appender.Slf4JLogger

设置 p6spy driver 代理

deregisterdrivers=true

取消JDBC URL前缀

useprefix=true

配置记录 Log 例外,可去掉的结果集有error,info,batch,debug,statement,commit,rollback,result,resultset.

excludecategories=info,debug,result,commit,resultset

日期格式gui

dateformat=yyyy-MM-dd HH:mm:ss

实际驱动可多个

#driverlist=org.h2.Driver

是否开启慢SQL记录

outagedetection=true

慢SQL记录标准 2 秒

outagedetectioninterval=2

4.测试

@SpringBootTest

class SpringBootDaoApplicationTests

{

//继承了BaseMapper,所有的方法都来自于父类,我们页可以编写自己的扩展方法

@Autowired

UserMapper userMapper;

//通过id删除

@Test

@Profile({“dev”,“test”})

public void testDeleteById()

{

User user = userMapper.getUserId(174);

System.out.println(user);

}

}

在这里插入图片描述

注意,插件会影响性能,建议开发和测试环境下使用


@Profile注解详解

@Profile注解详解


进阶技巧


1. 使用日志系统记录 sql


1. 上面的样例配置,我们是直接将日志输出到控制台,我们可以修改 appender 配置属性,使用日志系统记录 sql:

在这里插入图片描述

2. 再次执行查询,可以看到现在改用日志系统记录 sql 了:

在这里插入图片描述

2. 将日志输出到文件


也可以修改 appender 配置属性,将日志输出到文件中:

#日志输出到文件

appender=com.p6spy.engine.spy.appender.FileLogger

指定 Log 的文件名 默认 spy.log

logfile=spy.log

指定是否每次是增加 Log,设置为 false 则每次都会先进行清空 默认true

append=true

3.自定义日志格式

? 1. 如果觉得默认的日志格式不合适,我们也可以使用 logMessageFormat 和 customLogMessageFormat 这两个配置参数来自定义日志输出格式:

可用的变量为:

%(connectionId):connection id %(currentTime):当前时间

%(executionTime):执行耗时 %(category):执行分组 %(effectiveSql):提交的 SQL 换行

%(effectiveSqlSingleLine):提交的 SQL 不换行显示 %(sql):执行的真实 SQL 语句,已替换占位

%(sqlSingleLine):执行的真实 SQL 语句,已替换占位不换行显示

6spy.engine.spy.appender.CustomLineFormat

customLogMessageFormat=%(currentTime) |

SQL耗时: %(executionTime) ms |

连接信息: %(category)-%(connectionId) | 执行语句: %(sql)

在这里插入图片描述


条件构造器(Wrapper)

=============================================================================

这部分建议看官方文档学习

测试一


@Test

void test1() {

//查询name不为空的用户,并且邮箱不为空的,年龄大于等于12

QueryWrapper wapper = new QueryWrapper<>();

wapper.isNotNull(“name”) //这里推荐使用链式编程

.ge(“age”, 64);//大于等于

userMapper.selectList(wapper).forEach(System.out::println);

}

在这里插入图片描述

测试二


@Test

void test2() {

//查询名字为Tom

QueryWrapper wapper = new QueryWrapper<>();

wapper.eq(“name”,“bbb”);

//只查询一个用户

User user = userMapper.selectOne(wapper);

System.out.println(user);

}

在这里插入图片描述

测试三—范围查询


//范围查询

@Test

void test3()

{

//查询年龄在20~30岁之间的用户

QueryWrapper wapper = new QueryWrapper<>();

wapper.between(“age”, 64, 68);//区间

System.out.println(userMapper.selectCount(wapper));//查询结果数

}

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-12-02 16:37:29  更:2021-12-02 16:38:01 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 5:03:29-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码