mybatis面试常见问题

版权声明:转载请注明出处https://blog.csdn.net/tomhavenocat https://blog.csdn.net/TomHaveNoCat/article/details/82958796

MyBatis
FAQ

  1. MyBatis 基础 1-1
    1.1. MyBatis 是什么? 1-1
    1.2. MyBatis 应用场景? 1-1
    1.3. MyBatis 核心对象有哪些? 1-1
    1.4. MyBatis编程步骤是什么样的? 1-2
    1.5. MyBatis 映射文件元素解析时对应哪些对象? 1-2
  2. MyBatis 进阶 2-2
    2.1. #{}和${}的区别是什么? 2-2
    2.2. MyBatis 中TypeHandler有什么作用以及应用场景? 2-2
    2.3. MyBatis 中TypeHandler如何编写以及配置? 2-3
    2.4. MyBatis 动态SQL如何理解及常用元素? 2-4
    2.5. 简述Mybatis的插件运行原理,以及如何编写一个插件? 2-4
    2.6. Mybatis是否支持延迟加载?如果支持,它的实现原理是什么? 2-4
    2.7. Mybatis都有哪些Executor执行器?它们之间的区别是什么? 2-5
    2.8. MyBatis 日志处理应如何配置? 2-5
    2.9. MyBatis 缓存设计及配置? 2-5

1.MyBatis 基础
1.1.MyBatis 是什么?
是一个优秀的数据持久层框架,主要负责数据的持久化以及映射操作。

1.2.MyBatis 应用场景?
MyBatis底层封装了JDBC中的一些通用性操作,主要用于在JAVA的生态系统中简化JDBC的数据持久化以及ORM操作。
1.3.MyBatis 核心对象及组件有哪些?
API:
SqlSessionFactoryBuilder
SqlSessionFactory
SqlSession

Xml
1)配置
2)映射文件
1.4.MyBatis编程步骤是什么样的?

① 创建SqlSessionFactory
② 通过SqlSessionFactory创建SqlSession
③ 通过sqlsession执行数据库操作
④ 调用session.commit()提交事务
⑤ 调用session.close()关闭会话

1.5.MyBatis 映射文件元素解析时对应哪些对象?
1)每一个、、、标签均会被解析为MappedStatement对象,标签内的sql会被解析为BoundSql对象。
2)标签会被解析为ResultMap对象,其每个子元素会被解析为ResultMapping对象

2.MyBatis 进阶

2.1.#{}和${}的区别是什么?

#{}是预编译处理,KaTeX parse error: Expected 'EOF', got '#' at position 21: …串替换。 Mybatis在处理#̲{}时,会将sql中的#{}替…{}时,就是把${}替换成变量的值。
使用#{}可以有效的防止SQL注入,提高系统安全性。

2.2.MyBatis 中TypeHandler有什么作用以及应用场景?
TypeHandler主要有两个作用,一是完成从javaType至jdbcType的转换,二是完成jdbcType至javaType的转换,具体体现为setParameter()和getResult()两个方法,分别代表设置sql问号占位符参数和获取列查询结果。

typeHandler专门用来解决数据库中的数据类型和Java中的数据类型之间的转化问题, 事实上,mybatis本身已经为我们提供了许多typeHandler了,系统提供的typeHandler能够满足我们日常开发中的大部分需求,但是现在要将list集合中的的数据以指定格式写入到数据库(例如{xxx,xxx,xxx}),或从数据库读取的这样的数据到list集合。

2.3.MyBatis 中TypeHandler如何编写以及配置?

自定义typeHandler我们有两种方式,一种是实现TypeHandler接口,还有一种简化的写法就是继承自BaseTypeHandler类,了解如下类基本配置

@MappedJdbcTypes({JdbcType.VARCHAR})
@MappedTypes({Date.class})
class MyDateTypeHandler extends BaseTypeHandler {
public void setNonNullParameter(PreparedStatement preparedStatement, int i, Date date, JdbcType jdbcType) throws SQLException {
preparedStatement.setString(i, String.valueOf(date.getTime()));
}

public Date getNullableResult(ResultSet resultSet, String s) throws SQLException {
    return new Date(resultSet.getLong(s));
}

public Date getNullableResult(ResultSet resultSet, int i) throws SQLException {
    return new Date(resultSet.getLong(i));
}

public Date getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
    return callableStatement.getDate(i);
}

}

在Mapper中进行配置

