Mybatis 基础架构
- Mybatis 的基础架构主要分三层,如下图所示:
- 各层主要功能简述:
(1)基础支持层:
- 类型转换模块:主要是进行JDBC类型和Java类型之间的转换
- 日志模块:可以集成其他的第三方日志框架
- 资源加载模块:资源加载模块主要是对类加载器进行封装,确定类加载器的使用顺序,并提供了加载 类文件以及其他资源文件的功能
- 解析器模块:解析器模块的主要提供了两个功能 个功能是对 XPath 进行封装,为 MyBatis 初始 化时解析 mybatis-config.xml 配置文件以及映射配置文件提供支持;另一个功能是为处理动态SQL 语句中的占位符提供支持。
(2)核心处理层处理数据流程:
(3)接口层: 接口层相对简单,其核心是 SqlSession 接口,该接口中定义了MyBatis 暴露给应用程序调 用的 API ,也就是上层应用与 MyBatis 交互的桥梁。接口层在接收到调用请求时,会调用核心 处理层的相应模块来完成具体的数据库操作。
Mybatis 基础问答
- 使用$和#的区别:
- {}是预编译处理,${}是字符串替换。
- Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值;使用#{}可以有效的防止SQL注入,提高系统安全性。
- Mybatis在处理${}时,仅仅把${}替换成变量的值。
- Mybatis中使用多个参数:
- 第一种: 使用 arg0 , arg1(以此类推,不建议使用,容易弄混参数)
- 第二种: 使用 param注解
- 获取自增Id的配置方式
- 模糊查询的方法
- 第一种:字符串拼接:就是将要查询的关键字keyword,在代码中拼接好要查询的格式,如%keyword%,然后直接作为参数传入mapper.xml的映射文件中
- 第二种:使用CONCAT()函数(可以防SQL注入)
- 第三种:Mybatis的bind bind 标签可以使用 OGNL 表达式创建一个变量井将其绑定到上下文中。bind 标签的两个属性都是必选项
- 批量插入操作方式
- 第一种:普通for循环插入
- 第二种:mybatis BATCH模式插入(Mybatis一共有三种模式,Batch为批量操作),该方式有事务控制。
- 第三种:动态sql foreach方式插入(无事务控制)
经插入100万条数据测试后,效率最好为动态sql foreach循环。
- mybatis 字段命名方式:
-
数据库列名的命名规则:
(1)实体类与数据库列名相等
(2)符合驼峰命名规则,例如 cityId 对应city_id,必须在配置文件中开启: (开启驼峰,开启后,只要数据库字段和对象属性名字母相同,无论中间加多少下划线都可以识别)
-
实现实体类中字段名与数据库字段映射成功的方案
(1)打开驼峰式命名配置,或者不开,数据库列和字段名全一致。
(2)在select语句执行的时候指定别名(AS)
(3)使用resultMap 进行一一对应
- 分页
-
分页一般分有两种方式:
1、物理分页:即使用数据库数据库分页的方式,如mysql的limit。
2、逻辑分页:先查询出所有数据到内存中,再根据游标从内存中截取对应的数据,如mybatis 的 RowBounds,这样效率十分低,数据量大的时候会造成内存溢出。
MYbatis中的逻辑分页:
- Mybatis 中的分页常使用Github上面的插件PageHelper去进行分页(实例项目后面会上传GitHub)
- Mybatis的一级缓存
- mybatis的一级缓存是sqlsession级别的缓存,sqlsession只能访问自己的一级缓存的数据,mybatis默认是支持一级缓存的,不需要任何配置即可使用。
- 同一个sqlsession再次发出相同的sql,就从缓存中取不走数据库。如果两次中间出现commit操作(修改、添加、删除),本sqlsession中的一级缓存区域全部清空,下次再去缓存中查询不到所以要从数据库查询,从数据库查询到再写入缓存。
- mybatis和spring整合后进行mapper代理开发,不支持一级缓存,mybatis和spring整合,spring按照mapper的模板去生成mapper代理对象,模板中在最后统一关闭sqlsession (mybatis与spring整合一级缓存失败的原因: 1.mybatis的一级缓存生效的范围是sqlsession,是为了在sqlsession没有关闭时,业务需要重复查询相同数据使用的。一旦sqlsession关闭,则由这个sqlsession缓存的数据将会被清空。 2.spring对mybatis的sqlsession的使用是由template控制的,sqlsession又被spring当作resource放在当前线程的上下文里(threadlocal),spring通过mybatis调用数据库的过程如下:
- Mybatis 中的Mapper接口中的方法可以重载吗?
接口的权限名就是Mapper对应的XML文件中namespace中的值,就是映射文件中MappedStatement的id值。Mapper接口是没有实现类的,当调用接口方法时,接口全限名+方法名拼接字符串作为key值,可唯一定位一个MappedStatement,因为根据的是接口权限名+方法名去查找,所以不能重载。Dao接口的工作原理是JDK动态代理,Mybatis运行时会使用JDK动态代理为Dao接口生成代理proxy对象,代理对象proxy会拦截接口方法,转而执行MappedStatement所代表的sql,然后将sql执行结果返回。
Mybatis 与 Hibernate的对比
- 上手的难易程度,Mybatis来说比较容易掌握,因为其更贴近数据库,Hibernate则更注重对象与对象之间的关系,要设计好这些关系并不简单。
- 优化的难易程度,由于Hibernate将对象之间通过配置去表示,优化起来要对Hibernate映射之间的配置十分熟悉,较难优化,Mybatis则只需对sql语句进行调优即可。
- 数据库无关性,Hibernate可以轻松的迁移至不同类型的数据库,只需做细微的修改即可,Mybatis则不行,在某些情况下可能需要进行重写sql语句。