Java_Mybatis(29)

1、什么是Mybatis
  • 一个半ORM(对象关系映射)、实现了Sql统一管理的持久化框架;
  • 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集;
  • 支持定制化 SQL、存储过程以及高级映射;
2、ORM是什么
  • ORM,对象关系映射,是一种为了解决关系型数据库数据与简单Java对象(POJO)的映射关系的技术;
  • 简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系型数据库中;
3、为什么Mybatis是半自动化ORM映射工具
  • 查询关联对象或者集合对象时需要手动编写SQL;
4、JDBC编程有哪些不足之处,MyBatis是如何解决这些问题的?
  • 数据库连接创建、释放频繁造成系统资源浪费影响系统性能;
    解决:在mybatis-config.xml中配置数据链接池,使用连接池管理数据库连接。

  • Sql语句写在代码中造成代码不易维护;
    解决:将Sql语句配置在mapper.xml文件中与java代码分离。

  • 向sql语句传参数麻烦;
    解决: Mybatis自动将java对象映射至sql语句。

  • 对结果集解析麻烦,sql变化导致解析代码变化,且解析前需要遍历;
    解决:Mybatis自动将sql执行结果映射至java对象。

5、Mybatis优缺点

优点:

  • Mybatis是一款优秀的持久层框架,底层是JDBC;
  • Mybatis实现了Sql统一管理;
  • MybatisJ简化开发,如可以直接通过ResultMap将数据映射为java对象;
  • JDBC批处理效率较高;

缺点:

  • SQL语句的编写工作量较大,对开发人员编写SQL语句的功底有一定要求;
  • SQL语句依赖于数据库,导致数据库移植性差;
6、Mybatis编程步骤
  • 创建SqlSessionFactory
  • 由SqlSessionFactory创建SqlSession
  • 通过SqlSession操作数据库
  • session.commit()提交事务
  • session.close关闭事务
7、请说说MyBatis的工作原理
  • 读取 MyBatis 配置文件:mybatis-config.xml 为 MyBatis 的全局配置文件,配置了 MyBatis 的运行环境等信息,例如数据库连接信息。

  • 加载映射文件。映射文件即 SQL 映射文件,该文件中配置了操作数据库的 SQL 语句,需要在 MyBatis 配置文件 mybatis-config.xml 中加载。mybatis-config.xml 文件可以加载多个映射文件,每个文件对应数据库中的一张表。

  • 构造会话工厂:通过 MyBatis 的环境等配置信息构建会话工厂 SqlSessionFactory。

  • 创建会话对象:由会话工厂创建 SqlSession 对象,该对象中包含了执行 SQL 语句的所有方法。

  • Executor 执行器:MyBatis 底层定义了一个 Executor 接口来操作数据库,它将根据 SqlSession 传递的参数动态地生成需要执行的 SQL 语句,同时负责查询缓存的维护。

  • MappedStatement 对象:在 Executor 接口的执行方法中有一个 MappedStatement 类型的参数,该参数是对映射信息的封装,用于存储要映射的 SQL 语句的 id、参数等信息。

  • 输入参数映射:输入参数类型可以是 Map、List 等集合类型,也可以是基本数据类型和 POJO 类型。输入参数映射过程类似于 JDBC 对 preparedStatement 对象设置参数的过程。

  • 输出结果映射:输出结果类型可以是 Map、 List 等集合类型,也可以是基本数据类型和 POJO 类型。输出结果映射过程类似于 JDBC 对结果集的解析过程。

8、为什么需要预编译

定义:

  • SQL 预编译指的是数据库驱动在发送 SQL 语句和参数给 DBMS 之前对 SQL 语句进行编译,当 DBMS 执行 SQL 时,就不需要重新编译。

为什么需要预编译

  • 预编译阶段可以优化 SQL 的执行,预编译之后的 SQL 多数情况下可以直接执行,DBMS 不需要再次编译;
  • 预编译语句对象可以重复利用。把一个 SQL 预编译后产生的 PreparedStatement 对象缓存下来,下次对于同一个SQL,可以直接使用这个缓存的 PreparedState 对象;
  • Mybatis默认情况下,将对所有的 SQL 进行预编译;
9、Mybatis都有哪些Executor执行器?它们之间的区别是什么?
  • SimpleExecutor:每执行一次update或select,就开启一个Statement对象,用完立刻关闭Statement对象;

  • ReuseExecutor:执行update或select,以sql作为key查找Statement对象,存在就使用,不存在就创建,用完后,不关闭Statement对象,而是放置于Map<String, Statement>内,供下一次使用;

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

10、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()方法的调用。
11、#{}与${}区别
  • #{}是预编译处理,${}是字符替换;
  • 为了防止sql注入,推荐#{};
12、模糊查询like语句该怎么写

(1)’%${question}%’ 可能引起SQL注入,不推荐

(2)“%”#{question}“%” 注意:因为#{…}解析成sql语句时候,会在变量外侧自动加单引号’ ',所以这里 % 需要使用双引号" ",不能使用单引号 ’ ',不然会查不到任何结果。

