关于sql的一些学习
关于trim标签的使用
属性
描述
prefix
给sql语句拼接的前缀
suffix
给sql语句拼接的后缀
prefixOverrides
去除sal语句前面的关键字或者字符,该关键字或者字符由prefxOverrides属性指定,假设该属性指定为”AND”,当sql语句的开头为”AND”,trim标签将会去除该”AND”
suffixOverrides
去除sql语句后面的关键字或者字符,该关键字或者字符由suffixOverrides属性指定
例如下面的sql语段1234<trim prefix="(" suffix=")" suffixOverrides=","> <if test="id != null">id,</if> <if test="name != null">name,</if> </trim>就是在sql中将前缀拼接为”(“,后缀拼接为”)”,并 ...
关于git
获取仓库1.获取本地仓库在需要创建仓库的文件夹中打开git bash,并输入1git init
2.获取线上仓库1git clone <项目地址>
仓库相关指令1.本地仓库123456git status 查看仓库状态git add 添加所有文件到暂存区git reset 撤销暂存区文件git reset --hard 回退到指定版本git commit -m "提交信息" 提交暂存区文件到本地仓库git log 查看提交历史
2.线上仓库当同事A上传了代码后,同事B使用clone获取代码。在获取代码后我们可以对代码进行更新。更新后同事B可以直接push代码到托管平台,同事A想查看更新可以直接pull代码,不需要再进行clone.12345git remote 查看远程仓库git remote add origin <项目地址> 添加远程仓库git ...
关于redis使用场景
关于redis常用的数据类型String: 字符串。 set key value ; get key
Hash:键值对集合,存储多个字段。 hset key field value ; hget key field ; hmset key field1 value1 field2 value2 ; hmget key field1 field2 (存储/获取一个或多个哈希是键值对的集合)
List:列表,按插入顺序排序。 lpush key value ; rpush key value ;(插入元素到列表的头部/尾部) lpop key ; rpop key (从头/尾删除一个元素) lrange key start end (获取列表指定范围的元素)
Set:集合,无序不重复。 sadd key value ; srem key value ; smembers key (添加/删除元素到集合/获取集合所有元素)
Zset:有序集合 每个元素都会关联double类型的分数,元素唯一但是分数可以重复。 zadd key score v ...
关于线程池的问题
线程池执行原理线程池参数设置1.corePoolSize 核心线程数,默认是cpu核数。2.maximumPoolSize 最大线程数,默认是Integer.MAX_VALUE。3.keepAliveTime 非核心线程空闲时间,默认60s。4.unit 时间单位,默认TimeUnit.SECONDS。5.workQueue 阻塞队列,默认是LinkedBlockingQueue。6.threadFactory 线程工厂,默认是DefaultThreadFactory。
执行原理当我们提交任务时,要先判断核心线程是否已满,若没满则添加到工作线程并执行,若满了则判断阻塞队列是否已满,若没满则把任务添加到阻塞队列,若满了则判断线程数是否小于最大线程数,若小于则我们使用非核心线程来处理最新的任务,处理后非核心线程会检查阻塞队列中是否有要执行的线程,若有则处理。若线程数大于最大线程数,则使用拒绝策略。拒绝策略分四点:1.AbortPolicy:直接抛出异常,默认。2.CallerRunsPolicy:由调用者所在的线程来执行任务。3.DiscardOldestPolicy:丢弃阻塞队列中最靠前 ...
关于线程安全问题
synchronized关键字的底层原理synchronized是互斥锁,同一时刻只有一个线程能持有对象锁,synchronized基于monitor实现,修饰代码块时会使用monitorenter和monitorexit指令,当一个线程执行monitorenter指令时,会尝试获取对象的锁,如果成功,则执行代码块,执行完毕后释放锁,如果失败,则阻塞线程,直到锁被释放。monitor中由waitset,entrylist,owner组成。owner中存储获取对象锁的线程,只有一个线程在owner里面,entrylist中存放的是没有抢到锁的线程,当owner里面没有线程的时候entrylist里面的线程会进行争抢,最后抢到锁的线程进入owner,其他线程仍然在entrylist处于阻塞状态。waitset中存放的是调用了wait方法的线程。
synchronized和lock区别synchronized是Java关键字,由C++实现,lock是java.util.concurrent包下的类。使用synchronized时退出同步代码块锁会自动释放,使用lock时需手动调用unlock ...
关于多线程的基础问题
线程和进程的区别进程是计算机资源分配的基本单位,线程是CPU调度的基本单位,一个进程中包含了多个线程来完成不同的任务。不同的进程会使用不同的内存空间,在同一个进程中的所有线程可以共享内存空间。线程相对来说更轻量化,线程的上下文切换要比进程的切换效率高。
并发与并行的区别并发是计算机在同一时间应对多个事情,线程轮流使用CPU。并行是计算机在同一时间做多个事情,多个线程同时使用CPU。
创建线程的方式
继承Thread类创建线程
实现Runnable接口创建线程
实现Callable接口创建线程
线程池创建线程runnable和callable的区别Runnable接口中run()方法没有返回值,而Callable接口中call()方法有返回值,是泛型,和Future、FutureTask配合使用可以实现异步调用。同时Callable接口的call()方法允许抛出异常,而Runnable的run()方法的异常只能内部解决。run()和start()的区别start()用来启动线程,通过该线程调用run方法执行run方法中定义的代码,start()方法只能被调用一次run()封装了要被线程执 ...
关于Mybatis的一些问题
关于MybatisMybatis是一个半ORM(对象关系映射)的框架,内部封装了JDBC,使用时可只注意便携SQL语句,不需要手动创建链接等操作。但是SQL语句编写工作量大,且不能随意更改数据库。
关于Mybatis的执行流程首先在maven中我们导入了mybatis-spring-boot的起步依赖,然后在application.properties/application.yml中配置了mybatis的相关配置,包括mybatis的配置文件路径、数据库连接信息等。创建完依赖后我们会构建会话工厂SqlSessionFactory,然后我们就可以通过SqlSessionFactory来创建会话对象,然后我们操作数据库接口,Executor执行器,同时负责查询缓存的维护。Executor接口中有MappedStatement类型的参数,封装了映射信息。最后我们输入参数映射并等待输出结果映射。(说实话没听懂)
关于Mybatis传递多个参数1.参数可以像数组一样用下标传递,如#{0}则代表传递第0个参数2.可以使用@Param注释来指定参数,在方法中例如public void addUse ...
关于Spring的一些问题
单例bean是线程安全的吗Spring 的单例bean不是线程安全的。如果bean中定义了可修改的成员变量,就可能会有其他线程对其进行修改,所以线程不是安全的。我们可以把单例的bean修改成多例模式或者加锁来解决。
关于AOPAOP是面向切面编程,主要是把公共模块抽离代码,降低耦合。
项目中有没有用到AOP?用到过,主要是使用环绕通知和切点的方式,对controller中的方法进行参数拦截,获取到参数后进行判断,如果不满足aop定义的规则则调用自己定义的错误方法报错。
关于Spring事务Spring事务主要分为两种,编程式事务和声明式事务。其中编程式事务需使用方法实现,对业务代码有入侵性,很少使用。而声明式事务是建立在AOP之上的,主要是通过AOP对方法前后进行拦截,方法执行完后根据运行情况进行提交或回滚。
事务失效事务失效有很多种情况。首先是异常捕获处理不当会导致事务失效。在trycatch中如果我们自己处理了异常,事务无法得知,则会出现事务失效。正确的解决方法是将异常抛出,让事务知晓代码出了异常,从而进行回滚。其次是Spring默认只会回滚非检查异常,在方法中定义了检查类异常会导 ...
关于HashMap的基本原理
简述HashMap的基本原理HashMap是基于哈希表实现的,由数组+链表\红黑树组成。在添加数据时先计算key的哈希值,若key的哈希值和某个值的哈希值相同,则比对key和值的区别,若相同则进行替换,若不同则存入链表或红黑树中。具体在下面的put方法实现中。在JDK1.7版本中,HashMap仅采用数组加链表的形式进行存储,后来在JDK1.8中引入了红黑树,在链表长度>8且数组长度>64时,链表会自动转换为红黑树进行存储,若红黑树的大小小于6时会退化成链表。
简述HashMap的put过程Hash在添加数据时首先会进行判断,判断数组是否为空,若为空则初始化一个长度为16的数组并进行添加。若不为空则根据key的哈希值进行索引,若哈希值为空则直接添加,并判断size+1是否大于临界值,若大于临界值则需要进行扩容。若key的哈希值不为空则有两种情况,一种是有两个一模一样的key插入进来,还有一种就是虽然哈希值相同但是key不相同,因为哈希值是有限的。这时候就要判断key是否相同。若相同则直接进行替换,以最后的key为主。若不相同则要把key存入数组下的链表或红黑树中。这时候我们 ...
关于ArrayList和LinkedList以及其他单列集合
集合单列:(基于Collectrion) List(ArrayList,LinkedList,Vector) Set(HashSet,TreeSet)双列:(基于Map)Map(HashMap,ConcurrentHashMap,HashTable,TreeMap)
ArrayList基本概述与扩容机制ArrayList是由动态数组实现的,初始容量为0,在第一次添加数据时会出发ArrayList扩容机制扩容到10。当添加的数量超过了ArrayList的容量时,ArrayList会自动扩容为原来的1.5倍。关于ArrayList的扩容机制,ArrayList会调用ensureCapacityInternal方法先判断容量是否足够,如果不够就创建一个原来长度1.5倍的新数组,然后把原数组复制到新数组中,并且添加要添加的元素。
区别ArrayList是基于动态数组实现的,而LinkedList是基于双向链表实现的。在查找数据时,ArrayList可以使用下标进行查询,时间复杂度是O(1),而LinkedList需要遍历链表,时间复杂度是O(n)。但是他们两个都不是线程安全的。如需 ...










