第二十九天

练习

两点之间不包含任何点的最宽垂直区域

给你 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 自带分页插件,只要简单的配置即可实现分页功
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;
    }

}

分页测试

    @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());
    }

乐观锁流程

数据库中添加 version 字段
取出记录时,获取当前 version
SELECT id,`name`,price,`version` FROM product WHERE id= 1
更新时, version + 1 ,如果 where 语句中的 version 版本不对,则更新失败
UPDATE product SET price=price+ 50 , `version`=`version` + 1 WHERE id= 1 AND
`version`= 1

通用枚举

enums枚举
@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;
配置yml
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 );
删除 mybatis_plus product
use mybatis_plus;
DROP TABLE IF EXISTS product;
新建项目
mybatis_plus_datasource
引入依赖
<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>
注释掉之前的数据库连接,添加新配置
yml
spring :
# 配置数据源信息
     datasource :
          dynamic :
                # 设置默认的数据源或者数据源组, 默认值即为 master
                primary : master
                # 严格匹配数据源 , 默认 false.true 未匹配到指定数据源时抛异常 ,false 使用默认数据源
                strict : false
                datasource :
                  master :
                        url : jdbc : mysql : //localhost : 3306/mybatis_plus?characterEncoding=utf-
8&useSSL=false
                        driver-class-name : com.mysql.cj.jdbc.Driver
                        username : root
                        password : 123456
                  slave_1 :
                        url : jdbc : mysql : //localhost : 3306/mybatis_plus_1?characterEncoding=utf-
8&useSSL=false
                        driver-class-name : com.mysql.cj.jdbc.Driver
                        username : root
                        password : 123456
实体类pojo
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"})
用户service
public interface UserService extends IService<User> {
}


@DS("master") //指定所操作的数据源
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements
UserService {
}
商品service
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

MyBatisX 插件用法: https://baomidou.com/pages/ba5b24/
大部分东西不写了,上面用法写的比我全

这个写在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站找个项目做做,弄个重点业务学学。但是不高强度学了,每天从五六个小时降低到四个小时左右吧,不然感觉真心压不住。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值