1、什么是Mybatis?
(1)Mybatis是一个半ORM(对象关系映射)框架,它内部封装了JDBC,开发时只需要关注SQL语句本身,不需要花费精力去处理加载驱动、创建连接、创建statement等繁杂的过程。程序员直接编写原生态sql,可以严格控制sql执行性能,灵活度高。
(2)MyBatis 可以使用 XML 或注解来配置和映射原生信息,将 POJO映射成数据库中的记录,避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。
(3)通过xml 文件或注解的方式将要执行的各种 statement 配置起来,并通过java对象和 statement中sql的动态参数进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射为java对象并返回。(从执行sql到返回result的过程)。
2、Mybaits的优点:
(1)基于SQL语句编程,相当灵活,不会对应用程序或者数据库的现有设计造成任何影响,SQL写在XML里,解除sql与程序代码的耦合,便于统一管理;提供XML标签,支持编写动态SQL语句,并可重用。
(2)与JDBC相比,减少了50%以上的代码量,消除了JDBC大量冗余的代码,不需要手动开关连接;
(3)很好的与各种数据库兼容(因为MyBatis使用JDBC来连接数据库,所以只要JDBC支持的数据库MyBatis都支持)。
(4)能够与Spring很好的集成;
(5)提供映射标签,支持对象与数据库的ORM字段关系映射;提供对象关系映射标签,支持对象关系组件维护。
3、MyBatis框架的缺点:
(1)SQL语句的编写工作量较大,尤其当字段多、关联表多时,对开发人员编写SQL语句的功底有一定要求。
(2)SQL语句依赖于数据库,导致数据库移植性差,不能随意更换数据库。
4、MyBatis框架适用场合:
(1)MyBatis专注于SQL本身,是一个足够灵活的DAO层解决方案。
(2)对性能的要求很高,或者需求变化较多的项目,如互联网项目,MyBatis将是不错的选择。
5、MyBatis与Hibernate有哪些不同?
(1)Mybatis和hibernate不同,它不完全是一个ORM框架,因为MyBatis需要程序员自己编写Sql语句。
(2)Mybatis直接编写原生态sql,可以严格控制sql执行性能,灵活度高,非常适合对关系数据模型要求不高的软件开发,因为这类软件需求变化频繁,一但需求变化要求迅速输出成果。但是灵活的前提是mybatis无法做到数据库无关性,如果需要实现支持多种数据库的软件,则需要自定义多套sql映射文件,工作量大。
(3)Hibernate对象/关系映射能力强,数据库无关性好,对于关系模型要求高的软件,如果用hibernate开发可以节省很多代码,提高效率。
6、#{}和${}的区别是什么?
#{}是预编译处理,${}是字符串替换。
Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值;
Mybatis在处理{}替换成变量的值。
使用#{}可以有效的防止SQL注入,提高系统安全性。
7、请写出Mybatis核心配置文件MyBatis-config.xml的内容?
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--加载我们需要的properties文件 获取连接四要素-->
<properties resource="jdbc.properties"/>
<settings>
<!-- 全局性地启用或禁用延迟加载。当禁用时,所有关联的配置都会立即加载。 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!--当启用后,一个有延迟加载属性的对象的任何一个延迟属性被加载时,该对象
的所有的属性都会被加载。否则,所有属性都是按需加载。 -->
<setting name="aggressiveLazyLoading" value="false"/>
<!--全局关闭2级缓存 -->
<!--<setting name="cacheEnabled" value="false"/>-->
</settings>
<!--创建类的别名-->
<typeAliases>
<!--只要是在mapper.xml文件中使用了cn.pb.bean包下面的任意类的时候,无需再用全类名
使用简写的类名
之前应该 cn.pb.bean.Student
现在 Student
-->
<package name="cn.pb.bean"/>
</typeAliases>
<!--设置mybatis运行环境 default默认的运行环境====environment id的属性值-->
<environments default="mysql">
<environment id="mysql">
<!--配置事务管理器-->
<transactionManager type="JDBC"></transactionManager>
<!--配置数据源 POOLED:mybatis自带的数据源-->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!--配置需要的mapper文件-->
<mappers>
<mapper resource="mapper/StudentMapper.xml"/>
</mappers>
</configuration>
8、什么是数据持久化以及ORM?
01.数据持久化的概念
数据持久化就是将内在中的数据模型转换为存储模型,以及将存储模型转换为内在中的数据模型的统称,数据模型可以是任何数据结构或对象模型,例如JavaBean对象;存储模型可以是关系型数据库表,XML文件,二进制文件等.02.什么是ORM
ORM(Object/Relational Mapping)中文翻译为对象/关系型数据映射,它也可以理解为一种数据持久化技术,其主要是把对象模型,例如JavaBean对象和关系型数据库的表建立对应关系,并且提供了一个通过JavaBean对象去操作数据库表的机制.03.使用ORM技术的好处
在实际开发中,程序员使用面向对象的技术操作数据,而当要把数据存储起来时,使用的却是关系型数据库,这样就造成了很多的不便,ORM在对象模型和关系数据库的表之间建立了一座桥梁,有了它,程序员就不需要再使用SQL语句操作数据库中的表,直接操作JavaBean对象就可以实现数据的存储,查询,更改和删除等操作,Hibernate就是这样一种技术.
9、请写出MybatisUtil工具类
package cn.pb.util;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
public class SessionFactoryUtil {
//01.创建需要单例的对象实例
private static SqlSessionFactory sessionFactory;
//02.私有化构造
private SessionFactoryUtil(){}
/**
* 03.对外提供访问的接口
* 001.SqlSession的创建依赖SqlSessionFactory
* 002.SqlSessionFactory依赖于SqlSessionFactoryBuilder
* 003.SqlSessionFactoryBuilder依赖于配置文件
* 004.获取配置文件
*/
public static synchronized SqlSession getSession(){
//给我一个文件 返回一个输入流 到 内存中
try {
InputStream stream = Resources.getResourceAsStream("mybatis.xml");
//判断SqlSessionFactory是否为空
if (sessionFactory==null){
sessionFactory=new SqlSessionFactoryBuilder().build(stream);
}
} catch (IOException e) {
e.printStackTrace();
}
/**
* 之前还需要写一个finally用来关闭流! 现在不需要 为什么不需要??
* 01.查询源码build(stream)
* 02.SqlSessionFactoryBuilder类中已经关闭reader.close()
* 03.所以我们如果关闭流 会报错!
*/
return sessionFactory.openSession(); //创建session返回
}
}
10、请使用association节点实现根据用户id查询用户信息以及对应角色信息(Role实体类中有一个对象User,只写SQL映射文件)?
<!-- 01. 根据角色id 查询出角色信息-->
<select id="selectRoleById" resultMap="roleMap">
select id,name,userid from role where id=#{xxx}
</select>
<!-- 02. 根据角色表中查询结果中的userid 查询用户信息
xxx就是resultmap中传递来的 userid-->
<select id="selectUserByUserId" resultType="User">
select userid,name from user where userid=#{xxx}
</select>
<!--对应的roleMap 这种方式 推荐使用 因为使用延迟加载-->
<resultMap id="rolrMap" type="Role">
<id property="id" column="id"/>
<result property="name" column="name"/>
<!-- Role有一个属性的类型是 user 域属性
javaType:域属性对应的类型 -->
<association property="user" javaType="User" select="selectUserByUserId"
column="userid"/>
</resultMap>
11、请使用collection节点实现获取指定用户的相关信息和地址列表(User实体类中有一个复杂类型的Address集合,只写SQL映射文件)?
<!-- 01. 根据用户id 查询出用户信息-->
<select id="selectUserById" resultMap="userMap">
select id,name from user where id=#{xxx}
</select>
<!-- 02. 根据用户表中查询结果中的userid 查询地址信息
xxx就是resultmap中传递来的 userid-->
<select id="selectAddressByUserId" resultType="Address">
select id,name,userid from address where userid=#{xxx}
</select>
<!--对应的userMap 这种方式 推荐使用 因为使用延迟加载-->
<resultMap id="userMap" type="User">
<id property="id" column="id"/>
<result property="name" column="name"/>
<!-- User有一个属性的类型是 list
javaType:域属性对应的类型 -->
<collection property="addresses" javaType="Address" select="selectAddressByUserId"
column="userid"/>
</resultMap>
12、MyBatis实现一对一有几种方式?具体怎么操作的?
有联合查询和嵌套查询,联合查询是几个表联合查询,只查询一次, 通过在resultMap里面配置association节点配置一对一的类就可以完成;
嵌套查询是先查一个表,根据这个表里面的结果的 外键id,去再另外一个表里面查询数据,也是通过association配置,但另外一个表的查询通过select属性配置。
13、MyBatis实现一对多有几种方式,怎么操作的?
有联合查询和嵌套查询。联合查询是几个表联合查询,只查询一次,通过在resultMap里面的collection节点配置一对多的类就可以完成;嵌套查询是先查一个表,根据这个表里面的 结果的外键id,去再另外一个表里面查询数据,也是通过配置collection,但另外一个表的查询通过select节点配置。
14、Mybatis是否支持延迟加载?如果支持,它的实现原理是什么?
答:Mybatis仅支持association关联对象和collection关联集合对象的延迟加载,association指的就是一对一,collection指的就是一对多查询。在Mybatis配置文件中,可以配置是否启用延迟加载lazyLoadingEnabled=true|false。
它的原理是,使用CGLIB创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用a.getB().getName(),拦截器invoke()方法发现a.getB()是null值,那么就会单独发送事先保存好的查询关联B对象的sql,把B查询上来,然后调用a.setB(b),于是a的对象b属性就有值了,接着完成a.getB().getName()方法的调用。这就是延迟加载的基本原理。
当然了,不光是Mybatis,几乎所有的包括Hibernate,支持延迟加载的原理都是一样的。
15、Mybatis的一级、二级缓存:
1)一级缓存: 基于 PerpetualCache 的 HashMap 本地缓存,其存储作用域为 Session,当 Session flush 或 close 之后,该 Session 中的所有 Cache 就将清空,默认打开一级缓存。
2)二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap 存储,不同在于其存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache。默认不打开二级缓存,要开启二级缓存,使用二级缓存属性类需要实现Serializable序列化接口(可用来保存对象的状态),可在它的映射文件中配置<cache/> ;
3)对于缓存数据更新机制,当某一个作用域(一级缓存 Session/二级缓存Namespaces)的进行了C/U/D 操作后,默认该作用域下所有 select 中的缓存将被 clear。
16、什么是MyBatis的接口绑定?有哪些实现方式?
接口绑定,就是在MyBatis中任意定义接口,然后把接口里面的方法和SQL语句绑定, 我们直接调用接口方法就可以,这样比起原来了SqlSession提供的方法我们可以有更加灵活的选择和设置。
接口绑定有两种实现方式,一种是通过注解绑定,就是在接口的方法上面加上 @Select、@Update等注解,里面包含Sql语句来绑定;另外一种就是通过xml里面写SQL来绑定, 在这种情况下,要指定xml映射文件里面的namespace必须为接口的全路径名。当Sql语句比较简单时候,用注解绑定, 当SQL语句比较复杂时候,用xml绑定,一般用xml绑定的比较多。
17、使用MyBatis的mapper接口调用时有哪些要求?
① Mapper接口方法名和mapper.xml中定义的每个sql的id相同;
② Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同;
③ Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同;
④ Mapper.xml文件中的namespace即是mapper接口的类路径。