文章目录
- Q:什么是Mybatis?
- Q:MyBatis与Hibernate有哪些不同?
- Q:#{}和${}的区别是什么?
- Q:当实体类中的属性名和表中的字段名不一样如何解决?
- Q:Xml映射文件中,除了常见的select|insert|update|delete标签之外,还有哪些标签?
- Q:通常一个Xml映射文件,都会写一个Dao接口与之对应,这个Dao接口的工作原理是什么?
- Q:介绍一下mybatis缓存?
- Q:Mybatis是如何进行分页的?分页插件的原理是什么?
- Q:如何获取自动生成的id?
- Q:在mapper中如何传递多个参数?
- Q:MyBatis的mapper接口调用时有那些限定?
- Q:Mybatis 与 JDBC 编程的比较
Q:什么是Mybatis?
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL
、存储过程
以及高级映射
。
MyBatis 避免了几乎所有的 JDBC 代码
和手动设置参数
以及获取结果集
。
MyBatis 可以使用简单的 XML
或注解
来配置和映射原生信息
、将接口
和 Java 的 POJO
(Plain Old Java Objects,普通老式 Java 对象)映射为数据库中的记录。
Q:MyBatis与Hibernate有哪些不同?
相同点
都是对jdbc的封装,都是持久层的框架,都用于dao层的开发。
不同点 :
Hibernate:是一个全自动映射
的框架,不需要编写SQL就能对数据库进行操作。对于SQL的修改和优化
比较困难。比较适合需求变化不大的中小型项目:OA,ERP、管理系统等
MyBatis:是一种半自动映射
的框架,专注于SQL本身
,对SQL修改和优化
比较简单,支持对象关系映射。需要是手动实现SQL。比较适合需求变化比较多的互联网项目。
Q:#{}和${}的区别是什么?
(1)#{}
是预编译处理,${}
是字符串替换
(2)Mybatis在处理#{}时,会将sql中的#{}
替换为?号,调用PreparedStatement的set方法来赋值;
(3)Mybatis在处理${}
时,就是把{}替换成变量的值。
(4)使用#{}可以有效的防止SQL注入,提高系统安全性
Q:当实体类中的属性名和表中的字段名不一样如何解决?
第1种: 让SQL语句字段名的别名和实体类的属性名一致。
第2种: 通过<resultMap>
来映射字段名和实体类属性名一 一对应。
第1种:
<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>
Q:Xml映射文件中,除了常见的select|insert|update|delete标签之外,还有哪些标签?
(1)<resultMap>结果集
:配置实体类属性
与结果集列名
的对应关系。
(2)<selectKey>
:selectKey返回最近插入的id。
(3)多表配置关联关系:collection(对一),association(对多)
(4)定义常量及引用:<sql>封装重复的SQL片段
,通过<include>
标签引入sql片段
(5)格式化输出:where格式化 ,set格式化, trim。
(6)控制动态SQL拼接:if选择, foreach循环, choose (when otherwise)相当于switch。
Q:通常一个Xml映射文件,都会写一个Dao接口与之对应,这个Dao接口的工作原理是什么?
Dao接口即Mapper接口。
接口的全限名,就是映射文件中的namespace的值;(com.song.dao.IUserDao
)
接口的方法名,就是映射文件中Mapper的Statement的id值;(findAll
)
接口方法内的参数,就是传递给sql的参数。
Mapper接口是没有实现类的,当调用接口方法时,接口全限名+方法名
拼接字符串作为key值,可唯一定位一个MapperStatement。在Mybatis中,每一个select、insert、update、delete标签,都会被解析为一个MapperStatement
对象。
public interface IUserDao {
List<User> findAll();
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.song.dao.IUserDao">
<!-- 配置查询所有 -->
<!-- resultType="com.song.domain.User"将结果集封装到User对象 ,添加到List里边 -->
<!-- id不能随便写,写的是方法名称 -->
<select id="findAll" resultType="com.song.domain.User">
<!-- 写的是SQL语句 -->
select * from user
</select>
</mapper>
在MyBatis启动时,会解析这些包含SQL的XML文件,并将其包装成为MapperStatement对象,并将MapperStatement注册到全局的configuration对象上。
Q:介绍一下mybatis缓存?
1.一级缓存
: MyBatis在开启一个数据库会话时,会创建一个新的SqlSession对象,SqlSession对象中会有一个新的Executor对象
(线程池)。Executor对象中持有一个新的PerpetualCache对象(缓存类);
何时清空一级缓存?
当会话结束时,SqlSession对象及其内部的Executor对象还有PerpetualCache对象也一并释放掉。当调用SqlSession的修改,添加,删除,commit(),close()等方法时,就会清空一级缓存。
2.二级缓存
:二级缓存其作用域是SqlSessionFactory。其默认是不开启的,二级缓存的开启需要进行配置,实现二级缓存的时候,MyBatis要求返回的POJO必须是可序列化的。 也就是要求实现Serializable接口,配置方法很简单,只需要在映射XML文件配置就可以开启缓存了
注意: 对于缓存数据更新机制,当某一个作用域(一级缓存 SQLSession/二级缓存SQLSessionFactory)的进行了cud操作后,默认该作用域下所有select中的缓存将被clear掉并重新更新,如果开启了二级缓存,则只根据配置判断是否刷新。
Q:Mybatis是如何进行分页的?分页插件的原理是什么?
Mybatis使用RowBounds
对象进行分页,它是针对ResultSet结果集执行的内存分页,而非物理分页。可以在sql内直接书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页。
分页插件的基本原理是使用Mybatis提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的sql,然后重写sql,根据dialect方言,添加对应的物理分页语句和物理分页参数。
举例:select * from student
拦截sql后重写为:select t.* from (select * from student) t limit 0, 10
Q:如何获取自动生成的id?
1 <insert id="xxx" usegeneratedkeys="true" keyproperty="id">
2 insert into xxxx (xxx) values (#{xxxx})
3 </insert>
Q:在mapper中如何传递多个参数?
1、对应的xml,#{0}
代表接收的是dao层中的第一个参数,#{1}
代表dao层中第二参数
2、使用 @param
注解
3、使用map
封装参数
Q:MyBatis的mapper接口调用时有那些限定?
1、Mapper接口方法名和mapper.xml中定义的每个sql的id
相同
2、Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql的parameterType的类型
相同
3、Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型
相同
4、Mapper.xml文件中的namespace即是mapper接口
的类路径。
Q:Mybatis 与 JDBC 编程的比较
(1)数据库连接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库连接池可解决此问题。
解决:在 SqlMapConfig.xml 中配置数据链接池,使用连接池管理数据库链接。
(2)Sql 语句写在代码中造成代码不易维护,实际应用 sql 变化的可能较大,sql 变动需要改变 java 代码。
解决:将 Sql 语句配置在 XXXXmapper.xml 文件中与 java 代码分离。
(3)向 sql 语句传参数麻烦,因为 sql 语句的 where 条件不一定,可能多也可能少,占位符需要和参数对应。
解决:Mybatis 自动将 java 对象映射至 sql 语句,通过 statement 中的 parameterType 定义输入参数的类型。
(4)对结果集解析麻烦,sql 变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成 pojo 对象解析比较方便。
解决:Mybatis 自动将 sql 执行结果映射至 java 对象,通过 statement 中的 resultType 定义输出结果的类型。