Mybatis
(从XML中构建SqlsessionFactory,并从中获取SqlSession)
1、什么是MyBatis
- 持久层框架,一个半ORM框架,内部封装了JDBC,可以直接编写SQL语句
- 使用XML配置或者注解映射原生信息,将Java对象映射成数据库中的记录
- 可以将要执行的statement配置起来,并通过java对象和statement中sql的动态参数进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射为java对象并返回
2、说说MyBatis的优点和缺点
优点:(解耦、去冗余、高复用)
- SQL写在XML里,能有效解除sql与程序代码的耦合,便于统一管理
- 提供XML标签,支持编写动态SQL语句,并可重用。
- 消除了JDBC大量冗余的代码
- 能够与Spring很好的集成
缺点:(SQL水平和数据库移植性差)
- 对编写SQL能力有要求
- SQL语句依赖数据库,不能随意更换数据库
3、#{}和${}的区别是什么?
#{}是预编译处理,${}是字符串替换。
- 处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值
- 在处理${}时,就是把${}替换成变量的值。
- #{}可以有效的防止SQL注入
(1、#{任意值},$(value) 2、#{}会给字段加上''自动类型转换 ${}不会,适合动态排序和查询 3、#{}防SQL注入)
#一般用在参数的赋值上, $一般用在 order by 或desc 分组和排序的业务场景上
4、当实体类中的属性名和表中的字段名不一样 ,怎么办 ?
- 可以在查询的sql语句中取别名让字段名和属性名一致
- 使用结果集映射--->ResultMap property是属性名、column是字段名
5、Mybatis是如何进行分页的?分页插件的原理是什么?
- 用RowBounds对象进行分页,它是针对ResultSet结果集执行的内存分页而非物理分页。
- 使用SQL语句的Limit进行分页
分页插件的基本原理是使用Mybatis提供的插件接口,实现自定义插件,在插件的拦截方法内拦截
待执行的sql,然后重写sql,根据dialect方言,添加对应的物理分页语句和物理分页参数
6、Mybatis是如何将sql执行结果封装为目标对象并返回的?都有哪些映射形式?
- 第一种是使用标签,一个一个的定义数据库列名和对象属性名之间的映射关系
- 第二种是使用sql列的别名功能,将列的别名书写为对象属性名。
当有了列名和属性名的映射关系之后,Mybatis通过反射创建对象,同时使用反射给对象的属性逐一赋
值并返回,那些找不到映射关系的属性,是无法完成赋值的。
7、 如何执行批量插入?
(Mybatis-Plus中还提供了在XML中人添加MP 框架使用savebatch以及InsertBatchSomeColumn)
- 在SQL语句中使用foreach元素 (将所有插入语句封装成一个大的SQL语句)
- sqlsession sqlsession = sqlsessionfactory.opensession(executortype.batch); 使用executortype.batch
8、Xml映射文件中,除了常见的select|insert|updae|delete标签之外,还有哪些标签?
- resultType/resultMap:用于指定返回结果的类型
- parameterType:用于指定输入参数的类型
- include:用于将其他的SQL片段引入当前的SQL语句中,可以使代码更加模块化和复用
- Set:在update语句中设置要更新的字段和值
- if/choose/when/otherwise:编写动态SQL,根据条件判断生成不同的SQL语句
- trim/where/set:用于在动态SQL中去除多余的空格和逗号
- foreach:处理集合类型的参数
- bind:用于将一个Ognl表达式的结果绑定到一个变量上,方便后续使用
- sql:用于定义可重用的SQL片段,可以在其他地方引用。
9、MyBatis实现一对一有几种方式?具体怎么操作的?
有联合查询和嵌套查询,
联合查询是几个表联合查询,只查询一次, 通过在resultMap里面配置association节点配置一对一的类就可以完成;
嵌套查询是先查一个表,根据这个表里面的结果的 外键id,去再另外一个表里面查询数据,也是通过association配置,但另外一个表的查询通过select属性配置。
10、Mybatis是否支持延迟加载?如果支持,它的实现原理是什么?
Mybatis仅支持association关联对象(一对一)和collection关联集合对象(一对多)的延迟加载
原理:使用CGLIB创建目标对象的代理对象。当调用目标方法时,进入拦截器方法,比如调
用a.getB().getName(),拦截器invoke()方法发现a.getB()是null值,那么就会单独发送事先保存好的
查询关联B对象的sql,把B查询上来,然后调用a.setB(b),于是a的对象b属性就有值了,接着完成
a.getB().getName()方法的调用。这就是延迟加载的基本原理。
11、说说Mybatis的缓存机制:
一级缓存localCache:
如果是相同的 SQL 语句,会优先命中一级缓存,避免直接对数据库进行查询,提高性能。
每个 SqlSession 中持有了 Executor,每个 Executor 中有一个 LocalCache。当用户发起查询时,
MyBatis 根据当前执行的语句生成 MappedStatement,在 Local Cache 进行查询,||如果缓存命中
的话,直接返回结果给用户,||如果缓存没有命中的话,查询数据库,结果写入 Local Cache,最后
返回结果给用户。
- 一级缓存的生命周期和 SqlSession 一致。
- 内部设计是一个没有容量限定的 HashMap,在缓存的功能性上有所欠缺
- 最大范围是 SqlSession 内部,有多个 SqlSession 或者分布式的环境下,数据库写操作会引起脏数据,建议设定缓存级别为 Statement。
二级缓存:
如果多个 SqlSession之间需要共享缓存,则需要使用到二级缓存
开启二级缓存后,会使用 CachingExecutor 装饰Executor,进入一级缓存的查询流程前,先在 CachingExecutor 进行二级缓存的查询
-
实现了 SqlSession 之间缓存数据的共享,同时粒度更加细,能够到 namespace 级别
-
MyBatis 在多表查询时,极大可能会出现脏数据,有设计上的缺陷,安全使用二级缓存的条件比较苛刻
-
默认的 MyBatis Cache 实现都是基于本地的,分布式环境下必然会出现读取到脏数据,需要使用集中式缓存将 MyBatis 的 Cache 接口实现,有一定的开发成本,直接使用 Redis、Memcached 等分布式缓存可能成本更低,安全性也更高
12、JDBC 编程有哪些步骤?
1.装载相应数据库的 JDBC 驱动并进行初始化:
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
- 单例模式:LogFactory和ErrorContest
- 代理模式:Mybatis核心实现,MapperProxy,ConnectionLogger,executor.loader包使用CGLIB达到延迟加载效果等
- 工厂模式:SqlSessionFactory、ObjectFactory、MapperProxyFactory
- 迭代器模式:PropertyTokenizer
- 装饰者模式:Cache包中的decorators子包
- 模板方法模块:BaseExecutor和SimpleExecutor和BaseTypeHandler
- 组合模式:SqlNode和各个子类ChooseSqlNode
14、MyBatis 中比如 UserMapper.java 是接口,为什么没有实现类还能调用?
使用JDK动态代理+MapperProxy。本质上调用的是MapperProxy的invoke方法
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix