9.Mybatis总结

一.什么是Mybatis?

MyBatis是一个开源的数据持久层框架,它内部封装了通过JDBC访问数据库的操作,支持普通的SQL查询、存储过程和高级映射,几乎消除了所有的JDBC代码和参数的手工设置以及结果集的检索。MyBatis作为持久层框架,其主要思想是将程序中大量SQL语句剥离出来,配置在配置文件中,实现SQL的灵活配置。这样做的好处是将SQL与程序代码分离,可以在不修改程序代码的情况下,直接在配置文件中修改SQL。Mybatis通过简单的XML或者注解进行配置和原始映射,将POJO实体类和SQL语句之间建立映射关系,是一种半自动化的ORM实现。

在这里插入图片描述

二.Mybatis的优点?

1)与JDBC相比,减少了50%以上的代码量。

2)MyBatis是最简单的持久化框架,小巧并且简单易学。

3)MyBatis相当灵活,不会对应用程序或者数据库的现有设计强加任何影响,SQL写在XML里,从程序代码中彻底分离,降低耦合度,便于统一管理和优化,并可重用。

4)提供XML标签,支持编写动态SQL语句。

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

三.Mybatis框架的组成(重点!!!)

在这里插入图片描述

四.Mybatis框架的工作流程(重点!!!)

在这里插入图片描述

1、读取Mybatis配置文件
2、根据读取到的配置文件生成SqlSessionFactoryBuilder和接口的实现类,创建 SqlSessionFactory
3、创建SqlSession对象(开启事务)
4、操作目标数据库
5、提交事务
6、关闭SqlSession

五.面试题:

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

#{}是预编译处理,${}是字符串替换。
Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值,会自动添加引号;
Mybatis在处理 时 , 就 把 {}时,就把 {}替换成变量的值,参数需要手动加引号。

使用#{}可以有效的防止SQL注入,提高系统安全性。

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

  • 给查询出的列命名别名,别名和属性名一致
  • 设置resultMap(一对一和一对多)

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

  • 1).在SQL语句中拼接 %
  • userName like CONCAT('%',#{},'%')
  • 2).在传递的实参中,参数值的两侧%

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

工作原理:接口+mapper映射文件结合起来,生成实现类,然后通过反射创建实现类的对象,通过这个对象去调用方法

  • Dao接口即Mapper接口。接口的全限名,就是映射文件中的namespace的值;接口的方法名,就是映射文件中Mapper的Statement的id值;接口方法内的参数,就是传递给sql的参数。

  • 不能重载.Mapper接口是没有实现类的,当调用接口方法时,接口全限名+方法名拼接字符串作为key值,可唯一定位一个MapperStatement。在Mybatis中,每一个<select><insert><update><delete>标签,都会被解析为一个MapperStatement对象。

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

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

  • 第二种是将列名和属性名一一对应.
    如果不一致,使用sql列的别名功能,将列的别名书写为对象属性名。
    有了列名与属性名的映射关系后,Mybatis通过反射创建对象,同时使用反射给对象的属性逐一赋值并返回,那些找不到映射关系的属性,是无法完成赋值的。

6.如何执行批量插入?

重点在这一句:
sqlsessionfactory.opensession(executortype.batch)

    sqlsession sqlsession = sqlsessionfactory.opensession(executortype.batch); 
    try { 
     namemapper mapper = sqlsession.getmapper(namemapper.class); 
     for (string name : names) { 
     mapper.insertname(name); 
     } 
     sqlsession.commit(); 
    } finally { 
     sqlsession.close(); 
    }

7.在mapper中如何传递多个参数?

  • 赋值给一个对象
  • 存入Map集合中
  • @Param注解

8.Mybatis动态sql是做什么的?都有哪些动态sql?能简述一下动态sql的执行原理不?

  • 1)Mybatis动态sql可以在Xml映射文件内,以标签的形式编写动态sql,执行原理是根据表达式的值 完成逻辑判断并动态拼接sql的功能。
  • 2)Mybatis提供了9种动态sql标签:trim | where | set | foreach | if | choose | when | otherwise | bind。
  • 3)原理:先解析方法的参数列表,然后根据参数的值动态生成sql,执行sql语句后,做结果映射

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

不能重复. 如果配置了namespace:那么id可以重复
namespace不是必须的,如果没有配置,mybatis把所有没有namespace的XML文件编译成一个文件
所以id是不能重复的。
区分原理namespace.id值作为HashMap集合的key值

10.mybatis的核心类是什么?

SqlSessionFactoryBuilder
  读取全局配置文件,得到数据源信息,创建连接工厂SqlSessionFactory。它的特点是,当创建了SqlSessionFactory对象之后,这个类就不需要了。因此,它的最佳范围是存在于方法体内,也就是局部变量。