(3)CONCAT(’%’,#{question},’%’) 使用CONCAT()函数,推荐

13、Mybatis如何将sql结果封装为对象并返回(属性名与字段不一致)
  • 使用resultMap标签来映射字段名与对象属性的关系,通过反射创建对象;
  • 在查询的SQL语句中定义字段名的别名,让字段名的别名和实体类的属性名一致;
14、在mapper中如何传递多个参数
  • 顺序传参:利用参数顺序获取参数
  • @Parm注解传参(推荐)
  • JavaBean对象传参 (推荐)
  • Map传参(推荐)
15、使用MyBatis的mapper接口调用时有哪些要求?
  • Mapper接口方法名和mapper.xml中定义的每个sql的id相同;

  • Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同;

  • Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同;

  • Mapper.xml文件中的namespace即是mapper接口的类路径;

16、最佳实践中,通常一个Xml映射文件,都会写一个Dao接口与之对应,请问,这个Dao接口的工作原理是什么?Dao接口里的方法,参数不同时,方法能重载吗
  • Dao接口,就是人们常说的Mapper接口,接口的全限名,就是映射文件中的namespace的值,接口的方法名,就是映射文件中MappedStatement的id值,接口方法内的参数,就是传递给sql的参数。Mapper接口是没有实现类的,当调用接口方法时,接口全限名+方法名拼接字符串作为key值,可唯一定位一个MappedStatement;

  • Dao接口里的方法,是不能重载的,因为是全限名+方法名的保存和寻找策略。

  • Dao接口的工作原理是JDK动态代理,Mybatis运行时会使用JDK动态代理为Dao接口生成代理proxy对象,代理对象proxy会拦截接口方法,转而执行MappedStatement所代表的sql,然后将sql执行结果返回。

17、Mybatis的Xml映射文件中,不同的Xml映射文件,id是否可以重复?
  • 不同的Xml映射文件,如果配置了namespace,那么id可以重复;如果没有配置namespace,那么id不能重复;

  • 原因就是namespace+id是作为Map<String, MappedStatement>的key使用的,如果没有namespace,就剩下id,那么,id重复会导致数据互相覆盖。有了namespace,自然id就可以重复,namespace不同,namespace+id自然也就不同。

18、简述Mybatis的Xml映射文件和Mybatis内部数据结构之间的映射关系?

在Xml映射文件中,

  • 标签会被解析为ParameterMap对象,其每个子元素会被解析为ParameterMapping对象;
  • 标签会被解析为ResultMap对象,其每个子元素会被解析为ResultMapping对象;
  • 每一个select、insert、update、delete标签均会被解析为MappedStatement对象;
  • 标签内的sql会被解析为BoundSql对象。
19、Mybatis是如何将sql执行结果封装为目标对象并返回的?都有哪些映射形式?
  • 第一种是使用标签,逐一定义列名和对象属性名之间的映射关系;

  • 第二种是使用sql列的别名功能,将列别名书写为对象属性名;

有了列名与属性名的映射关系后,Mybatis通过反射创建对象,同时使用反射给对象的属性逐一赋值并返回。

20、Mybatis映射文件中,如果A标签通过include引用了B标签的内容,请问,B标签能否定义在A标签的后面,还是说必须定义在A标签的前面?
  • Mybatis解析Xml映射文件是按照顺序解析的,但是,被引用的B标签依然可以定义在任何地方;

  • 原理是Mybatis解析标签时未解析到会标记为未解析状态,待所有标签解析完毕,Mybatis会重新解析那些被标记为未解析的标签。

21、Mybatis实现一对一,一对多有几种方式
  • 联合查询:通过在resultMap中配置节点就可以,只查询一次;
  • 嵌套查询:根据对应关系去另外表里面匹配,查询多次;
22、Mybatis常见标签
  • 基本处理:select\insert\delete\update
  • 映射对象:resultmap
  • 动态sql:where\set\if\when\chose\otherwise\foreach
  • 公用sql:sql\incluse
23、Mybatis如何执行批量操作

使用foreach标签。foreach的主要用在构建in条件中,在SQL语句中进行集合迭代。foreach标签的属性主要有:

  • item:表示集合中每一个元素进行迭代时的别名,随便起的变量名;
  • index:指定一个名字,用于表示在迭代过程中,每次迭代到的位置;
  • open:表示该语句以什么开始,常用“(”;
  • separator:表示在每次进行迭代之间以什么符号作为分隔符,常用“,”;
  • close:表示以什么结束,常用“)”。
24、Mybatis是否可以映射Enum枚举类?
  • 可以映射枚举类,可以映射任何对象到表的一列上;
  • 映射方式为自定义一个TypeHandler,实现TypeHandler的setParameter()和getResult()接口方法;
25、简述动态sql及其执行原理
  • 概念:以标签形式编写SQL来完成动态拼接;
  • 标签:if\where\choose\when\otherwise\foreach\set
  • 原理:从sql参数对象中计算表达式的值,根据表达式的值动态拼接sql;
26、Mybatis如何进行分页
  • Mybatis使用RowBounds对象进行分页,它是针对ResultSet结果集执行的内存分页,而非物理分页,可以在sql内直接书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页;
27、什么是mybatisplus接口绑定?有哪些实现方式?
  • 接口绑定是指在Mybatis中定义接口,然后和sql语句绑定,直接调用接口使用;
  • 可以通过@select等注解实现,或者XML配置实现;
28、Mybatis插件运行原理?如何编写一个插件?
  • Mybatis仅可以编写针对ParameterHandler、ResultSetHandler、StatementHandler、Executor这4种接口的插件;
  • 实现Mybatis的Interceptor接口并复写intercept()方法,然后在给插件编写注解,指定要拦截哪一个接口的哪些方法即可;
29、Mybatis缓存理解
  • 支持一级缓存与二级缓存,默认开启为一级缓存,存储作用域为 Session,无法关闭;
  • 二级缓存需要手动开启和配置,他是基于namespace级别的缓存;
  • 数据默认在一级缓存中,只有会话提交或者关闭才会转到二级缓存;
  • 当某一个作用域(一级缓存 Session/二级缓存Namespaces)的进行了C/U/D 操作后,默认该作用域下所有 select 中的缓存将被 clear;
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值