练习
两点之间不包含任何点的最宽垂直区域
给你 n 个二维平面上的点 points ,其中 points[i] = [xi, yi] ,请你返回两点之间内部不包含任何点的 最宽垂直区域 的宽度。
垂直区域 的定义是固定宽度,而 y 轴上无限延伸的一块区域(也就是高度为无穷大)。 最宽垂直区域 为宽度最大的一个垂直区域。
请注意,垂直区域 边上 的点 不在 区域内。
示例 1:
输入:points = [[8,7],[9,9],[7,4],[9,7]]
输出:1
解释:红色区域和蓝色区域都是最优区域。
示例 2:
输入:points = [[3,1],[9,0],[1,0],[1,4],[5,3],[8,8]]
输出:3
提示:
n == points.length
2 <= n <= 105
points[i].length == 2
0 <= xi, yi <= 109
class Solution {
public int maxWidthOfVerticalArea(int[][] points) {
int max=0;
//只让points 的 x 进行排序
//按照arr数组中的每一行的第一列进行比较,并按照升序排序。
//原版Arrays.sort(points, (a, b) -> a[0] - b[0]);
Arrays.sort(points, Comparator.comparingInt(a -> a[0]));
for (int i = 1; i < points.length; i++) {
max=Math.max(max,points[i][0]-points[i-1][0]);
}
return max;
}
}
/**
* 按照arr数组中的每一行的第一列进行比较,并按照降序排序。
* Arrays.sort(arr, (a, b) -> b[0] - a[0]);
*/
class Solution {
public int maxWidthOfVerticalArea(int[][] points) {
int[] arr = new int[points.length];
for (int i = 0; i < points.length; i++) {
arr[i]=points[i][0];
}
Arrays.sort(arr);
int max = 0;
for (int i = 1; i < arr.length; i++) {
max=Math.max(arr[i]-arr[i-1],max);
}
return max;
}
}
咋说呢,仔细读题就会发现,它那个题意其实就是告诉你,比较x之间有没有点存在,找最长的x,也就是说,只比较x就对了,可以画个图看看
俩个都是大差不差,都行先去排序,然后比较数组的x轴,比昨天简单多了。
八股
使用聚簇索引的优势
聚簇索引的叶子节点与行数据存储在一起,也就是说在访问一次后,会将数据加载到缓存器中,再次访问,就会在内存中访问完成,不用再访问磁盘
辅助索引的叶子节点存储的是主键值而不是数据的存放地址,减少了内存的存储,方便更新数据变化,每次发生新的io操作只需要维护聚簇索引就好了,减少了重复性。
MyISAM的主索引并非聚簇索引,所以它们的存的都是都不是数据的物理地址,所以每次进行IO读取操作时都要通过算法去寻找,而聚簇索引只需要进行一次IO操作
所以,MyISAM主查询,因为内存小不负责存储数据的物理地址,在数据需要频繁更改的不建议使用MyISAM
聚簇索引需要注意的地方
主键为聚簇索引最好不要用uuid,不适合排序并且容易让索引树变得复杂,消耗更多时间和资源。与之解决的办法就是建议使用自增ID,因为聚簇索引的数据物理存放顺序和索引顺序一致,索引相邻的对应数据一定是相邻的存在磁盘上。也就是说,如果不是自增ID的任何一种算法,都会不断的去调整数据的物理地址,这样会导致磁盘碎片变多,效率降低,而且主键值占用存储越大,辅助索引保存的主键值也会变大,占用存储空间越多,就会影响IO读取的效率。
b+树的简称
Balance Tree多路平衡查找树
B+就是加强版多路平衡查找树 没有B-,B-就是B树,而且中间不是减号是横线。
mysql搜索引擎发展之全部遍历hash和二叉树
全部遍历:将表的每条数据都查找一遍
hash:hashmap是典型的kv操作,对于CURD的时间复杂度都是O(1),而树的CURD操作平均时间复杂度都是O(log2(n))。为什么不用hash呢,因为hash解决不了复杂的sql语句,例如涉及到范围查询,而且innoDB不支持hash索引
二叉树:二叉树特点是一个节点有两个子节点,每个节点长度不超过2,且左子节点小于本节点,右子节点大于等于本节点,所以比本节点大的都要向右放,小的都要忘左放
但是会出现一个问题,如果是持续递减或者持续递增呢?这样的操作又会退化成全部遍历的时间复杂度O(n)
mybatis_plus学习第三天
分页插件
MyBatis Plus 自带分页插件,只要简单的配置即可实现分页功
@Configuration
//扫描mapper接口所在的包
@MapperScan("com.atguigu.mybatisplus.mapper")
public class MyBatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
//添加分页插件
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
//添加乐观锁插件
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
}
分页测试
@Autowired
private UserMapper userMapper;
@Test
public void testPage(){
//(current当前页页码,size每页显示条数)
Page<User> page = new Page<>(2, 3);
//查询默认所有
userMapper.selectPage(page, null);
// //显示所有信息
// System.out.println(page);
//返回当前页数据
System.out.println(page.getRecords());
//返回总页数
System.out.println(page.getPages());
//返回总记录数
System.out.println(page.getTotal());
//判断有没有下一页
System.out.println(page.hasNext());
//判断有没有上一页
System.out.println(page.hasPrevious());
}
自定义分页功能
java里面的mapper
@Repository
//将一个类或接口标记成持久层组件-仓库
public interface UserMapper extends BaseMapper<User> {
/**
* 根据id查询用户信息为map集合
* @param id
* @return
*/
Map<String, Object> selectMapById(Long id);
/**
* 通过年龄查询用户信息并分页
* @param page MyBatis-Plus所提供的分页对象,必须位于第一个参数的位置
* @param age
* @return
*/
Page<User> selectPageVo(@Param("page") Page<User> page, @Param("age") Integer age);
}
对应的mapper
<!--Page<User> selectPageVo(@Param("page") Page<User> page, @Param("age") Integer age);-->
<select id="selectPageVo" resultType="User">
select uid,user_name,age,email from t_user where age > #{age}
</select>
resultType 返回的结果类型
type-aliases-package: 扫描实体类类型别名的包
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
type-aliases-package: com.atguigu.mybatisplus.pojo
测试
@Test
public void testPageVo(){
Page<User> page = new Page<>(1, 3);
userMapper.selectPageVo(page, 20);
System.out.println(page.getRecords());
System.out.println(page.getPages());
System.out.println(page.getTotal());
System.out.println(page.hasNext());
System.out.println(page.hasPrevious());
}
乐观锁悲观锁
场景
一件商品,成本价是 80 元,售价是 100 元。老板先是通知小李,说你去把商品价格增加 50 元。小李正在玩游戏,耽搁了一个小时。正好一个小时后,老板觉得商品价格增加到150 元,价格太高,可能会影响销量。又通知小王,你把商品价格降低30 元。此时,小李和小王同时操作商品后台系统。小李操作的时候,系统先取出商品价格 100 元;小王也在操作,取出的商品价格也是100 元。小李将价格加了 50 元,并将 100+50=150 元存入了数据库;小王将商品减了30 元,并将 100-30=70 元存入了数据库。是的,如果没有锁,小李的操作就 完全被小王的覆盖了。现在商品价格是 70 元,比成本价低 10 元。几分钟后,这个商品很快出售了 1 千多件商品,老板亏 1 万多。如果是乐观锁,小王保存价格前,会检查下价格是否被人修改过了。如果被修改过了,则重新取出的被修改后的价格, 150 元,这样他会将 120 元存入数据库。如果是悲观锁,小李取出数据后,小王只能等小李操作完之后,才能对价格进行操作,也会保证最终的价格是 120 元。
数据库表
CREATE TABLE t_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 t_product (id, NAME, price) VALUES (1, '外星人笔记本', 100);
添加实体类
package com.atguigu.mybatisplus.entity;
import lombok.Data;
@Data
public class Product {
private Long id;
private String name;
private Integer price;
@Version//用来表示乐观锁版本号字段
private Integer version;
}
添加mapper
@Repository
public interface ProductMapper extends BaseMapper<Product> {
}
乐观锁config
@Configuration
//扫描mapper接口所在的包
@MapperScan("com.atguigu.mybatisplus.mapper")
public class MyBatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
//添加分页插件
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
//添加乐观锁插件
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
}
测试
@Test
public void testProduct01(){
//小李查询商品价格
Product productLi = productMapper.selectById(1);
System.out.println("小李查询的商品价格:"+productLi.getPrice());
//小王查询商品价格
Product productWang = productMapper.selectById(1);
System.out.println("小王查询的商品价格:"+productWang.getPrice());
//小李将商品价格+50
productLi.setPrice(productLi.getPrice()+50);
productMapper.updateById(productLi);
//小王将商品价格-30
productWang.setPrice(productWang.getPrice()-30);
int result = productMapper.updateById(productWang);
if(result == 0){
//操作失败,重试
Product productNew = productMapper.selectById(1);
productNew.setPrice(productNew.getPrice()-30);
productMapper.updateById(productNew);
}
//老板查询商品价格
Product productLaoban = productMapper.selectById(1);
System.out.println("老板查询的商品价格:"+productLaoban.getPrice());
}
乐观锁流程
SELECT id,`name`,price,`version` FROM product WHERE id= 1
UPDATE product SET price=price+ 50 , `version`=`version` + 1 WHERE id= 1 AND`version`= 1
通用枚举
@Getter
public enum SexEnum {
MALE(1, "男"),
FEMALE(2, "女");
@EnumValue //将注解所标识的属性的值存储到数据库中
//本来应该传入数据库 "男""女"的,但是数据库里面是int类型,需要前面的1,2
//这边设置完后去配置里面配置枚举扫描包
private Integer sex;
private String sexName;
SexEnum(Integer sex, String sexName) {
this.sex = sex;
this.sexName = sexName;
}
}
实体类 user添加
private SexEnum sex;
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
#配置类型别名对应的包
type-aliases-package: com.atguigu.mybatisplus.pojo
#扫描通用枚举包
type-enums-package: com.atguigu.mybatisplus.enums
# #设置myBatis-plus全局配置
# global-config:
# db-config:
# #设置实体类表的统一前缀
# table-prefix: t_
# #配置MyBatis-Plus的主键策略
# id-type: auto
@SpringBootTest
public class MyBatisPlusEnumTest {
@Autowired
private UserMapper userMapper;
@Test
public void test(){
User user = new User();
user.setName("admin");
user.setAge(33);
user.setSex(SexEnum.MALE);
int result = userMapper.insert(user);
System.out.println("result:"+result);
}
}
代码生成器
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.31</version>
</dependency>
快速生成
public class FastAutoGeneratorTest {
public static void main(String[] args) {
FastAutoGenerator.create("jdbc:mysql://127.0.0.1:3306/mybatis_plus?characterEncoding=utf-8&userSSL=false", "root", "123456")
.globalConfig(builder -> {
builder.author("atguigu") // 设置作者
//.enableSwagger() // 开启 swagger 模式
.fileOverride() // 覆盖已生成文件
.outputDir("D://mybatis_plus"); // 指定输出目录
})
.packageConfig(builder -> {
builder.parent("com.atguigu") // 设置父包名
.moduleName("mybatisplus") // 设置父包模块名
.pathInfo(Collections.singletonMap(OutputFile.mapperXml, "D://mybatis_plus")); // 设置mapperXml生成路径
})
.strategyConfig(builder -> {
builder.addInclude("t_user") // 设置需要生成的表名
.addTablePrefix("t_", "c_"); // 设置过滤表前缀
})
.templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
.execute();
}
}
多数据源
适用于多种场景:纯粹多库、 读写分离、 一主多从、 混合模式等目前我们就来模拟一个纯粹多库的一个场景,其他场景类似场景说明:我们创建两个库,分别为: mybatis_plus (以前的库不动)与 mybatis_plus_1 (新建),将mybatis_plus 库的 product 表移动到 mybatis_plus_1 库,这样每个库一张表,通过一个测试用例分别获取用户数据与商品数据,如果获取到说明多库模拟成功
创建数据库 mybatis_plus_1 和表 product
CREATE DATABASE `mybatis_plus_1` /*!40100 DEFAULT CHARACTER SET utf8mb4 */ ;use `mybatis_plus_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 );
use mybatis_plus;DROP TABLE IF EXISTS product;
<dependency><groupId> com.baomidou </groupId><artifactId> dynamic-datasource-spring-boot-starter </artifactId><version> 3.5.0 </version></dependency><!-- mybatis-plus启动器 --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.1</version> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-generator</artifactId> <version>3.5.1</version> </dependency> <dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.31</version> </dependency> <!-- lombok简化实体类开发 --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <!-- mysql驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> <version>5.1.47</version> </dependency>
spring :# 配置数据源信息datasource :dynamic :# 设置默认的数据源或者数据源组, 默认值即为 masterprimary : master# 严格匹配数据源 , 默认 false.true 未匹配到指定数据源时抛异常 ,false 使用默认数据源strict : falsedatasource :master :url : jdbc : mysql : //localhost : 3306/mybatis_plus?characterEncoding=utf-8&useSSL=falsedriver-class-name : com.mysql.cj.jdbc.Driverusername : rootpassword : 123456slave_1 :url : jdbc : mysql : //localhost : 3306/mybatis_plus_1?characterEncoding=utf-8&useSSL=falsedriver-class-name : com.mysql.cj.jdbc.Driverusername : rootpassword : 123456
package com.atguigu.mybatisplus.pojo;
import com.atguigu.mybatisplus.enums.SexEnum;
import com.baomidou.mybatisplus.annotation.*;
import lombok.*;
/**
*/
@Data
//@NoArgsConstructor
//@AllArgsConstructor
//@Getter
//@Setter
//@EqualsAndHashCode 一个data注解包括这五个
//设置实体类所对应的表名
@TableName("t_user")
public class User {
//将属性所对应的字段指定为主键
//@TableId注解的value属性用于指定主键的字段
//@TableId注解的type属性设置主键生成策略
//mybatis-plus默认雪花算法 如果我想用mysql自动递增呢
//@TableId(value = "uid", type = IdType.AUTO)
@TableId("uid")
private Long uid;
//指定属性所对应的字段名
//@TableField("user_name")
private String userName;
private Integer age;
private String email;
private SexEnum sex;
//@TableLogic
private Integer isDeleted;
}
@Data
public class Product {
private Long id;
private String name;
private Integer price;
private Integer version;
}
mapper
@Repository
public interface ProductMapper extends BaseMapper<Product> {
}
@Repository
public interface UserMapper extends BaseMapper<User> {
}
主启动类
@SpringBootApplication
//扫描mapper的包
@MapperScan("com.atguigu.mybatisplus.mapper")
//或者自己创建一个config类 让springboot去自己扫描
//@Configuration
//@MapperScan({"com.atguigu.mybatisplus.alibaba.mapper"})
public interface UserService extends IService<User> {
}
@DS("master") //指定所操作的数据源
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements
UserService {
}
public interface ProductService extends IService<Product> {
}
@DS("slave_1")
@Service
public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product>
implements ProductService {
}
测试
package com.atguigu.mybatisplus;
import com.atguigu.mybatisplus.service.ProductService;
import com.atguigu.mybatisplus.service.UserService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class MybatisPlusDatasourceApplicationTests {
@Test
void contextLoads() {
}
@Autowired
private UserService userService;
@Autowired
private ProductService productService;
@Test
public void test(){
System.out.println(userService.getById(1));
System.out.println(productService.getById(1));
}
}
关于@DS
MyBatisX插件
MyBatis-Plus 为我们提供了强大的 mapper 和 service 模板,能够大大的提高开发效率但是在真正开发过程中, MyBatis-Plus 并不能为我们解决所有问题,例如一些复杂的 SQL ,多表联查,我们就需要自己去编写代码和 SQL 语句,我们该如何快速的解决这个问题呢,这个时候可以使用 MyBatisX 插件MyBatisX 一款基于 IDEA 的快速开发插件,为效率而生。
去idea下载MyBatisX
这个写在yml里面,一般默认在配置类下的mapper,想改自己改
另外使用mybatis-plus 都是引用之前的依赖,跟yml 不写了
接下来是一些流程图片(截图来自老师视频)
这个解释下,基本上汉化的都有
工程文件
包名 编码 父类
java代码的地址 字段前缀 表名前缀
实体类对象包名 字段后缀 表名后缀
注解
选项 注释 .....
模板
快速crud
选中要使用的插件快捷方法 在红名上面alt+enter补全即可
添加
去配置类里面就能看见自动生成的代码
之后就是各种使用图片
删除
修改
通过by来生成条件
查询
排序
总结
本来两天能学完的,但是这两天学习劲头不太好,就宁可在算法上耗时间也不愿意去听课,因为听课得做笔记(X-X),腻了,感觉需要一定时间调节下自己,今天也是一样,听完后感觉心里面闷闷的,不是很自在,感觉有个无形东西压着自己,跟我之前寒假学java一段时间后的疲惫期有点像。那段时间学的基本都忘了例如mybatis,我记得那时候强制自己学的ssm跟springboot,显然ssm学的不是很好,虽然后面又因为面试题回去看了spring和spingmvc的内容,学springcloud重新温故了一遍springboot的部分知识,其实我感觉也是跟不常用有关,会忘的,为啥学mybatis-plus,因为最后的springcloud用上了,我发现我除了对server,imp和mapper有印象,其他的基本都忘的差不多了,感觉那段时间学习效率挺低效的,该记得都没记住,虽然每天上午学完下午学,但是总是记不住昨天或者前天的内容。一直到返校前开题答辩,然后加上家里的各种过年的事情才休息了半个月多,回校后才慢慢好起来。
至于接下来的计划,不出意外应该是回顾mybatis,之后看硅谷的第二季第三季面试题,刷完后看看还缺啥么,去b站找个项目做做,弄个重点业务学学。但是不高强度学了,每天从五六个小时降低到四个小时左右吧,不然感觉真心压不住。