Mybatis-----基础篇

272 阅读5分钟

Mybatis 基础架构

  1. Mybatis 的基础架构主要分三层,如下图所示:

  1. 各层主要功能简述:

(1)基础支持层

  • 类型转换模块:主要是进行JDBC类型和Java类型之间的转换
  • 日志模块:可以集成其他的第三方日志框架
  • 资源加载模块:资源加载模块主要是对类加载器进行封装,确定类加载器的使用顺序,并提供了加载 类文件以及其他资源文件的功能
  • 解析器模块:解析器模块的主要提供了两个功能 个功能是对 XPath 进行封装,为 MyBatis 初始 化时解析 mybatis-config.xml 配置文件以及映射配置文件提供支持;另一个功能是为处理动态SQL 语句中的占位符提供支持

(2)核心处理层处理数据流程:

(3)接口层: 接口层相对简单,其核心是 SqlSession 接口,该接口中定义了MyBatis 暴露给应用程序调 用的 API ,也就是上层应用与 MyBatis 交互的桥梁。接口层在接收到调用请求时,会调用核心 处理层的相应模块来完成具体的数据库操作。

Mybatis 基础问答

  1. 使用$和#的区别:
  • {}是预编译处理,${}是字符串替换。
  • Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值;使用#{}可以有效的防止SQL注入,提高系统安全性。
  • Mybatis在处理${}时,仅仅把${}替换成变量的值。
  1. Mybatis中使用多个参数:
  • 第一种: 使用 arg0 , arg1(以此类推,不建议使用,容易弄混参数)

  • 第二种: 使用 param注解
  1. 获取自增Id的配置方式

  1. 模糊查询的方法
  • 第一种:字符串拼接:就是将要查询的关键字keyword,在代码中拼接好要查询的格式,如%keyword%,然后直接作为参数传入mapper.xml的映射文件中

  • 第二种:使用CONCAT()函数(可以防SQL注入)

  • 第三种:Mybatis的bind bind 标签可以使用 OGNL 表达式创建一个变量井将其绑定到上下文中。bind 标签的两个属性都是必选项

  1. 批量插入操作方式
  • 第一种:普通for循环插入

  • 第二种:mybatis BATCH模式插入(Mybatis一共有三种模式,Batch为批量操作),该方式有事务控制。

  • 第三种:动态sql foreach方式插入(无事务控制)

经插入100万条数据测试后,效率最好为动态sql foreach循环。

  1. mybatis 字段命名方式:
  • 数据库列名的命名规则:

    (1)实体类与数据库列名相等

    (2)符合驼峰命名规则,例如 cityId 对应city_id,必须在配置文件中开启: (开启驼峰,开启后,只要数据库字段和对象属性名字母相同,无论中间加多少下划线都可以识别

  • 实现实体类中字段名与数据库字段映射成功的方案

    (1)打开驼峰式命名配置,或者不开,数据库列和字段名全一致。

    (2)在select语句执行的时候指定别名(AS)

    (3)使用resultMap 进行一一对应

  1. 分页
  • 分页一般分有两种方式:

    1、物理分页:即使用数据库数据库分页的方式,如mysql的limit。

    2、逻辑分页:先查询出所有数据到内存中,再根据游标从内存中截取对应的数据,如mybatis 的 RowBounds,这样效率十分低,数据量大的时候会造成内存溢出。

    MYbatis中的逻辑分页:

  • Mybatis 中的分页常使用Github上面的插件PageHelper去进行分页(实例项目后面会上传GitHub)
  1. 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调用数据库的过程如下:

通过以上步骤后发现,同一线程里面两次查询同一数据所使用的sqlsession是不相同的,所以,给人的印象就是结合spring后,mybatis的一级缓存失效了。 )

  1. Mybatis 中的Mapper接口中的方法可以重载吗?

接口的权限名就是Mapper对应的XML文件中namespace中的值,就是映射文件中MappedStatement的id值。Mapper接口是没有实现类的,当调用接口方法时,接口全限名+方法名拼接字符串作为key值,可唯一定位一个MappedStatement,因为根据的是接口权限名+方法名去查找,所以不能重载。Dao接口的工作原理是JDK动态代理,Mybatis运行时会使用JDK动态代理为Dao接口生成代理proxy对象,代理对象proxy会拦截接口方法,转而执行MappedStatement所代表的sql,然后将sql执行结果返回。

Mybatis 与 Hibernate的对比

  1. 上手的难易程度,Mybatis来说比较容易掌握,因为其更贴近数据库,Hibernate则更注重对象与对象之间的关系,要设计好这些关系并不简单。
  2. 优化的难易程度,由于Hibernate将对象之间通过配置去表示,优化起来要对Hibernate映射之间的配置十分熟悉,较难优化,Mybatis则只需对sql语句进行调优即可。
  3. 数据库无关性,Hibernate可以轻松的迁移至不同类型的数据库,只需做细微的修改即可,Mybatis则不行,在某些情况下可能需要进行重写sql语句。