Mybatis(Java面试题)

1、Mybatis的一级缓存和二级缓存是如何实现的?

一级缓存是statement缓存

2、Mybatis中用到的设计模式有哪些?

建造者模式:SqlSessionFactoryBulider,XMLConfgBulider,XMLMapperBuilder
工厂模式:SqlSessionFactory、MapperProxyFactory
单例模式:ErrorContext
代理模式:JDK动态代理MapperProxy
模版方法模式:BaseExecution和simpleExecution
适配器模式:对其他的日志框架实现适配
装饰者模式:二级缓存就是使用装饰者模式实现的

3、JDK动态代理和CGLIB动态代理有什么区别?

4、Mybatis源码分析流程?

(1)首先通过Resource类的方法去通过mybatis的xml文件获取InputStreamReader IO流
(2)SqlSessionFactoryBulider调用buile方法,Build方法内部创建了XMLConfigBuilder对象去解析mybatis.xml文件转换成Configuration对象,用XMLMapperBuilder去解析配置文件。把mapper.xml所在的位置存放到hashset中,把接口的class文件注册到mapperRegister中,然后使用Configuration对象创建了DefaultSqlSessionFactory
(3)通过SqlSessionFactory.openSession()获取到sqlsession对象,openSession方法中通过Configuration对象和执行器(BatchExecutor 批处理,SimpleExecutor 简单)去创建DefaultSqlSession,在创建执行器的时候会去判断创建哪种类型的执行器,批处理或者简单类型的,最后会去判断是否创建二级缓存执行器,默认是开启的,通过简单或者批处理执行器去创建
(4)通过sqlsession.getMapper方法去获取到Mapper对象,底层是使用JDK动态代理模式获取的对象,getMapper就是从mapperRegister中找的

5、Mybatis的五个优点?

(1)sql语句与代码分离,存放于xml配置文件中,降低耦合度,便于维护管理
(2)Mybatis是一个持久层框架(写入硬盘)
(3)提供XML标签,支持动态sql(例如if else)
(4)提供映射标签,支持对象和数据库的ORM字段关系映射(property column)
(5)封装了JDBC,与传统的JDBC相比,减少了50%以上的代码量

6、Mybatis的缺点?

(1)SQL语句的编写工作量大
(2)SQL语句依赖数据库,移植性差

7、什么是Mybatis

Mybatis是一个半ORM(对象关系映射)的持久层框架,简单封装了JDBC

8、接口绑定的两种方式及适用场合?

注解:适合单表简单操作
XML:适合复制操作

9、Mybatis的适用场合?

(1)性能要求高
(2)需求变动大,SQL语句可以灵活改动

10、#{}和 的 区 别 是 什 么 ? 通 配 符 {}的区别是什么?通配符 #

#{}是预编译处理,${}是字符串替换。
适用#{}可以有效的防止注入攻击

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

(1)字段取别名
(2)resultMap

12、jdbc的步骤

(1)加载驱动
(2)获取连接
(3)创建statement对象
(4)执行sql
(5)关闭资源