INSERT INTO user4(username,password,regTime) VALUES (#{username},#{password},#{regTime,javaType=Date,jdbcType=VARCHAR,typeHandler=org.sang.db.MyDateTypeHandler})

2.4.MyBatis 动态SQL如何理解及常用元素?

Mybatis动态sql可以让我们在Xml映射文件内,以标签的形式编写动态sql,完成逻辑判断和动态拼接sql的功能,Mybatis提供了9种动态sql标签
trim|where|set|foreach|if|choose|when|otherwise|bind。

2.5.简述Mybatis的插件运行原理,以及如何编写一个插件?
Mybatis仅可以编写针对ParameterHandler、ResultSetHandler、StatementHandler、Executor这4种接口的插件,Mybatis使用JDK的动态代理,为需要拦截的接口生成代理对象以实现接口方法拦截功能,每当执行这4种接口对象的方法时,就会进入拦截方法,具体就是InvocationHandler的invoke()方法,当然,只会拦截那些你指定需要拦截的方法。

实现Mybatis的Interceptor接口并复写intercept()方法,然后在给插件编写注解,指定要拦截哪一个接口的哪些方法即可,记住,别忘了在配置文件中配置你编写的插件。

2.6.Mybatis是否支持延迟加载?如果支持,它的实现原理是什么?
Mybatis仅支持association关联对象和collection关联集合对象的延迟加载,association指的就是一对一,collection指的就是一对多查询。在Mybatis配置文件中,可以配置是否启用延迟加载lazyLoadingEnabled=true|false。
它的原理是,使用CGLIB创建目标对象的代理对象,当调用目标方法时,延迟加载关联对象。

2.7.Mybatis都有哪些Executor执行器?它们之间的区别是什么?

Mybatis有三种基本的Executor执行器,SimpleExecutor、ReuseExecutor、BatchExecutor。

SimpleExecutor:每执行一次update或select,就开启一个Statement对象,用完立刻关闭Statement对象。

ReuseExecutor:执行update或select,以sql作为key查找Statement对象,存在就使用,不存在就创建,用完后,不关闭Statement对象,而是放置于Map<String, Statement>内,供下一次使用。简言之,就是重复使用Statement对象。

BatchExecutor:执行update(没有select,JDBC批处理不支持select),将所有sql都添加到批处理中(addBatch()),等待统一执行(executeBatch()),它缓存了多个Statement对象,每个Statement对象都是addBatch()完毕后,等待逐一执行executeBatch()批处理。与JDBC批处理相同。

作用范围:Executor的这些特点,都严格限制在SqlSession生命周期范围内。

2.8.MyBatis 日志处理应如何配置?
???????
Log4j.propertes
Log4j2.xml
2.9.MyBatis 缓存设计及配置?
MyBatis 一级缓存概述及总结:
MyBatis一级缓存的生命周期和SqlSession一致。
MyBatis一级缓存内部设计简单,只是一个没有容量限定的HashMap,在缓存的功能性上有所欠缺。
MyBatis的一级缓存最大范围是SqlSession内部,有多个SqlSession或者分布式的环境下,数据库写操作会引起脏数据,建议设定缓存级别为Statement。

MyBatis 二级缓存及概述?
如果多个SqlSession之间需要共享缓存,则需要使用到二级缓存。开启二级缓存后,会使用CachingExecutor装饰Executor,进入一级缓存的查询流程前,先在CachingExecutor进行二级缓存的查询。二级缓存开启后,同一个namespace下的所有操作语句,都影响着同一个Cache,即二级缓存被多个SqlSession共享,是一个全局的变量。

当开启缓存后,数据的查询执行的流程就是 二级缓存 -> 一级缓存 -> 数据库。

MyBatis的二级缓存相对于一级缓存来说,实现了SqlSession之间缓存数据的共享,同时粒度更加的细,能够到namespace级别,通过Cache接口实现类不同的组合,对Cache的可控性也更强。
MyBatis在多表查询时,极大可能会出现脏数据,有设计上的缺陷,安全使用二级缓存的条件比较苛刻。
在分布式环境下,由于默认的MyBatis Cache实现都是基于本地的,分布式环境下必然会出现读取到脏数据,需要使用集中式缓存将MyBatis的Cache接口实现,有一定的开发成本,直接使用Redis,Memcached等分布式缓存可能成本更低,安全性也更高。

猜你喜欢

转载自blog.csdn.net/TomHaveNoCat/article/details/82958796