1、谈谈 MyBatis 和 JPA 的区别

  1. ORM 映射不同:MyBatis 是半自动的 ORM 框架,提供数据库与结果集的映射;JPA(默认采用 Hibernate 实现)是全自动的 ORM 框架,提供对象与数据库的映射。
  2. 可移植性不同:JPA 通过它强大的映射结构和 HQL 语言,大大降低了对象与数据库的耦合性;MyBatis 由于需要写 SQL,因此与数据库的耦合性直接取决于 SQL 的写法,如果 SQL 不具备通用性而用了很多数据库的特性 SQL 的话,移植性就会降低很多,移植时成本很高。
  3. 日志系统的完整性不同:JPA 日志系统非常健全、涉及广泛,包括:SQL 记录、关系异常、优化警告、缓存提示、脏数据警告等;MyBatis 除了基本的记录功能外,日志功能薄弱很多。
  4. SQL优化上的区别:由于 Mybatis 的 SQL 都是写在 XML 里,因此优化 SQL 比 Hibernate 方便很多。而Hibernate 的 SQL 很多都是自动生成的,无法直接维护 SQL。虽有 HQL ,但功能还是不及 SQL 强大,见到报表等复杂需求时 HQL 就无能为力,也就是说 HQL 是有局限的 Hhibernate 虽然也支持原生 SQL ,但开发模式上却与 ORM 不同,需要转换思维,因此使用上不是非常方便。总之写 SQL 的灵活度上 Hibernate 不及Mybatis。

    2、MyBatis输入输出支持的类型有哪些?

    parameterType:
    MyBatis 支持多种输入输出类型,包括:

  5. 简单的类型,如整数、小数、字符串等;

  6. 集合类型,如Map等;
  7. 自定义的JavaBean。

其中,简单的类型,其数值直接映射到参数上。对于Map或JavaBean则将其属性按照名称映射到参数上。

3、MyBatis里如何实现一对多关联查询?

一对多映射有两种配置方式,都是使用collection标签实现的。在此之前,为了能够存储一对多的数据,需要在主表对应的实体类中增加集合属性,用于封装子表对应的实体类。
嵌套查询:

  1. 通过 select 标签定义查询主表的SQL,返回结果通过 reusltMap 进行映射。
  2. 在 resultMap 中,除了映射主表属性,还要通过 collection 标签映射子表属性,该标签需包含如下内容:
    • 通过property属性指定子表属性名;
    • 通过javaType属性指定封装子表属性的集合类型;
    • 通过ofType属性指定子表的实体类型;
    • 通过select属性指定查询子表所依赖的SQL,这个SQL需单独定义,内部包含查询子表的语句。

嵌套结果:

  1. 通过select标签定义关联查询主表和子表的SQL,返回结果通过resultMap进行映射。
  2. 在resultMap中,除了映射主表属性,还要通过collection标签映射子表属性,该标签需包含如下内容:
    • 通过property属性指定子表属性名;
    • 通过ofType属性指定子表的实体类型;
    • 通过result子标签定义子表字段和属性的映射关系。

      4、MyBatis中的 $ 和 # 有什么区别?

      使用 # 设置参数时,MyBatis 会创建预编译的SQL语句
  • 然后在执行 SQL 时 MyBatis 会为预编译SQL中的占位符(?)赋值。预编译的SQL语句执行效率高,并且可以防止注入攻击。

使用 $ 设置参数时,MyBatis只是创建普通的SQL语句

  • 然后在执行 SQL 语句时 MyBatis 将参数直接拼入到SQL里。这种方式在效率、安全性上均不如前者,但是可以解决一些特殊情况下的问题。例如,在一些动态表格(根据不同的条件产生不同的动态列)中,我们要传递SQL的列名,根据某些列进行排序,或者传递列名给SQL都是比较常见的场景,这就无法使用预编译的方式了。

    5、既然不安全为什么还需要,什么时候会用到它?

    它可以解决一些特殊情况下的问题。例如,在一些动态表格(根据不同的条件产生不同的动态列)中,我们要传递SQL的列名,根据某些列进行排序,或者传递列名给SQL都是比较常见的场景,这就无法使用预编译的方式了。

    6、MyBatis 的 xml 文件和 Mapper 接口是怎么绑定的?

    是通过 xml 文件中, 根标签的 namespace 属性进行绑定的,即 namespace 属性的值需要配置成接口的全限定名称,MyBatis 内部就会通过这个值将这个接口与这个 xm l关联起来。

    7、MyBatis分页和自己写的分页哪个效率高?

    自己写的分页效率高。
    在 MyBatis 中,我们可以通过分页插件实现分页,也可以通过分页 SQL 自己实现分页。
    其中,分页插件的原理是,拦截查询 SQL ,在这个 SQL 基础上自动为其添加 limit 分页条件。它会大大的提高开发的效率,但是无法对分页语句做出有针对性的优化,比如分页偏移量很大的情况,而这些在自己写的分页SQL里却是可以灵活实现的。

    8、了解 MyBatis 缓存机制吗?

    MyBatis的缓存分为一级缓存和二级缓存。
    一级缓存:
    一级缓存也叫本地缓存,它默认会启用,并且不能关闭一级缓存存在于SqlSession的生命周期中,即它是SqlSession 级别的缓存。在同一个 SqlSession 中查询时,MyBatis 会把执行的方法和参数通过算法生成缓存的键值,将键值和查询结果存入一个 Map 对象中。如果同一个 SqlSession 中执行的方法和参数完全一致,那么通过算法会生成相同的键值,当 Map 缓存对象中己经存在该键值时,则会返回缓存中的对象。
    二级缓存:
    二级缓存存在于 SqlSessionFactory 的生命周期中,即它是SqlSessionFactory级别的缓存。
    若想使用二级缓存,需要在如下两处进行配置。
    在 MyBatis 的全局配置 settings 中有一个参数 cacheEnabled,这个参数是二级缓存的全局开关,默认值是 true ,初始状态为启用状态。
    MyBatis 的二级缓存是和命名空间绑定的,即二级缓存需要配置在 Mapper.xml 映射文件中。在保证二级缓存的全局配置开启的情况下,给 Mapper.xml 开启二级缓存只需要在 Mapper. xml 中添加如下代码:

    1. <cache></cache>

    二级缓存具有如下效果:

  • 映射语句文件中的所有 SELECT 语句将会被缓存。

  • 映射语句文件中的所有时INSERT 、UPDATE 、DELETE 语句会刷新缓存。
  • 缓存会使用 Least Rece ntly U sed ( LRU ,最近最少使用的)算法来收回。
  • 根据时间表(如 no Flush Int erv al ,没有刷新间隔),缓存不会以任何时间顺序来刷新。
  • 缓存会存储集合或对象(无论查询方法返回什么类型的值)的 1024 个引用。
  • 缓存会被视为 read/write(可读/可写)的,意味着对象检索不是共享的,而且可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。