public  void test_insert()
	{
		String driver="oracle.jdbc.driver.OracleDriver";
		String url="jdbc:oracle:thin:@127.0.0.1:1521:orcl";//orcl为sid
		String user="briup";
		String password="briup";
		Connection conn=null;
		 Statement stat=null;
		try {
			//1、注册驱动
			Class.forName(driver);
			//2、获取连接
			 conn= DriverManager.getConnection(url, user, password);
			 //System.out.println(conn);
			//3、创建statement对象
			stat=conn.createStatement();
			 //4、执行sql语句
			 String sql="insert into lover values(5,'suxingxing',to_date('21-9-2016','dd-mm-yyyy'))";
			 stat.execute(sql);
			 //System.out.println(stat.execute(sql));
			 //5、处理结果集,如果有的话就处理,没有就不用处理,当然insert语句就不用处理了
		} catch (Exception e) {
			e.printStackTrace();
		}
		finally{
			//6、关闭资源
			try {
				if(stat!=null)stat.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			try {
				if(conn!=null)conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}

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

(1)like #{value} 传值时加入%
(2)like “%”#{value}"%"
(3)like concat("%",#{value},"%")

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

(1)Mapper接口中的方法不能重载,因为xml中id是根据方法名识别的
(2)每一个、、、标签,都会被解析为一个MapperStatement对象。
(3)Mapper 接口的工作原理是JDK动态代理

15、Mybatis是如何进行分页的?分页插件的原理是什么?

(1)Mybatis使用RowBounds对象进行分页,它是针对ResultSet结果集执行的内存分页,而非物理分页。
(2)分页插件的基本原理是使用Mybatis提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的sql,然后重写sql

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

(1)通过反射创建对象
(2)使用标签,一一对应
(3)使用别名对应 as

17、如何执行批量插入?

先循环插入且不提交,全部插入后一次性提交

18、在mapper中如何传递多个参数?

(1)直接传入,用#{0},#{1}表示第几个参数
(2)@param(“name”) String name,用#{name}获取
(3)传入对象,用#{name}获取

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

(1)动态编写sql语句
(2)根据表达式,完成逻辑判断,动态拼接sql
(3)九种标签:trim | where | set | foreach | if | choose | when | otherwise | bind

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

(1)、、、、,加上动态sql的9个标签,其中为sql片段标签,通过标签引入sql片段,为不支持自增的主键生成策略标签。

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

(1)namespace+id作为key,只要namespace不同,id相同也行

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

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

23、一对一,一对多?

一对一:association
一对多:collection

24、Mybatis是否支持延迟加载?如果支持,它的实现原理是什么?

(1)association和collection可以配置lazyLoadingEnabled=true|false
(2)使用CGLIB动态代理,在真正调用的时候才去查询指定sql

<association property="customer" javaType="cn.com.mybatis.po.Customer" select="findCustomerById" column="cus_id">
</association>

<select id="findCustomerById" parameterType="int" resultType="cn.com.mybatis.po.Customer">
	select * from customer where cus_id=#{id}
</select>

<settings>
		<!-- 打开延迟加载的开关 -->
		<setting name="lazyLoadingEnabled" value="true"/>
		<!-- 将积极加载改为消极加载(即按需加载) -->
		<setting name="aggressiveLazyLoading" value="false"/>
</settings>

25、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 掉并重新更新,如果开启了二级缓存,则只根据配置判断是否刷新。

26、Mapper编写有哪几种方式?

(1)接口实现类继承SqlSessionDaoSupport
(2)xml中配置映射
(3)使用mapper扫描器

27、缓存的顺序,以及一级缓存集群中存在的问题?

先找二级缓存,二级缓存没有配置的话,再去找一级缓存
一级缓存:sqlsession缓存
二级缓存:sqlsessionFactory缓存,存到第三方缓存

一级缓存底层是使用map集合去存放的,查询的时候会缓存到map集合中,在增删改数据的时候会去清除全部的缓存,在集群的条件下,一台节点缓存了数据之后,另一台节点去修改,此时会导致第一台出现脏读。

28、如何关闭一级缓存?

(1)开启二级缓存
(2)查询的时候增加随机数,但是这样map集合很快就满了
(3)在增删改的时候执行器会调用update方法会去清除缓存,我们可以调用这个clear方法清除缓存

Mybatis默认最多查询Integer最大值2^32-1

29、几个核心类的作用?

BaseExecutor:继承了Executor,实现了部分方法,是个抽象类,使用模版方法设计模式,实现他的子类有简单执行器、批处理执行器、还有重复使用执行器,默认情况下是使用简单执行器的

SimpleExecutor:简单的执行类,并不会做一些处理就执行sql
BacthExecutor:批处理执行器,toUpdate、toQuery、toFlushStatements三个方抽象法
ReuseExecutor:重复使用执行器,其中定义个一个Map,String是SQL语句,这样就不用重复去创建Statement对象
Statement:用于执行不带参数的简单SQL语句
PreparedStatement:预编译,默认采用

SqlSessionFactoryBulider:根据InputStreamReader转换流去创建SqlSessionFactory
SqlSessionFactory:根据执行器创建SqlSession
SqlSession:存放sql会话信息,属性有执行器和configuration,getMapper方法就是从configuration中的MapperRegistry中的MapperProxyFactory获取到代理类

XMLConfgBulider:用来解析mybatis配置文件,返回configuration对象
XMLMapperBuilder:主要是用于解析mybatis中的标签里边的内容

RoutingStatementHandler,这是一个封装类,它不提供具体的实现,只是根据Executor的类型,创建不同的类型StatementHandler。
SimpleStatementHandler,这个类对应于JDBC的Statement对象,用于没有预编译参数的SQL的运行。
PreparedStatementHandler 这个用于预编译参数SQL的运行。

localCache:hashmap存放一级缓存
DefaultResoultSetHandler:返回结果集给客户端

你可能感兴趣的:(面试题总结,数据库,mybatis,java,mysql,hibernate)