MyBatis面试题整理

MyBatis面试题整理

MyBatis简介

Mybatis是一个半ORM框架,封装了JDBC,开发时只要关注SQL语句本身,不需要处理加载驱动,创建连接,床架statement等过程,直接编写原生态sql语句,可以严格控制sql执行性能、灵活度高。

Mybatis可以使用XML和注解来配置和映射原生信息,将POJO映射成数据库中的记录,避免了所有的JDBC代码和手动设置参数以及获取结果集。

通过xml文件或注解的方式将要执行的各种statement配置起来,并通过Java对象和statement中的sql的动态参数进行映射生成最终执行的sql语句,最后由Mybatis框架执行sql并将结果映射成Java对象并返回。

MyBatis的功能架构

Mybatis的功能架构分为三层:
API接口层:提供给外部使用的接口API,开发人员通过这些本地API来操纵数据库。接口层一接收到调用请求就会调用数据处理层来完成具体的数据处理。
数据处理层:负责具体的SQL查找、SQL解析、SQL执行和执行结果映射处理等。它主要的目的是根据调用的请求完成一次数据库操作。
基础支撑层:负责最基础的功能支撑,包括连接管理、事务管理、配置加载和缓存处理,这些都是共用的东西,将他们抽取出来作为最基础的组件。为上层的数据处理层提供最基础的支撑。

MyBatis的优缺点

优点:
(1)基 于 SQL 语句编程,相当灵活,不会对应用程序或者数据库的现有设计造成任何影响,SQL 写在 XML 里,解除 sql 与程序代码的耦合,便于统一管理;提供 XML标签,支持编写动态 SQL 语句,并可重用。

(2)与 JDBC 相比,减少了 50%以上的代码量,消除了 JDBC 大量冗余的代码,不需要手动开关连接;

(3)很好的与各种数据库兼容(因为 MyBatis 使用 JDBC 来连接数据库,所以只要JDBC 支持的数据库 MyBatis 都支持)。

(4)能够与 Spring 很好的集成;

(5)提供映射标签,支持对象与数据库的 ORM 字段关系映射;提供对象关系映射标签,支持对象关系组件维护。

缺点:

(1)SQL 语句的编写工作量较大,尤其当字段多、关联表多时,对开发人员编写SQL 语句的功底有一定要求。

(2)SQL 语句依赖于数据库,导致数据库移植性差,不能随意更换数据库。

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

#{}预编译处理${}字符串替换

Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值;
Mybatis在处理${}时,就是把${}替换成变量的值
使用#{}可以有效的防止SQL注入,提高系统安全性。

Xml映射文件中,除了常见的select|insert|updae|delete标签之外,还有哪些标签?

还有很多其他的标签:<resultMap>、<parameterMap>、<sql>、<include>、<selectKey>
加上动态sql的9个标签:trim|where|set|foreach|if|choose|when|otherwise|bind等,其中<sql>为sql片段标签,通过<include>标签引入sql片段,<selectKey>不支持自增的主键生成策略标签。

Mybatis是如何将sql执行结果封装为目标对象并返回的?都有哪些映射形式?

第一种是使用<resultMap>标签,逐一定义列名对象属性名之间的映射关系。

第二种是使用sql列的别名功能,将列别名书写为对象属性名,比如T_NAME AS NAME,对象属性名一般是name,小写,但是列名不区分大小写,Mybatis会忽略列名大小写,智能找到与之对应对象属性名,你甚至可以写成T_NAME AS NaMe,Mybatis一样可以正常工作。

有了列名与属性名的映射关系后,Mybatis通过反射创建对象,同时使用反射给对象的属性逐一赋值并返回,那些找不到映射关系的属性,是无法完成赋值的。

Mybatis的Xml映射文件中,不同的Xml映射文件,id是否可以重复?

