原文
根据上面博客手敲了一些面试题,加强自己理解
1.mybaits是什么?
mybatis是一款优秀的持久层框架,一个半ORM(对象关系映射)框架。它支持定制化SQL、存储过程以及高级映射。mybatis
几乎避免了所有的jdbc代码和手动的配置参数以及获取结果集。mybatis可以使用简单的XML或者注解来配置和映射原生类型、接口、和Java的POJO(普通老式java对象)为数据库中的记录。
2.ORM是什么?
ORM(Object Relational Mapping) ,对象关系映射,是一种为了解决关系型数据库与POJO的映射关系的技术。及ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的对像自动持久化到关系型数据库中。
3.为什么说Mybatis是半自动ORM映射工具?它与全自动的区别在哪里?
Hibernate属于全自动ORM映射工具,使用Hibernate查询关联对象时,可以根据对象关系模型直接获取,所以是全自动的;
Mybatis在查询关联对象时,需要手动编写sql来完成,及为半ORM框架。
4.传统JDBC开发存在的问题
1.频繁的创建数据库连接对象、释放,容易造成系统资源的浪费,影响性能。
2.结果集处理存在重复代码,处理麻烦、
3.。。。
5.JDBC的不足之处,Mybatis时如何解决的
在mybaits-config.xml中配置数据连接池,使用连接池来管理数据库连接。
将SQL语句配置在XXXMapper.xml文件中与java代码分离。
Mybatis自动将Java对象映射至sql语句。
Mybatis自动将SQL执行结果映射至Java对象。
Mybatis的解析和运行原理。
6.Mybaits的编程步骤是怎样的?
1.创建SqlSessionFactory
2.通过SqlSessionFactory创建SqlSession
3.通过SqlSession执行数据库操作
4.调用session.commit()提交事务
5.调用session.close()关闭会话
7.说说Mybatis的工作原理。
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 对结果集的解析过程。
8.为什么需要预编译?
定义:SQL预编译是指数据库驱动在发送SQL语句和参数给DBMS之前堆SQL语句进行预编译,这样DBMS在执行SQL语句的时候,就不需要重新编译。
为什么要预编译?
JDBC 中使用对象 PreparedStatement 来抽象预编译语句,使用预编译。预编译阶段可以优化 SQL 的执行。预编译之后的 SQL 多数情况下可以直接执行,DBMS 不需要再次编译,越复杂的SQL,编译的复杂度将越大,预编译阶段可以合并多次操作为一个操作。同时预编译语句对象可以重复利用。把一个 SQL 预编译后产生的 PreparedStatement 对象缓存下来,下次对于同一个SQL,可以直接使用这个缓存的 PreparedState 对象。Mybatis默认情况下,将对所有的 SQL 进行预编译。
9.Mybatis都有哪些Executor执行器?他们之间的区别是什么?
Mybatis有三种基本的Executor执行器,SimpleExecutor、ReuseExecutor、BatchExecutor。
*SimpleExecutor:每执行一次update或select,就开启一个Statement对象,用完立刻关闭Statement对象。
*ReuseExecutor:执行update或select,以sql作为key查找Statement对象,存在就使用,不存在就创建,用完后,不关闭Statement对象,而是放置于Map
*BatchExecutor:执行update(没有select,JDBC批处理不支持select),将所有sql都添加到批处理中(addBatch()),等待统一执行(executeBatch()),它缓存了多个Statement对象,每个Statement对象都是addBatch()完毕后,等待逐一执行executeBatch()批处理。与JDBC批处理相同。
作用范围:Executor的这些特点,都严格限制在SqlSession生命周期范围内。
.映射器
10. #{}和${}的区别?
#{}是占位符,预编译处理;${}是拼接符,字符串替换,没有预编译处理。
Mybatis在处理#{}时,#{}传入参数是以字符串传入,会将SQL中的#{}替换为?号,调用PreparedStatement的set方法来赋值。
Mybatis在处理时,是原值传入,就是把时,是原值传入,就是把{}替换成变量的值,相当于JDBC中的Statement编译
变量替换后,#{} 对应的变量自动加上单引号 ‘’;变量替换后,${} 对应的变量不会加上单引号 ‘’
#{} 可以有效的防止SQL注入,提高系统安全性;${} 不能防止SQL 注入
#{} 的变量替换是在DBMS 中;${} 的变量替换是在 DBMS 外。
11.模糊查询like怎么写?
(1)’%${question}%’ 可能引起SQL注入,不推荐
(2)"%"#{question}"%" 注意:因为#{…}解析成sql语句时候,会在变量外侧自动加单引号’ ',所以这里 % 需要使用双引号" ",不能使用单引号 ’ ',不然会查不到任何结果。
(3)CONCAT(’%’,#{question},’%’) 使用CONCAT()函数,推荐
(4)使用bind标签
```java
12.mapper中如何传递多个参数?
1.使用@Param注解传参法。
public User selectUser(@Param("userName") String name, int @Param("deptId") deptId);
<select id="selectUser" resultMap="UserResultMap">
select * from user
where user_name = #{
userName} and dept_id = #{
deptId}
</select>
```#{
}里面的名称对应的是注解@Param括号里面修饰的名称
2.使用JavaBean传参法。
```java
public User selectUser(User user);
<select id="selectUser" parameterType="com.jourwon.pojo.User" resultMap="UserResultMap">
select * from user
where user_name = #{
userName} and dept_id = #{
deptId}
</select>
#{}里面的名称对应的是User类里面的成员属性。
13.当实体类中的属性和表中的字段名不一样,怎么办?
1.通过在查询的SQL语句中定义字段名的别名,让字段名的别名和实体类的属性名一致。
<select id="getOrder" parameterType="int" resultType="com.jourwon.pojo.Order">
select order_id id, order_no orderno ,order_price price form orders where order_id=#{
id};
</select>
2.使用来映射字段名和实体类属性名一一对应。
<select id="getOrder" parameterType="int" resultMap="orderResultMap">
select * from orders where order_id=#{
id}
</select>
<resultMap type="com.jourwon.pojo.Order" id="orderResultMap">
<!–用id属性来映射主键字段–>
<id property="id" column="order_id">
<!–用result属性来映射非主键字段,property为实体类属性名,column为数据库表中的属性–>
<result property ="orderno" column ="order_no"/>
<result property="price" column="order_price" />
</reslutMap>
14.Mybatis的一级缓存和二级缓存
1)一级缓存: 基于 PerpetualCache 的 HashMap 本地缓存,其存储作用域为 Session,当 Session flush 或 close 之后,该 Session 中的所有 Cache 就将清空,默认打开一级缓存。
2)二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap 存储,不同在于其存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache。默认不打开二级缓存,要开启二级缓存,使用二级缓存属性类需要实现Serializable序列化接口(可用来保存对象的状态),可在它的映射文件中配置 ;
3)对于缓存数据更新机制,当某一个作用域(一级缓存 Session/二级缓存Namespaces)的进行了C/U/D 操作后,默认该作用域下所有 select 中的缓存将被 clear。
更新中。。。