Mybatis的整体框架分为三层,分别是接口层、核心处理层、和基础支持层。如下图 Mybatis的核心工作流程图如下: 一、基础支持层 基础支持层位于MyBatis整体架构的最底层,支撑着MyBatis的核心处理层,是整个框架的基石。基 础支持层中封装了多个较为通用的、独立的模块。不仅仅为MyBatis提供基础支撑,也可以在合适的场 景中直接复用。 1.反射模块 MyBatis在进行参数处理、结果集映射等操作时会使用到大量的反射操作,Java中的反射功能虽然强 大,但是代码编写起来比较复杂且容易出错,为了简化反射操作的相关代码,MyBatis提供了专门的反 射模块,该模块位于org.apache.ibatis.reflection包下,它对常见的反射操作做了进一步的封装,提供 了更加简洁方便的反射API。 Reflector类 // 对应的Class 类型 private final Class<?> type; // 可读属性的名称集合 可读属性就是存在 getter方法的属性,初始值为null private final String[] readablePropert.... MyBatis(2)的体系结构与核心工作原理分析 java
MyBatis的特点: 使用连接池对连接进行管理 SQL和代码分离,集中管理 结果集映射 参数映射和动态SQL 重复SQL的提取 缓存管理 插件机制 MyBatis核心配置 全局配置文件 MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置和属性信息。 配置文档的顶层结构如下: configuration(配置) properties(属性) settings(设置) typeAliases(类型别名) typeHandlers(类型处理器) objectFactory(对象工厂) plugins(插件) environments(环境配置) environment(环境变量) transactionManager(事务管理器) dataSource(数据源) databaseIdProvider(数据库厂商标识) mappers(映射器) MyBatis最佳实践 Executor SimpleExecutor:每执行一次update或select,就开启一个Statement对象,用完立刻关闭Statement对象。 ReuseExecutor:执行update或s.... MyBatis(1)高级应用 java
B+ 树简介 B+树是B-树的变体,也是一颗多路搜索树。一棵m阶的B+树主要有这些特点: 每个结点至多有m个子女; 非根节点关键值个数范围:⌈m/2⌉ - 1 <= k <= m-1 相邻叶子节点是通过指针连起来的,并且是关键字大小排序的。 一颗3阶的B+树如下: B+树和B-树的主要区别如下: B-树内部节点是保存数据的;而B+树内部节点是不保存数据的,只作索引作用,它的叶子节点才保存数据。 B+树相邻的叶子节点之间是通过链表指针连起来的,B-树却不是。 查找过程中,B-树在找到具体的数值以后就结束,而B+树则需要通过索引找到叶子结点中的数据才结束 B-树中任何一个关键字出现且只出现在一个结点中,而B+树可以出现多次。 B+树经典面试题 InnoDB一棵B+树可以存放多少行数据? 在文件系统中,最小单位是块,一个块大小就是4k; InnoDB存储引擎最小储存单元是页,一页大小就是16k。 因为B+树叶子存的是数据,内部节点存的是键值+指针。索引组织表通过非叶子节点的二分查找法以及指针确定数据在哪个页中,进而再去数据页中找到需要的数据; 假设B+树的高度为2的话,即有一个..... 树(8)B+树 java
红黑树的应用 Java中,TreeMap、TreeSet都使用红黑树作为底层数据结构 JDK 1.8开始,HashMap也引入了红黑树:当冲突的链表长度超过8时,自动转为红黑树 Linux底层的CFS进程调度算法中,vruntime使用红黑树进行存储。 多路复用技术的Epoll,其核心结构是红黑树 + 双向链表。 满足一个树是红黑树条件: 每个节点要么是红色,要么是黑色。 根节点必须是黑色 红色节点不能连续 从任意节点出发,到其所有叶子节点的简单路径上都包含相同数目的黑色节点.(非常重要) 每个红色节点的两个子节点一定都是黑色(叶子节点包含NULL) 一棵典型的红黑树,如图1.1所示 插入 1.插入节点置为红色,当插入位置为根节点时,改成黑色即可,插入位置的父节点为黑色时,直接插入。 2.当插入位置的父节点为红色时,分两种情况讨论 第一种情况父节点是左子树 对于这种情况又可以分为以下3中小的情况考虑 1.叔叔节点是黑色(null节点也是黑色),插入到左子树中 2.叔叔节点是黑色(null节点也是黑色),插入到右子树中 3.叔叔节点是红色 第二种情况,父节点是右子树 这种情况也可以分为以.... 树(5)红黑树 java
为什么需要B-树? B-树是一种平衡的多路查找树,注意: B树就是B-树,"-"是个连字符号,不是减号 。 在大多数的平衡查找树(Self-balancing search trees),比如 AVL 树 和红黑树,都假设所有的数据放在主存当中。那为什么要使用 B-树呢(或者说为啥要有 B-树呢)?要解释清楚这一点,我们假设我们的数据量达到了亿级别,主存当中根本存储不下,我们只能以块的形式从磁盘读取数据,与主存的访问时间相比,磁盘的 I/O 操作相当耗时,而提出 B-树的主要目的就是减少磁盘的 I/O 操作。大多数平衡树的操作(查找、插入、删除,最大值、最小值等等)需要 次磁盘访问操作,其中 是树的高度。但是对于 B-树而言,树的高度将不再是 (其中 是树中的结点个数),而是一个我们可控的高度 (通过调整 B-树中结点所包含的键【你也可以叫做数据库中的索引,本质上就是在磁盘上的一个位置信息】的数目,使得 B-树的高度保持一个较小的值)。一般而言,B-树的结点所包含的键的数目和磁盘块大小一样,从数个到数千个不等。由于B-树的高度 h 可控(一般远小于 ),所以与 AVL 树和.... 树(7)B-树 java
哈夫曼是也叫最优二叉树,给我n个带权值的节点,权值可以表示被访问的频率等等,我要做的就是将这n个带权值的节点构成二叉树,限制条件是这n个节点都是所构成二叉树中的叶子节点,且权值越大的叶子节点,到根节点的路径越短,所以由n个节点构成的满足限制条件的二叉树一共有2n-1个节点,且被称为哈夫曼树,又称最优二叉树, 哈夫曼树的概念 概念1:什么是路径? 在一棵树中,从一个结点到另一个结点所经过的所有结点,被我们称为两个结点之间的路径。 上面的二叉树当中,从根结点A到叶子结点H的路径,就是A,B,D,H 概念2:什么是路径长度? 在一棵树中,从一个结点到另一个结点所经过的“边”的数量,被我们称为两个结点之间的路径长度。 仍然用刚才的二叉树举例子,从根结点A到叶子结点H,共经过了3条边,因此路径长度是3 概念3:什么是 结点的带权路径长度? 树的每一个结点,都可以拥有自己的“权重”(Weight),权重在不同的算法当中可以起到不同的作用。 结点的带权路径长度,是指树的根结点到该结点的路径长度,和该结点权重的乘积。 假设结点H的权重是3,从根结点到结点H的路径长度也是3,因此结点H的带权路径长度是 .... 树(6)哈夫曼树 java
在AVL树中,任一节点对应的两棵子树的最大高度差为1,因此它也被称为高度平衡树 例如图 2.1 不是平衡二叉树,因为结点 60 的左子树不是平衡二叉树。 图 2.2 也不是平衡二叉树,因为虽然任何一个结点的左子树与右子树都是平衡二叉树,但高度之差已经超过 1 。 平衡因子 定义: 某节点的左子树与右子树的高度(深度)差即为该节点的平衡因子(BF,Balance Factor),平衡二叉树中不存在平衡因子大于 1 的节点。在一棵平衡二叉树中,节点的平衡因子只能取 0 、1 或者 -1 ,分别对应着左右子树等高,左子树比较高,右子树比较高。 AVL树的四种插入节点方式 A的左孩子的左子树插入节点 A的右孩子的右子树插入节点 A的左孩子的右子树插入节点 若 A 的左孩子节点 B 的右子树 E 插入节点 F ,导致节点 A 失衡,如2.3图: 先左旋再右旋 A的右孩子的左子树插入节点 如图2.4所示 先右旋再左旋 AVL树的四种删除节点方式 跟二叉搜索树的删除方式一样,也分为四种情况 (1)删除叶子节点 (2)删除的节点只有左子树 (3)删除的节点只有右子树 (4)删除的节点既有左子树又有右..... 树(4)平衡二叉树AVL java
二叉搜索树是一种节点值之间具有一定数量级次序的二叉树,对于树中每个节点: 若其左子树存在,则其左子树中每个节点的值都不大于该节点值; 若其右子树存在,则其右子树中每个节点的值都不小于该节点值。 例如:图2.2.1所示的二叉树为一棵二叉搜索树。 例如:图2.2.2所示不是一棵二叉搜索树,因为节点40的左孩子节点值为44,不满足二叉搜索树的定义。 插入 (1)先检测该元素是否在树中已经存在。如果已经存在,则不进行插入; (2)若元素不存在,则进行查找过程,并将元素插入在查找结束的位置。 删除 如果是一个叶子节点直接删除即可,下面是三种不为叶子节点时的删除情况 1、待删除结点的左子树为空 2、待删除结点的右子树为空 3、待删除结点的左右子树均不为空 查找 若树为空树,则查找失败,返回nullptr。 若key值小于当前结点的值,则应该在该结点的左子树当中进行查找。 若key值大于当前结点的值,则应该在该结点的右子树当中进行查找。 若key值等于当前结点的值,则查找成功,返回对应结点的地址。 树(3)二叉搜索树 java
定义 二叉树是n(n>=0)个节点的有限集合,该集合或者为空集(称为空二叉树),或者由一个根节点和两棵互不相交的、分别称为根节点的左子树和右子树组成。 二叉树特点 由二叉树的定义,以及图中所示的二叉树的分析可以得出二叉树具有以下几个特点: (1)每个节点最多有两颗子树,所以二叉树中不存在度大于2的节点。 (2)左子树和右子树是有顺序的,次序不能任意颠倒。 (3)即使树中某节点只有一棵子树,也要区分它是左子树还是右子树。 斜树 所有的节点都只有左子树的二叉树叫左斜树。所有节点都是只有右子树的二叉树叫右斜树,这两者统称为斜树。 满二叉树 在一棵二叉树中。如果所有分支节点都存在左子树和右子树,并且所有叶子都在同一层上,这样的二叉树称为满二叉树。 完全二叉树 一棵深度为k的有n个结点的二叉树,对树中的结点按从上至下、从左到右的顺序进行编号,如果编号为i(1≤i≤n)的结点与满二叉树中编号为i的结点在二叉树中的位置相同,则这棵二叉树称为完全二叉树。 二叉树的存储结构 (1)顺序存储 二叉树的顺序存储结构就是使用一维数组存储二叉树中的节点,并且节点的存储位置,就是数组的下标索引。 可以看.... 树(2)基础二叉树 java
前言 树是数据结构中的重中之重,本系列文章将着重介绍二叉树、二叉搜索树、AVL树、红黑树、哈夫曼树、B树、B+树、树与森林。争取学完之后做到心中有"树"。 树的定义 树(Tree) 是n(n>=0)个结点的有限集。n=0时称为空树。 在任意一颗非空树中: 1)有且仅有一个特定的称为根(Root)的结点; 2)当n>1时,其余结点可分为m(m>0)个互不相交的有限集T1、T2、......、Tn,其中每一个集合本身又是一棵树,并且称为根的子树。 此外,树的定义还需要强调以下两点: 1)n>0时根结点是唯一的,不可能存在多个根结点,数据结构中的树只能有一个根结点。 2)m>0时,子树的个数没有限制,但它们一定是互不相交的。 一颗普通的树: 由树的定义可以看出,树的定义使用了递归的方式。递归在树的学习过程中起着重要作用,如果对于递归不是十分了解,建议先看看递归算法 结点的度 结点拥有的子树数目称为结点的 度 。 结点关系 结点子树的根结点为该结点的 孩子结点 。相应该结点称为孩子结点的 双亲结点 。 如上图中,A为B的双亲节点,B为A的孩子节点。 同一个双亲结点.... 树(1)什么是树 java
为什么要用ConcurrentHashMap? HashMap -> 非线程安全的 HashTable -> synchronized(偏向锁、轻量级锁(CAS)),锁的粒度太粗 ConcurrentHashMap -> 锁的粒度细,而且有很多优化操作在里面,比如它的并发扩容、高低位迁移、红黑树、链表等等。 ConcurrentHashMap的使用 jdk1.8的map引入了新的几个方法: computeIfAbsent computeIfPresent compute(computeIfAbsent和computeIfPresent两者的结合) merge(可用于计数) ConcurrentHashMap的存储结构 链表用来解决hash冲突问题,红黑树用来解决链表过长的问题。 put方法源码分析 final V putVal(K key, V value, boolean onlyIfAbsent) { if (key == null || value == null) throw new NullPointerException(); //计算哈希值 int h..... 面试官:讲讲你对ConcurrentHashMap的理解 java
相信每个人都写过这样的的mybatis的sql代码: SELECT * FROM user WHERE NAME LIKE concat('%', concat( '小', '%' )) 查询结果如下: 那么如果将'小'换成%呢? 再换成''呢? 没错,它会查询出所有数据,说来惭愧,这也是我一个5年java开发程序员才注意到的事情!!!GOD 问题出现了就要解决它,有大佬推荐说mysql可以使用ngram进行分词,我不知道是啥也没用过,而且我用的数据库是oracle 不过我找到了另外一种既可以在oracle用的也可以在mysql用的解决办法: 首先我们在代码中进行字符串替换: String name = user.getUserName(); if(null!=name && !"".equals(name)){ user.setName(name.replaceAll("\%","\\%").replaceAll("\","\\_")); } 然后修改查询sql: 为什么图中用的@?因为mysql用\会报错,只能用两个斜杠\ \ ,但是在oracle中.... 模糊查询输入%和_会查询全部的问题 java
Java常见线上问题总结 绝⼤多数Java线上问题从表象来看通常可以归纳为4个方面:CPU、内存、磁盘、网络。比如,应用上线 后突然CPU使用率99%、内存泄漏、STW时间过长,这些问题通常可以分为两大类: 系统异常 (CPU占用率过高、磁盘使用率100%、系统可用内存低等) 业务异常 (服务运⾏⼀段时间⾃动退出、服务间调⽤时间过⻓、多线程并发异常、死锁等) 1.如何去定位问题 解决问题的第⼀步是定位问题,排查手段⼀般包括以下⼏项,也可以将此理解为排查顺序: 业务⽇志分析排查 APM分析排查 物理环境排查 应⽤服务排查 云⼚商或运营商问题排查 1.1 业务⽇志分析排查 这个没啥说的,看日志不会吗? 1.2 APM分析排查 APM,全称Application Performance Management,应⽤性能管理 在分布式系统中,需要用到APM进行全链路分析 ⽬前市场上使⽤较多的链路跟踪⼯具有如下⼏个: Apache Skywalking:https://skywalking.apache.org Pinpoint:https://pinpoint.com/product/for-e.... java线上故障排查方案 java
在Linux操作系统中,所有被操作系统管理的资源,例如网络接口卡、磁盘驱动器、打印机、输入输出设备、普通文件或是目录都被看作是一个文件。也就是说在LINUX系统中有一个重要的概念:一切都是文件。其实这是UNIX哲学的一个体现,而Linux是重写UNIX而来,所以这个概念也就传承了下来。在UNIX系统中,把一切资源都看作是文件,包括硬件设备。UNIX系统把每个硬件都看成是一个文件,通常称为设备文件,这样用户就可以用读写文件的方式实现对硬件的访问。 Linux目录树 所有可操作的计算机资源都存在于目录树这个结构中,对计算资源的访问,可以看做是对这棵目录树的访问 Linux文件系统的结构层次鲜明,就像一棵倒立的树,最顶层是其根目录: 常见目录说明: /bin: 存放二进制可执行文件(ls、cat、mkdir等),常用命令一般都在这里; /etc: 存放系统管理和配置文件; /home: 存放所有用户文件的根目录,是用户主目录的基点,比如用户user的主目录就是/home/user,可以用~user表示; /usr : 用于存放系统应用程序; /opt: 额外安装的可选应用程序包所放置的位置。.... 面试官:用过Linux吗? Linux
SpringMVC执行流程: 用户点击某个请求路径,发起一个 HTTP request 请求,该请求会被提交到 DispatcherServlet(前端控制器); 由 DispatcherServlet 请求一个或多个 HandlerMapping(处理器映射器),并返回一个执行链(HandlerExecutionChain)。 DispatcherServlet 将执行链返回的 Handler 信息发送给 HandlerAdapter(处理器适配器); HandlerAdapter 根据 Handler 信息找到并执行相应的 Handler(常称为 Controller); Handler 执行完毕后会返回给 HandlerAdapter 一个 ModelAndView 对象(Spring MVC的底层对象,包括 Model 数据模型和 View 视图信息); HandlerAdapter 接收到 ModelAndView 对象后,将其返回给 DispatcherServlet ; DispatcherServlet 接收到 ModelAndView 对象后,会请求 ViewReso.... SpringMVC执行流程和源码分析 java
什么是事务? 在数据库开发中,一组业务逻辑操作,要么全部成功,要么全部失败。 事务有什么特点?ACID 原子性 atomicity:整体,原子不可分割的。整个操作被看成一个整体,要么成功,要么失败。 一致性 consistency:数据,事务操作的前后数据一致,参考AB转账钱的多少一致性。 隔离性 isolation:并发,两个事务之间并发访问情况下互相的隔离程度。 持久性 durability:结果,这个事物只要提交了,哪怕提交后宕机,他也确确实实的提交了。 传播属性 Propagation: NEVER 以非事务方式执行,如果当前存在事务,则抛出异常。 NOT_SUPPORTED 以非事务方式执行,如果当前存在事务,就把当前事务挂起。 SUPPORTS 支持当前事务,如果当前没有事务,就以非事务方式执行。 REQUIRES_NEW 新建事务,如果当前存在事务,把当前事务挂起。 REQUIRED(默认属性) 如果当前存在事务,则支持当前事务。如果没有事务则开启一个新的事务。 MANDATORY 支持当前事务,如果当前没有事务,就抛出异常。 NESTED 支持当前事务,新增Savepo.... Spring事务传播属性和隔离级别 spring
AQS全称是AbstractQueuedSynchronizer,形如其名,抽象队列同步器。 AQS定义了两种资源共享模式: 独占式,每次只能有一个线程持有锁,例如ReentrantLock实现的就是独占式的锁资源。 共享式,允许多个线程同时获取锁,并发访问共享资源,ReentrantWriteLock和CountDownLatch等就是实现的这种模式。 它维护了一个volatile修饰的state变量和一个FIFO(先进先出)的队列。 其中state变量代表的是竞争资源标识,而队列代表的是竞争资源失败的线程排队时存放的容器。 AQS中提供了操作state的方法: getState(); setState(); compareSetState(); protected final int getState() { return state; } protected final void setState(int newState) { state = newState; } protected final boolean compareAndSetState(int expect, i.... 你怎么理解AQS? java
回收算法 标记-清除算法 该算法分为“标记”和“清除”阶段:首先比较出所有需要回收的对象,在标记完成后统一回收掉所有被标 记的对象。它是最基础的收集算法,后续的算法都是对其不足进行改进得到。这种垃圾收集算法会带来 两个明显的问题: 效率问题 空间问题(标记清除后会产生大量不连续的碎片) 复制算法 为了解决效率问题,“复制”收集算法出现了。它可以将内存分为大小相同的两块,每次使用其中的一 块。当这一块的内存使用完后,就将还存活的对象复制到另一块去,然后再把使用的空间一次清理掉。 这样就使每次的内存回收都是对内存区间的一半进行回收。 标记-整理算法 根据老年代的特点提出的一种标记算法,标记过程仍然与“标记-清除”算法一样,但后续步骤不是直接对 可回收对象回收,而是让所有存活的对象向一端移动,然后直接清理掉端边界以外的内存。 分代收集算法 当前虚拟机的垃圾收集都采用分代收集算法,这种算法没有什么新的思想,只是根据对象存活周期的不 同将内存分为几块。一般将 java 堆分为新生代和老年代,这样我们就可以根据各个年代的特点选择合 适的垃圾收集算法。 比如在新生代中,每次收集都会有大量对象死去,所.... 垃圾回收算法及收集器 java