不同的Xml映射文件:
如果配置了namespace,那么id可以重复
如果没有配置namespace,那么id不能重复
原因就是namespace+id是作为Map<String, MappedStatement>key使用的,如果没有namespace,就剩下id,那么,id重复会导致数据互相覆盖。有了namespace,自然id就可以重复,namespace不同,namespace+id自然也就不同。

MyBatis的缓存

MyBatis的缓存分为一级缓存二级缓存
一级缓存放在session里面,默认就有,二级缓存放在它的命名空间里,默认是打开的,
使用二级缓存属性类需要实现Serializable序列化接口(可用来保存对象的状态),可在它的映射文件中配置<cache/>

简单的说一下MyBatis的一级缓存和二级缓存

Mybatis首先去缓存中查询结果集,如果没有则查询数据库,如果有则从缓存取出返回结果集就不走数据库。Mybatis内部存储缓存使用一个HashMap,key为hashCode+sqlId+Sql语句。value为从查询出来映射生成的java对象

Mybatis的二级缓存即查询缓存,它的作用域是一个mapper的namespace,即在同一个namespace中查询sql可以从缓存中获取数据。二级缓存是可以跨SqlSession的。

Mybatis全局配置文件中有哪些标签?分别代表什么意思?

configuration 配置
properties 属性:可以加载properties配置文件的信息
settings 设置:可以设置mybatis的全局属性
typeAliases 类型命名
typeHandlers 类型处理器
objectFactory 对象工厂
plugins 插件
environments 环境
environment 环境变量
transactionManager 事务管理器
dataSource 数据源
mappers 映射器

一对一关联查询使用什么标签?一对多关联查询使用什么标签?

MyBatis中使用collection*标签来解决一对多的关联查询,collection标签可用的属性如下:
property:指的是集合属性的值.
ofType:指的是集合中元素的类型.
column:所对应的外键字段名称.
select:使用另一个查询封装的结果.

MyBatis中使用association标签来解决一对一的关联查询,association标签可用的属性如下:
property:对象属性的名称.
javaType:对象属性的类型.
column:所对应的外键字段名称.
select:使用另一个查询封装的结果!

Mybatis 动态 sql 有什么用?执行原理?有哪些动态 sql?

Mybatis 动态 sql 可以在 Xml 映射文件内,以标签的形式编写动态 sql,执行原理是根据表达式的值 完成逻辑判断并动态拼接 sql 的功能

Mybatis 提供了 9 种动态 sql 标签:trim | where | set | foreach | if | choose| when | otherwise | bind

MyBatis配置实体包的别名

// 配置实体包的别名
 <typeAliases>       
 <package name="com.swjd.bean"/>   
 </typeAliases> 

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

Mybatis有三种基本的Executor执行器:SimpleExecutorReuseExecutorBatchExecutor

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生命周期范围内

当实体类中的属性名和表中的字段名不一样 ,怎么办 ?

第1种: 通过在查询的sql语句中定义字段名的别名,让字段名的别名和实体类的属性名一致。

 <select id=”selectorder” parametertype=int” resultetype=”me.gacl.domain.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=”me.gacl.domain.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>

模糊查询like语句该怎么写?

第1种:在Java代码中添加sql通配符。

 string mhname=%li%;   
 list<name> names = mapper.selectlike(mhname);   
 <select id=”selectlike”>    
 	select * from foo where name like #{value}   
 </select>

第2种:在sql语句中拼接通配符,会引起sql注入

string mhname= “li”;    
list<name> names = mapper.selectlike(mhname);     
<select id=”selectlike”>         
	select * from foo where name like "%"${value}"%"   
</select>

为什么说Mybatis是半自动ORM映射工具?它与全自动的区别在哪里?

Hibernate属于全自动ORM映射工具,使用Hibernate查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以它是全自动的。而Mybatis在查询关联对象或关联集合对象时,需要手动编写sql来完成,所以,称之为半自动ORM映射工具

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

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

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

在Mybatis中,每一个<select>、<insert>、<update>、<delete>标签,都会被解析为一个MappedStatement对象。

