lagou-java习题库

序言:

文章内容输出来源:拉勾教育Java高薪训练营。
本篇文章是学习课程中的一部分面试题集锦(持续更新中......)

一、请说说MyBatis的工作原理?

1)读取 MyBatis 配置文件:
  • mybatis-config.xml 为 MyBatis 的全局配置文件,配置了 MyBatis 的运行环境等信息,例如数据库连接信息。
2)加载映射文件:
  • 映射文件即 SQL 映射文件,该文件中配置了操作数据库的 SQL 语句,需要在 MyBatis 配置文件 mybatis-config.xml 中加载。
    mybatis-config.xml 文件可以加载多个映射文件,每个文件对应数据库中的一张表。
3)构造会话工厂:
  • 通过 MyBatis 的环境等配置信息构建会话工厂 SqlSessionFactory。
4)创建会话对象:
  • 由会话工厂创建 SqlSession 对象,该对象中包含了执行 SQL 语句的所有方法。
5)Executor 执行器:
  • MyBatis 底层定义了一个 Executor 接口来操作数据库,它将根据 SqlSession 传递的参数动态地生成需要执行的 SQL 语句,同时负责查询缓存的维护。
6)MappedStatement 对象:
  • 在 Executor 接口的执行方法中有一个 MappedStatement 类型的参数,该参数是对映射信息的封装,用于存储要映射的 SQL 语句的 id、参数等信息。
7)输入参数映射:
  • 输入参数类型可以是 Map、List 等集合类型,也可以是基本数据类型和 POJO 类型。
    输入参数映射过程类似于 JDBC 对 preparedStatement 对象设置参数的过程。
8)输出结果映射:
  • 输出结果类型可以是 Map、 List 等集合类型,也可以是基本数据类型和 POJO 类型。
    输出结果映射过程类似于 JDBC 对结果集的解析过程。

二、HashMap存储原理,有啥问题,如何避免?

一、存储原理:
  • 1、HashMap是一个键值对的集合,是非synchronized的,源码中每个节点用Node表示。
    Node是一个内部类,这里的key为键,value为值,next指向下一个元素,可以看出HashMap中的元素不是一个单纯的键值对,还包含下一个元素的引用。

  • 2、HashMap的数据结构:数组+(链表或红黑树),数组是HashMap的主体,链表则是主要为了解决哈希冲突而存在的。
    在HashMap底层使用数组加(链表或红黑树)的结构完美的解决了数组和链表的问题,使得查询和插入,删除的效率都很高。
    因为链表中元素太多的时候会影响查找效率,所以当 链表的元素个数达到8 的时候使用链表存储就转变成了使用红黑树存储,原因就是红黑树是平衡二叉树,在查找性能方面比链表要高。

  • 3、HashMap中有两个重要的参数:初始容量大小和加载因子,初始容量大小是创建时给数组分配的容量大小,默认值为16,用数组容量大小乘以加载因子得到一个值。
    一旦数组中存储的元素个数超过该值就会调用rehash方法将数组容量增加到原来的两倍,专业术语叫做扩容。
    在做扩容的时候会生成一个新的数组,原来的所有数据需要重新计算哈希码值重新分配到新的数组,所以扩容的操作非常消耗性能。

二、问题:
  • 当重新调整HashMap大小的时候,存在条件竞争,如果两个线程都发现HashMap需要重新调整大小了,它们会同时试着调整大小。
    在调整大小的过程中,存储在LinkedList中的元素的次序会反过来,因为移动到新的bucket位置的时候,HashMap并不会将元素放在LinkedList的尾部,而是放在头部,这是为了避免尾部遍历(tail traversing)。
    如果条件竞争发生了,那么就死循环了。
三、避免:
  • 1.java8的改进
    添加了红黑树,当链表长度大于8时,还需要判断当前数组的长度,如果数组长度 < 64 时,此时并不会转换为红黑树,而是扩容, 只有当链表 中的元素个数 > 8,并且数组的长度 >= 64 时才会将链表转为红黑树。
    扩容后,新数组中的链表顺序依然与旧数组中的链表顺序保持一致。
    具体JDK8是用 head 和 tail 来保证链表的顺序和之前一样,这样就不会产生循环引用,也就没有死循环了。
    虽然修复了死循环的BUG,但是HashMap 还是非线程安全类,仍然会产生数据丢失等问题。

  • 2.可以使用HashTable和调用Collections工具类的synchronizedMap()方法达到线程安全的目的。
    但由于synchronized是串行执行,在访问量很大的情况下效率很低,不推荐使用。

三、通常一个Xml映射文件,都会写一个Dao接口与之对应,请问,这个Dao接口的工作原理是什么?Dao接口里的方法,参数不同时,方法能重载吗?

1.简述:

Dao接口,就是人们常说的Mapper接口;
接口的全限名,就是映射文件中的namespace的值;
接口的方法名,就是映射文件中MappedStatement的id值;
接口方法内的参数,就是传递给sql的参数;
Mapper接口是没有实现类的,当调用接口方法时,接口全限名+方法名拼接字符串作为key值,可唯一定位一个MappedStatement。

2.举例:

com.mybatis3.mappers.StudentDao.findStudentById,可以唯一找到namespace为com.mybatis3.mappers.StudentDao下面id = findStudentById的MappedStatement。

3.工作原理:

在Mybatis中,每一个