MybatisPlus学习4--MybatisPlus中提供的插件
####分页插件
问题:如何在MybatisPlus中使用分页插件?
–解答:这也是MybatisPlus相较于Mybatis功能更加强大的一个方面,在MybatisPlus中封装了分页功能,使用户可以更加方便的使用分页操作。具体使用方法为:
创建分页配置类
1234567891011121314151617181920package com.deng.config;import com.baomidou.mybatisplus.annotation.DbType;import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;import org.mybatis.spring.annotation.MapperScan;import org.springframework.context.annotation.Bean;import ...
MybatisPlus学习3
问题:MybatisPlus中如何进行有条件查询?
–解答:在MybatisPlus中进行条件查询有两种方式,第一种就是在XxxMapper中编写自定义SQL语句;另一种就是使用MybatisPlus提供的条件查询抽象类Wrapper,该抽象类是MybatisPlus中的顶级条件查询父类,我们一般使用其子类的子类来进行条件查询。
LambdaWrapper可以使用Lambda表达式指定查询或修改条件,优点是可以确保字段的正确;
UpdateWrapper和QueryWrapper分别对应修改和查询时指定条件,相较于使用Lambda语法,可能会出现字段书写错误导致数据库中出现错误信息。
实际使用QueryWrapper
12345678910@Testpublic void testQueryWrapper(){ QueryWrapper<User> queryWrapper = new QueryWrapper<>(); //查询name中有‘张’,年龄在10~20之间并且邮箱不为空的记录 queryWrapper.li ...
Redis--黑马点评项目秒杀优化
问题:当前秒杀功能的执行逻辑是怎样的?
–解答:
问题:这种逻辑存在什么问题?
–解答:所有处理均由一个线程完成,性能较低。
问题:如何进行优化?
–解答:可以使用Redis完成检查库存是否充足和校验一人一单的过程,对于满足条件的线程(请求),将其放入阻塞队列中,异步的处理这些请求(生成订单,扣减库存,将订单信息存入数据库中)
问题:为什么要用阻塞队列?
–解答:因为我们想要异步的处理生成订单的请求,而不是一旦某个用户满足条件,就立即为他生成订单(这里的生成订单指的是扣减数据库中的库存)。
问题:BlockingQueue有哪些特性?
–解答:本质上是一个队列,这也是一个接口,有多个实现类,这里选择的是ArrayBlockingQueue。阻塞队列最大的特点就是,当取不到数据时,该线程会一直等待,直到队列中有数据。
问题:那这样不会影响效率吗,因为要一直等待?
–解答:由于我们在处理订单,也就是从阻塞队列中取数据时,是交给另一个线程来做的,因此对我们的主线程不会有影响,其实主线程在redis判断完后就基本上可以将秒杀结果返回给用户了。
问题:Redis中是如何 ...
MybatisPlus学习2
问题:什么是MybatisPlus?为什么需要使用MybatisPlus?MybatisPlus如何使用?
–解答:MybatisPlus是基于Mybatis而开发的一个持久层框架,在Mybatis中能够完成的操作在MybatisPlus中都能够完成,MybatisPlus的口号是“只做增强,不做修改”。
–解答:相较于Mybatis,使用MybatisPlus更加方便,比如在MybatisPlus中提供了一个BaseMapper接口,在这个接口中提供了基本的CRUD操作,我们不需要在mapper.xml文件中编写SQL语句。
–解答:使用方法非常简单,详细教程可以参考mybatisplus官网
MybatisPlus
问题:在MybatisPlus中如何自定义SQL语句?
解答:刚才提到BaseMapper接口中提供大量基础的CRUD操作,如果想要编写自定义SQL语句,就需要像在Mybatis中一样,需要在Xxxmapper.xml文件中进行。具体步骤为:
需要在yaml文件中给mybatis-plus的mapper-locations属性进行配置,该属性有一个默认 ...
MIT6.S081操作系统学习-4
中断(Interrupt)问题:什么是中断?为什么需要中断?中断是如何产生的?操作系统中是如何处理中断的?
–解答:和page fault一样,中断也会引起trap机制。当发生中断时,系统需要停止当前运行的工作,优先处理中断事件。在操作系统中主要有3类中断:由软件引起的中断、时钟中断(用于时间片调度算法)以及外部设备引起的中断(比如网卡受到一个packet后,在某个时间点会产生中断将处理完的packet交给操作系统)。在本节主要介绍最后一种中断。
在计算机中为了提高运行效率,几乎所有外部设备和CPU都是并行运行的,这样做的好处是可以充分利用CPU资源。因此当外部设备准备好了后(一些资源的初始化操作),必须依靠某种机制使它们能够和CPU进行交互。这种机制就是中断,它们会产生一个中断,告诉操作系统我需要CPU。
当产生中断时,我们需要在内核处理这些中断,因此会触发trap机制完成到内核的切换以及保存好那些重要的用户数据,这个过程在之前讲过,这里不再赘述。在操作系统中设置了PLIC(Platform Level Interrupt Control)用于将这些中断分发给CPU。更具 ...
MybatisPlus学习--1.入门程序
MybatisPlus概述及入门程序 MybatisPlus是由国人开发的基于Mybatis但功能更加强大的持久层框架。内部提供了大量接口,相较于Mybatis更加灵活、更加强大。
使用
引入依赖,SpringBoot3.0及以上需要使用以下MybatisPlus依赖
12345<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-spring-boot3-starter</artifactId> <version>3.5.5</version> </dependency>
在application.yml中进行相关配置
123456789101112spring: #数据源配置 datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: j ...
JUC--synchronized使用
####synchronized
synchronized关键字是java中实现互斥锁的一种方式,只能以某个对象作为锁,只有获得锁的线程才能进入代码区。
使用方法:
123synchronized(对象){ 需要加锁的代码}
synchronized关键字加在成员方法上时,默认以本对象作为锁
123public synchronized void a(){ }
synchronized关键字加在静态方法上时,默认以本类作为锁
123public static synchronized void b(){ }
Redis--黑马点评项目使用Redisson框架
在经过我们不断的改进后,可以说此时项目中的分布式锁是一个相对完善的锁,但依然存在着改进的空间。比如:
当前项目中的锁是不可重入的锁:同一个线程无法多次获取同一把锁,有时候我们会有这样的需求:A方法中需要获取锁并会调用同一个类中的方法B,同时在B方法中也需要获取锁,如果当前系统的锁不是可重入锁,那么就会造成死锁问题。
当前项目中的锁是不可重试的锁:当某个线程获取锁失败后,直接返回错误,该线程无法重试。
当前项目中的锁在Redis集群模式下可能存在问题:在Redis集群模式下,主从节点间存在一定的同步延迟,如果主节点宕机而从节点又未能及时同步存储在主节点中的锁信息,可能会导致线程安全问题。
以上几种问题可以自己实现解决方案,但是我们可以使用他人开发好的分布式框架——Redisson来解决以上问题,避免重复造轮子。Redisson是一个基于Redis的分布式框架。在解决以上问题的同时,Redisson实现的分布式锁利用watchdog机制实现了不断更新锁的有效期,避免因为线程阻塞而锁释放导致线程安全问题的出现
使用步骤:
引入Redisson依赖
123456&l ...
Redis--黑马点评项目分布式锁释放存在的问题
以上这张图描述了这样一种场景:线程1在获取分布式锁后进入业务阻塞状态,并且阻塞时间甚至超过了我们设置的锁过期时间。在此期间,线程2成功获取了锁并开始执行业务,此时被阻塞的线程1又恢复运行并完成了业务,于是按照代码逻辑线程1会去释放锁,此时另一个线程3又来获取锁,造成了线程安全问题。
出现该问题的本质原因在于在编写锁的释放代码时,并没有添加判断条件,这样做的漏洞就是释放的锁不一定是自己的锁。解决的方案也很简单,只需要在释放锁之前判断是否是自己的锁。可以使用UUID+线程id作为判断的标识,需要注意的是这种标识依旧无法做到完全唯一。如果想要实现标识完全唯一,可以使用每台电脑的MAC+线程id作为标识。本项目使用的是第一种方案
123456789101112 private static final String LOCK_PREFIX = UUID.randomUUID().toString(true);/** * 释放锁 */ public void unLock(){ String threadId = LOCK_PREFIX + ...
JUC--java中线程的状态
问题:在java中的线程有哪些状态?和操作系统中线程的状态有何不同?线程有哪些常见的状态转换?
–解答:在java中线程有6种状态,分别是NEW、RUNNABLE、WAITING、TIMED_WAITING、BLOCKED和TERMINATED。
在操作系统中一个正在运行的线程由于需要等待某个条件满足才能继续运行时,就会进入等待状态。java语言基于操作系统提供的状态做了一些细化和改变(在操作系统层面,java中不同状态的线程其实是相同状态)。比如:由IO引起的等待在java中不算等待而是RUNNABLE状态(在操作系统层面,该线程还是处于等待状态);由wait(),join(),park()引起的线程等待属于WAITING状态;由sleep(long time),wait(long time)等方法引起的线程等待属于TIMED_WAITING状态;争抢锁资源失败的线程属于BLOCKED状态。而这些状态在操作系统中都属于等待状态。
JUC--守护线程
在java中默认情况下只要有一个线程处于运行状态,那么整个java程序就不会停止运行。需要注意的是main线程只是java程序中的其中一个线程,main线程的结束不代表整个java程序的结束。
在java中有一种特殊的线程——守护线程,该线程的特点是当程序中不存在其他非守护线程运行时,该守护线程会自动结束运行。比如垃圾回收器线程就是一种守护线程。可以使用setDaemon(true)方法将一个普通线程转换为守护线程
MIT6.S081操作系统学习-3
Page faults page faults译为页面错误,是指发生在计算机操作系统中的一种情况,当程序需要访问某个页面但该页面不在内存中时,就会发生页面错误。
关于page faults,我们需要知道的是当用户程序触发了page fault之后,会触发trap机制,系统会跳转到内核状态。并且会将引起出错的虚拟地址存放在STVAL寄存器中,将出错原因存放在SCAUSE寄存器中。(为了便于保存,会将出错原因和数字关联起来,比如15表示的是由store指令引起的page fault)
针对page fault最直接的解决方案为给用户程序增加指定数量的空闲的物理内存(eager allocation),但这种方式的缺点是在大多数情况下,用户程序并不知道自己会用到多少内存,因此在分配的内存中可能有大部分内存实际上根本没有使用。
#####lazy allocation
另一种更加聪明的方法是在逻辑上增加内存,只有当用户实际使用这些内存时才真正分配内存(lazy allocation)
#####zero fill on demand
还有一个使用非常频繁的功能:zero fi ...