Dao接口里的方法,是不能重载的,因为是全限名+方法名的保存和寻找策略。

如何执行批量插入?

首先,创建一个简单的insert语句:

<insert id=”insertname”>
	insert into names (name) values (#{value})
</insert>

然后在java代码中像下面这样执行批处理插入:

list<string> names = new arraylist();    
	names.add(“fred”);    
	names.add(“barney”);    
	names.add(“betty”);    
	names.add(“wilma”);     
// 注意这里 executortype.batch    
	sqlsession sqlsession=sqlsessionfactory.opensession(executortype.batch);    
	try {     
		namemapper mapper = sqlsession.getmapper(namemapper.class);     
		for (string name : names) {         
		mapper.insertname(name);     
	}     
		sqlsession.commit();    
	}catch(Exception e){     
		e.printStackTrace();     
		sqlSession.rollback();      
		throw e;     
	}finally {         
	sqlsession.close();    
}

如何获取自动生成的(主)键值?

insert 方法总是返回一个int值 ,这个值代表的是插入的行数。
如果采用自增长策略,自动生成的键值在 insert 方法执行完后可以被设置到传入的参数对象中。
示例:

Mybatis 常见选择题

<insert id=”insertname” usegeneratedkeys=true” keyproperty=”id”>
	insert into names (name) values (#{name})
</insert>
  name name = new name();    
  name.setname(“fred”);     
  int rows = mapper.insertname(name);    
  // 完成后,id已经被设置到对象中    
  system.out.println(“rows inserted =+ rows);
  system.out.println(“generated key value =+ name.getid());

MyBatis实现一对一有几种方式?具体怎么操作的?

有联合查询和嵌套查询,联合查询是几个表联合查询,只查询一次, 通过在resultMap里面配置association节点配置一对一的类就可以完成;

嵌套查询是先查一个表,根据这个表里面的结果的 外键id,去再另外一个表里面查询数据,也是通过association配置,但另外一个表的查询通过select属性配置。

21、MyBatis实现一对多有几种方式,怎么操作的?

有联合查询和嵌套查询。
联合查询是几个表联合查询,只查询一次,通过在resultMap里面的collection节点配置一对多的类就可以完成;
嵌套查询是先查一个表,根据这个表里面的 结果的外键id,去再另外一个表里面查询数据,也是通过配置collection,但另外一个表的查询通过select节点配置。

简述Mybatis的插件运行原理,以及如何编写一个插件。

Mybatis仅可以编写针对ParameterHandlerResultSetHandlerStatementHandlerExecutor这4种接口的插件,Mybatis使用JDK的动态代理,为需要拦截的接口生成代理对象以实现接口方法拦截功能,每当执行这4种接口对象的方法时,就会进入拦截方法,具体就是InvocationHandler的invoke()方法,当然,只会拦截那些你指定需要拦截的方法。

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

Mybatis常见选择题

1. 对mybatis描述有误的是? (C、D)

A. MyBatis 是一个可以自定义 SQL、存储过程和高级映射的持久层框架

B. MyBatis 的缓存分为一级缓存和二级缓存,一级缓存放在 session 里面

C.Mybatis是一个全ORM(对象关系映射)框架,它内部封装了JDBC

D. MyBatis 只可以使用 XML来配置和映射原生信息

2. 多选题 Mybatis是如何将sql执行结果封装为目标对象并返回的 (B、C)

A. id
B. <resultMap>标签
C. 使用sql列的别名
D. resultType

3.多选题 mybaties中模糊查询like语句的写法 (A、D)

A. select * from foo where bar like #{value}

B. select * from foo where bar like #{%value%}

C. select * from foo where bar like %#{value}%

D. select * from foo where bar like “%”${value}"%"

4.多选题 Mybatis的Xml映射文件中,不同的Xml映射文件,id是否可以重复? 选择说法正确的 (A、B)

A. 不同的Xml映射文件,如果配置了namespace,那么id可以重复

B. 如果没有配置namespace,那么id不能重复

C. 如果没有配置namespace,id能重复

D. 不同的Xml映射文件,如果配置了namespace,那么id不可以重复

5.多选题 Mybatis的mapper接口调用时候的要求正确的是: (A、B、 C)

A. Mapper接口方法名和Mapper.xml中定义的每个SQL的id相同;

B. Mapper接口方法的输入参数类型和mapper.xml中定义的每个sqlparameterType类型 相同

C. Mapper接口方法的输入输出参数类型和mapper.xml中定义的每个sql的resultType的 类型相同

D. Mapper.xml文件中的namespace,就是接口的名字

6. 多选题 MyBatis内置类型别名有 (A、C)

A. _int
B. Integer
C. int
D. String

7. 多选题 Mybatis动态sql标签有哪些? (A、B、C)

A. trim
B. foreach
C. set
D. than

8. 多选题 Mybaits的优点正确的是? (A、 B、C)

A. 基于SQL语句编程,相当灵活,不会对应用程序或者数据库的现有设计造成任何影 响,SQL写在XML里,解除sql与程序代码的耦合,便于统一管理

B. 与JDBC相比,减少了50%以上的代码量,消除了JDBC大量冗余的代码,不需要手 动开关连接

C. 很好的与各种数据库兼容

D. 它是一全个ORM框架,MyBatis不需要程序员自己编写Sql语句。

9.多选题 实体类中的属性名和表中的字段名不一样怎么处理? (A、C)

A. 查询的sql语句中定义字段名的别名

B. 不用处理

C. 通过来映射字段名和实体类属性名

D. 通过来映射字段名和实体类属性名

10.多选题 MyBatis有两种事务管理器,分别是(A)和(B)

A. JDBC
B. MANAGED
C. POOLED
D. JNOI

11. 单选题 在mybatis的配置文件中,通过( C. )标签来设置实体类的别名

A. properties
B. settings
C. typeAliases
D. dataSource

12. 单选题 下列( B.)不属于 MyBatis全局配置文件中的标签

A. settings
B. select
C. plugins
D. properties

13. 单选题 在Mybatis中,SQL映射文件中配置insert语句时,在SQL SERVER中插入语句所在的表的ID为自动增长列,下列关于insert标签的说法,正 确的是( D )

A. 必须要显示插入标识列中的值

B. 使用任何数据库都可以使用自动生成主键策略

C. useGeneratedKeys属性对update标签也有作用

D. 可以使用useGeneratedKeys属性允许标识列的自动增长用于生成主键

14. 单选题 在 MyBatis 中,操作数据库的核心类是 ( B)

A. SqlSessionFactory
B. SqlSession
C. Session
D. SqlSessionFactoryBuilder

15. 单选题 在使用MyBatis的时候,除了可以使用@Param注解来实现多参数入参,还可以用(A)传递多个 参数值。

A. 用Map对象可以实现传递多参数值

B. 用List对象可以实现传递多参数值

C. 用数组的方式传递

D. 用Set集合的方式传递

16. 单选题 在 MyBatis 中,配置结果映射时,使用( C )标签实现多对1的关联

A. many-one
B. one-many
C. association
D. collection

17. 单选题 MyBatis操作数据库时的接口方法中,如果传入的参数名和动态sql 中使用时不一致,则需要使用( D )注解修饰。

A. @RequestParam
B. @Parameter
C. @String
D. @Param

18. 单选题 在mybatis中,配置结果映射时,使用( D )标签实现一对多的关 联

A. many-one
B. one-many
C. association
D. collection

19. 单选题 MyBatis 中对复杂数据映射到一个结果集的配置使用的标签是( A)

A. <resultMap>
B. <result>
C. <map>
D. <collection>

20. 单选题 在 MyBatis 动态 SQL 中,循环使用的标签名是( C )

A. for
B. while
C. foreach
D. do-while

21. 单选题 看程序进行分析:

Public UserselectUser(String name,String area);
  
<select id="selectUser"resultMap="BaseResultMap">  
 select * fromuser_user_t whereuser_name=#{0} anduser_area=#{1}
</select> 

#{0} 表示哪一个参数? (B)

A. 程序报错
B. name
C. area
D. 0

22. 单选题 MyBatis对JDBC访问数据库的代码进行封装,从而大大简化了数 据访问层的重复性代 码,它是针对三层架构中( C )的解决方案

A. 表现层
B. 业务逻辑层
C. 持久化层
D. 数据库系统

23. 单选题 MyBatis生命周期说法错误的是 (D)

A. SqlSessionFactoryBuilder实例的佳作用域是方法范围,也就是定义为本地方法变 量既可

B. SqlSessionFactory实例的生命周期应该在整个应用的执行期间都存在

C. SqlSession实例时线程不安全的,因此其生命周期应该是请求或方法范围

D. SqlSession实例通常定义为一个类的静态变量

24. 单选题 以下不属于一对多的是? (A)

A. 帅哥和美女
B. 学生和班级
C. 投影和学生
D. 学校和班级

25. 单选题 在MyBatis中,在进行select查询映射时,下列关于返回类型的说 法,正确的是( C )

A. 只能是resultType
B. 只能是resultMap
C. 可以是resultType或resultMap
D. 以上说法都不正确

26. 单选题 配置实体包的别名,正确的写法是 (A)

A.

<typeAliases>       
<package name="com.swjd.bean"/>  
 </typeAliases>

B.

<typeAliases>       
<package name="com/swjd/bean"/>
</typeAliases>

C.

<typeAliase>       
<package name="com.swjd.bean"/>
</typeAliase>

D.

<package>       
<package name="com.swjd.bean"/>
</package>

27. 单选题 一辆汽车由多个零部件组成,且相同的零部件可适用于不同型号的 汽车,则汽车实体集与零部件实体集之间的联系是( D)

A. 1 : M
B. 1:1
C. M : 1
D. M : N

28. 单选题 编译Java程序的命令是 (D)

A. appletviewer
B. javac
C. java
D. javadoc

29. 单选题 在MyBatis数据库操作时,需要编写(A)和对应的Xml文件,其 中Xml文件中编写的是对应Sql语句

A. 接口和抽象方法
B. 普通类和普通方法
C. 抽象类和抽象方法
D. 普通类和抽象方法

30. 单选题 在 MyBatis 中,配置结果映射时,使用( D)标签实现1对多的关 联

A. many-one
B. one-many
C. association
D. collection

Mybatis常见填空题

  1. Mybatis的Xml映射文件中,不同的Xml映射文件,id是否可以重复? 不同的Xml映射文件,如果配置了namespace,那么id 可以重复 ;如果没有配置 namespace,那么id不能重复
  2. #{}${}的区别是什么?#{}预编译处理${}字符串替换
  3. MyBatis是一款优秀的支持自定义SQL查询、存储过程和高级映射的持久层框架,几乎封装所有的JDBC代码和参数的手动设置以及结果集的检索,通过XML或注解的方式进行配置映射实现数据库操作,大大提高开发效率。
  4. MyBatis中提供了一级缓存和二级缓存,其中一级缓存默认存在,不可控制,同一SqlSession范围内的操作共享该缓存,增、删、改后将清除缓存
  5. 模糊查询like语句怎么写?
    第一种,在Java代码中添加sql通配符
    第二种,在sql语句中添加拼接通配符会引起sql注入。
  6. 四个核心接口是:
    Executor用于执行CRUD操作、ParameterHandler用于处理SQL的参数、
    ResultSetHandler处理返回结果集、
    StatementHandler用于执行SQL语句。
发布了2 篇原创文章 · 获赞 2 · 访问量 179

猜你喜欢

转载自blog.csdn.net/weixin_45259144/article/details/105308131