SqlSessionFactory
  连接工厂;创建SqlSession实例的工厂。它的特点是,SqlSessionFactory对象一旦被创建,就无法销毁或者再创建,也不建议多次创建SqlSessionFactory对象。因此,它的最佳范围是应用(Application)范围内。

SqlSession
  会话对象类,SqlSession 完全包含了面向数据库执行 SQL 命令所需的所有方法。可以通过 SqlSession 实例来直接执行已映射的 SQL 语句。SqlSession对应着一次数据库会话,所以每次访问数据库时都需要在SqlSessionFactory实例的openSession()方法中创建它。但一个SqlSession会话也可以执行多次SQL语句。 SqlSession关闭后消失

Mapper
  映射类,跟映射关系对应,是从SqlSession中获取的。任何映射器实例的最大作用域是和请求它们的 SqlSession 相同的。尽管如此,映射器实例的最佳作用域是方法作用域。也就是说,映射器实例应该在调用它们的方法中被请求,用过之后即可废弃。并不需要显式地关闭映射器实例,尽管在整个请求作用域(request scope)保持映射器实例也不会有什么问题,但是很快你会发现,像 SqlSession 一样,在这个作用域上管理太多的资源的话会难于控制。所以要保持简单,最好把映射器放在方法作用域(method scope)内。

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

SimpleExecutor:每执行一次update或select,就开启一个Statement对象,用完立刻关闭Statement对象。

ResourceExecutor:执行update或select,以sql作为key查找Statement对象,存在就使用,不存在就创建,用完后,不关闭Statement对象,而是放置于Map内,供下一次使用。简言之,就是重复使用Statement对象。

BatchExecutor:执行update(没有select,JDBC批处理不支持select),将所有sql都添加到批处理中(addBatch()),等待统一执行(executeBatch()),它缓存了多个Statement对象,每个Statement对象都是addBatch()完毕后,等待逐一执行executeBatch()批处理。与JDBC批处理相同。

作用范围:Executor的这些特点,都严格限制在SqlSession生命周期范围内。

12.Mybatis中接口绑定有几种实现方式?怎么实现的?

接口绑定有两种实现方式,

  • 一种是通过注解绑定,就是在接口的方法上面加上 @Select@Update等注解里面包含Sql语句来绑定,
  • 另外一种就是通过xml里面写SQL来绑定, 在这种情况下,要指定xml映射文件里面的namespace必须为接口的全路径名.

13.传入的参数是数组或集合,如何使用动态SQL进行遍历?

需要使用迭代标签foreach遍历

UserDao.java

	//参数是数组类型
	public List<User> getAllUsersByAry(int[] aryRole);
	
	//参数是集合类型
	public List<User> getAllUsersByList(List<Integer> roleList);

UserMapper.xml

	 <!-- 参数是数组类型 -->
	 <select id="getAllUsersByAry" resultType="User">
	 	select id,userCode,userName,userPassword,userRole
	 	from smbms_user
	 	where userRole in
	 	<!-- 需要使用迭代标签遍历数组
	 		 array:关键字,参数是数组,即遍历的是数组
	 	 -->
	 	 <foreach collection="array" item="aryRole"
	 	 open="(" close=")" separator=",">
	 	 #{aryRole}
	 	 </foreach>
	 </select>
	 
	 <!-- 参数是集合类型 -->
	 <select id="getAllUsersByList" resultType="User">
	 	select id,userCode,userName,userPassword,userRole
	 	from smbms_user
	 	where userRole in
	 	<!-- 需要使用迭代标签遍历集合
	 		 list:关键字,参数是集合,即遍历的是集合
	 	 -->
	 	 <foreach collection="list" item="roleList"
	 	 open="(" close=")" separator=",">
	 	 #{roleList}
	 	 </foreach>
	 </select>

14.mybatis注解方式是怎样通过没有实现类的dao接口进行数据库操作?

mybatis注解方式通过没有实现类的dao接口进行数据库操作的原理,一句话概括,就是jdk proxy,就是jdk代理

  • ( 1)原理上:JDK动态动态代理的原理是根据 InvocationHandler 中的invoke()方法,由jdk为你的接口手动生成了一个实现了对应接口的类,因此,你的接口可以调用,这是理解mybatis接口没有实现类能被调用的关键。
  • ( 2)功能上:可以看出mybatis中的接口就是XML文件的描述,一方面这样做的目的是和spring集成,将接口交给spring管理;另一方面是为了更加方便的管理XML文件(使用接口的package+interface作为namespace,method作为ID)

15.spring+mybatis注解方式是怎样在没有实现类的dao接口的情况下结合的?

spring+mybatis注解方式,也是没有实现类的,但是spring会默认返回MapperFactoryBean对象作为实现类的替换,但是这个只是被spring使用的,mybatis本身还是通过jdk代理来运行的。

16.spring整合mybatis后,mybatis一级缓存失效的原因?

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值