Java面试题总结记录(4)—— MyBatis篇

1、什么是MyBatis?

(1)MyBatis是一个对象关系映射框架,内部封装了JDBC,开发时只需要注意SQL语句本身,不需要花费精力去处理加载启动、创建连接、创建statement等繁杂的过程。

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

(3)MyBatis 可以使用 XML 或注解的方式将要执行的各种 statement 配置起来,并通过Java对象和 statement 中sql的动态参数进行映射生产最终执行的sql语句,最后由mybatis框架执行sql并将结果映射为java对象并返回。


2、说说MyBatis的优点和缺点

(1)优点

  • 基于 SQL 语句编程,SQL 写在 XML 里,解除SQL 与程序代码的耦合,便于统一管理;提供 XML 标签,支持编写动态SQL,并重用。
  • 简化 JDBC 配置和代码量,消除大量冗余的代码。
  • 兼容性好,由于Mybatis通过JDBC连接数据库,主要是JDBC支持的数据库。
  • 与Spring很好的集成。
  • 提供映射标签,支持对象与数据库的对象字段关系映射,提供对象关系映射标签,支持对象关系组件维护。
    (2)缺点
  • SQL编写量大。
  • SQL依赖于数据库,导致数据库移植性差,不能随意更换数据库。

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

  • #{}: 预编译处理,会将sql中的#{}替换为 ?号,调用PreparedStatement的set方法赋值,使用#{}有助于防止SQL注入,提高系统安全性。
  • ${}: 字符串替换,将${}替换成变量的值。

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

第 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 property=”id” column=”order_id”>
	 <result property = “orderno” column =”order_no”/>
	 <result property=”price” column=”order_price” />
</reslutMap>

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

MyBatis使用 RowBounds 对象进行分页,是针对 ResultSet 结果集执行的内存分页,而非物理分页。可以在 SQL 内直接拼写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页,例如:使用 limit 关键字分页。

分页插件的基本原理是使用 Mybatis 提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的sql,然后重写sql,根据dialect,添加对应的物理分页语句和物理分页参数。


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

(1)使用标签: 逐一定义数据库列名和对象属性名之间的映射关系。

<resultMap type=”me.gacl.domain.order” id=”orderresultmap”>
	 <id property=”id” column=”order_id”>
	 <result property = “orderno” column =”order_no”/>
	 <result property=”price” column=”order_price” />
</reslutMap>

(2)使用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>

注意:没有映射关系的属性,无法完成对象赋值


7、如何执行批量插入?

第 1 种: Java程序循环执行插入方法
第 2 种: mapper 中添加<foreach> 标签,但要开启提交事务保证安全性。


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

XML映射文件中的标签有:

  • select
  • insert
  • update
  • delete
  • if
  • foreach
  • sql(复用sql片段)
  • set
  • when
  • otherwise(就是switch)
  • choose(可以用where)
  • trim(截断添加)
    • prefix: 在前面添加内容
    • suffix: 在后面添加内容
    • prefixOverrides: 去掉前面内容
    • suffixOverrides: 去掉后面内容
  • bind(模糊查询,可以用CONCAT()函数)
    • name: 参数名
    • value: 模糊参数规则

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

联合查询嵌套查询

联合查询: 几个表联合查询,只查询一次,通过在resultMap里面配置association节点配置一对一的类就可以完成。

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


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

Mybatis仅支持 association 关联对象和 collection 关联集合对象的延迟加载。

association 指的是一对一。
collection指的是一对多查询。

配置延迟加载: lazyLoadingEnabled=true | false

实现原理: 使用 CGLIB 创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用 a.getB().getName(),拦截器 invoke() 发现 a.getB() 是 null ,那么就会单独发送事先保存好的查询关联B对象的sql,把B查询上来,然后调用a.setB(b),于是a的对象、b属性都有值了,接着完成 a.getB().getName() 的调用。


11、说说Mybatis的缓存机制

Mybatis有二级缓存

(1)一级缓存LocalCache: 当我们使用相同SQL进行查询,MyBatis就会使用LocalCache进行缓存查询结果,当再次使用相同SQL,会先从一级缓存拉取结果,提高了性能。

特点:

  • MyBatis 一级缓存的生命周期和 SqlSession一致(与会话存活相关)。
  • MyBatis 一级缓存内部设计简单,是一个无限制大小的HashMap。
  • MyBatis 的一级缓存最大范围是 SqlSession 内部,有多个 SqlSession 或者分布式的环境下,可能会引起在脏数据,建议设定缓存级别为 Statement。

(2)二级缓存共享缓存: 由于需要处理多SqlSession之间的共享数据,则需要耳机缓存,开启二级缓存后,会使用 CachingExecutor 修饰的 Executor,进入一级缓存的查询流程前,先进行二级缓存的查询。

注意:同一个 namespace 下的所有操作语句,都会影响同一个 Cache。

特定:

  • 二级缓存更专注共享缓存数据,同时粒度更细,能够到 namespace 级别,通过Cache 接口实现类不同的组合,对 Cache 的可控性更强。
  • 实现安全的二级缓存的条件比较苛刻。
  • 在分布式环境下,Mybatis Cache 实现都是基于本地的,必然会出现读取到脏数据,徐还要使用 集中式缓存 将 Cache 接口实现,有一定的开发成本,直接使用 Redis、Memcached 等分布式缓存可能成本更低,安全性也更高。

12、JDBC 编程有哪些步骤?

(1)反射机制加载驱动

Class.forName("com.mysql.jdbc.Driver");

(2)建立 JDBC 和数据库之间的 Connection 链接

Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test/characterEncoding=UTF-8", "root", "123456");

(3)常见 Statement 或着 PreparedStatement 接口,执行SQL
(4)处理和现实结果
(5)释放资源


13、MyBatis 中见过什么设计模式?

  • 建造者模式: SqlSessionFactoryBuilder,XMLConfigBuilder,XMLmAPPERBuilder,XMLStatementBuilder,CacheBuilder
  • 单例模式: ErrorContext,LogFactory
  • 代理模式: MyBatis实现的核心,比如MapperProxy,ConnectionLogger,用的JDK动态代理
  • 组合模式: SqlNode和各子类ChooseSqlNode
  • 模版方法模式: BaseExecutor 和 SimpleExecutor,还有BaseTypeHandler和所有子类
  • 适配器模式: Log的Mybatis接口和对JDBC、log4j等各种日志框架的适配实现。
  • 装饰者模式: Cache包中的cache.decorators自爆中各个装饰者的实现。
  • 迭代器模式: PropertyTokenizer
  • 工厂模式: SqlSessionFactory,ObjectFactory,MapperProxyFactory

14、MyBatis 中比如 UserMapper.java 是接口,为什么没有实现类还能调用?

使用了JDK动态代理+MapperProxy,本质上调用的是MapperProxy的invoke()。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Zain_horse

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值