• 1. 讲师:佟刚 新浪微博:尚硅谷-佟刚MyBatis
  • 2. 什么是 MyBatisMyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架。 MyBatis 避免了几乎所有的 JDBC 代码和手工设置参数以及抽取结果集。 MyBatis 使用简单的 XML 或 注解 来配置和映射,将 接口 和 Java 的 POJOs(Plain Old Java Objects, 普通的 Java对象)映射成数据库中的记录。
  • 3. HelloWorld1.加入 jar 包 2. 新建持久化类及数据表 3.加入 MyBatis 配置文件: mybatis-config.xml 4.加入 MyBatis 映射文件 5.通过 MyBatis API 操作数据表
  • 4. 新建持久化类及数据表
  • 5. MyBatis 配置文件
  • 6. MyBatis 映射文件
  • 7. MyBatis API 操作数据表String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); //1. 创建 SqlSessionFactory 对象 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //2. 获取 Session 对象 SqlSession session = sqlSessionFactory.openSession(); //3. 执行查询 Customer customer = session.selectOne("com.atguigu.mybatis.example.CustomerMapper.selectCustomer", 1); System.out.println(customer); //4. 关闭 Session session.close();
  • 8. 使用注解映射定义 Mapper 接口 在 MyBatis 配置文件中加入 Mapper Class 使用:
  • 9. MyBatis 配置文件MyBatis 配置文件包含了对 MyBatis 系统的核心设置,例如:数据源、事务管理器 MyBatis 配置文件文档的顶层结构:
  • 10. properties属性都是可外部配置的: 链接数据库的基本信息为:
  • 11. Settingssettings 中的设置非常关键:它们会改变 MyBatis 运行的行为
  • 12. typeAliases类型别名是为 Java 类型命名的一个短的名字。用来减少类完全限定名的冗余
  • 13. typeAliases也可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean 每一个在包 com.atguigu.mybatis.example 中的 Java Bean,在没有注解的情况下,会使用 Bean 的首字母小写的非限定类名来作为它的别名
  • 14. typeAliasesMyBatis 已经为普通的 Java 类型内建了许多相应的类型别名。它们都是大小写不敏感的。
  • 15. 配置环境(environments)MyBatis 可以配置成适应多种环境,这种机制有助于将 SQL 映射应用于多种数据库之中。例如,开发、测试和生产环境或许需要有不同的配置 注意:尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择其一。所以,如果你想连接两个数据库,就需要创建两个 SqlSessionFactory 实例,每个数据库对应一个。 关键配置项: 默认的环境 ID(比如:default=”development”)。 每个 environment 元素定义的环境 ID(比如:id=”development”)。 事务管理器的配置(比如:type=”JDBC”)。 数据源的配置(比如:type=”POOLED”) 默认的环境和环境 ID 是自我解释的。可以使用喜欢的名称来命名,只要确定默认的要匹配其中之一。
  • 16. 事务管理器(transactionManager)在 MyBatis 中有两种类型的事务管理器: JDBC:这个配置就是直接使用了 JDBC 的提交和回滚设置,它依赖于从数据源得到的连接来管理事务。 MANAGED:这个配置几乎没做什么。它从来不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。默认情况下它会关闭连接,可以将 closeConnection 属性设置为 false 来阻止它默认的关闭行为 如果使用 Spring + MyBatis,则没有必要配置事务管理器,因为 Spring 会使用自带的事务管理器来覆盖前面的配置
  • 17. 数据源(dataSource)dataSource 元素使用基本的 JDBC 数据源接口来配置 JDBC 连接对象的资源。 有三种内建的数据源类型(也就是 type=”???”): 无连接池(UNPOOLED) 有连接池(POOLED) JNDI
  • 18. 无连接池(UNPOOLED)这个数据源的实现是每次被请求时简单打开和关闭连接。 UNPOOLED 类型的数据源仅仅需要配置以下 5 种属性: driver – 这是 JDBC 驱动的 Java 类的完全限定名(如果你的驱动包含,它也不是数据源类)。 url – 这是数据库的 JDBC URL 地址。 username – 登录数据库的用户名。 password – 登录数据库的密码。 defaultTransactionIsolationLevel – 默认的连接事务隔离级别。 作为可选项,你也可以传递 properties 给数据库驱动。要这样做,属性的前缀以“driver.”开头,例如:driver.encoding=UTF8
  • 19. 有连接池(POOLED)这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来,避免了创建新的连接实例时所必需的初始化和认证时间。 除了上述无连接池(UNPOOLED)的属性外,会有更多属性用来配置有连接池(POOLED)的数据源: poolMaximumActiveConnections – 在任意时间可以存在的活动(也就是正在使用)连接数量,默认值:10 poolMaximumIdleConnections – 任意时间可能存在的空闲连接数。 poolMaximumCheckoutTime – 在被强制返回之前,池中连接被检出(checked out)时间,默认值:20000 毫秒(即 20 秒) poolTimeToWait – 这是一个低层设置,如果获取连接花费的相当长的时间,它会给连接池打印日志并重新尝试获取一个连接的机会(避免在误配置的情况下一直安静的失败),默认值:20000 毫秒(即 20 秒)。 poolPingQuery – 发送到数据的侦测查询,用来检验连接是否处在正常工作秩序中并准备接受请求。默认是“NO PING QUERY SET”,这会导致多数数据库驱动失败时带有一个恰当的错误消息。 poolPingEnabled – 是否启用侦测查询。若开启,也必须使用一个可执行的 SQL 语句设置 poolPingQuery 属性(最好是一个非常快的 SQL),默认值:false。 poolPingConnectionsNotUsedFor – 配置 poolPingQuery 的使用频度。这可以被设置成匹配标准的数据库连接超时时间,来避免不必要的侦测,默认值:0(即所有连接每一时刻都被侦测 — 当然仅当 poolPingEnabled 为 true 时适用)。
  • 20. 任何第三方数据源需要实现这个接口: DataSourceFactory UnpooledDataSourceFactory 可被用作父类来构建新的数据源适配器
  • 21. databaseIdProviderMyBatis 可以根据不同的数据库厂商执行不同的语句,这种多厂商的支持是基于映射语句中的 databaseId 属性。 MyBatis 会加载不带 databaseId 属性和带有匹配当前数据库 databaseId 属性的所有语句。如果同时找到带有 databaseId 和不带 databaseId 的相同语句,则后者会被舍弃。为支持多厂商特性只要在 mybatis-config.xml 文件中加入 databaseIdProvider  即可 DB_VENDOR 会通过 DatabaseMetaData#getDatabaseProductName() 返回的字符串进行设置。由于通常情况下这个字符串都非常长而且相同产品的不同版本会返回不同的值,所以最好通过设置属性别名来使其变短
  • 22. 映射器(mappers)使用相对于类路径的资源引用,或类名和包名等。例如:
  • 23. Mapper XML 文件MyBatis 的真正强大在于它的映射语句。 SQL 映射文件的顶级元素: insert – 映射插入语句 update – 映射更新语句 delete – 映射删除语句 select – 映射查询语句 sql – 可被其他语句引用的可重用语句块。 resultMap – 用来描述如何从数据库结果集中来加载对象。 cache – 给定命名空间的缓存配置。 cache-ref – 其他命名空间缓存配置的引用。
  • 24. select示例: select 元素有很多属性,来决定每条语句的作用细节:
  • 25. (本页无文本内容)
  • 26. databaseId 属性
  • 27. insert, update 和 delete
  • 28. insert, update 和 delete
  • 29. 主键生成方式若数据库支持自动生成主键的字段(比如 MySQL 和 SQL Server),则可以设置 useGeneratedKeys=”true”,然后再把 keyProperty 设置到目标属性上。
  • 30. 主键生成方式而对于不支持自增型主键的数据库(例如 Oracle),则可以使用 selectKey 子元素:selectKey 元素将会首先运行,id 会被设置,然后插入语句会被调用
  • 31. selectKey 
  • 32. SQL该元素可以被用来定义可重用的 SQL 代码段,可以包含在其他语句中
  • 33. 参数(Parameters)参数也可以指定一个特殊的数据类型: javaType 通常可以从参数对象中来去确定 如果 null 被当作值来传递,对于所有可能为空的列,jdbcType 需要被设置 对于数值类型,还可以设置小数点后保留的位数: mode 属性允许指定 IN,OUT 或 INOUT 参数。如果参数为 OUT 或 INOUT,参数对象属性的真实值将会被改变,就像在获取输出参数时所期望的那样。 实际上通常被设置的是:可能为空的列名指定 jdbcType
  • 34. Result Maps如果列名没有精确匹配, 可以在列名上使用 select 字句的别名(一个 基本的 SQL 特性)来匹配标签。比如:
  • 35. 外部 resultMap
  • 36. resultMapconstructor - 类在实例化时, 用来注入结果到构造方法中 idArg - ID 参数; 标记结果作为 ID 可以帮助提高整体效能 arg - 注入到构造方法的一个普通结果 id – 一个 ID 结果; 标记结果作为 ID 可以帮助提高整体效能 result – 注入到字段或 JavaBean 属性的普通结果 association – 一个复杂的类型关联;许多结果将包成这种类型 嵌入结果映射 – 结果映射自身的关联,或者参考一个 collection – 复杂类型的集 嵌入结果映射 – 结果映射自身的集,或者参考一个 discriminator – 使用结果值来决定使用哪个结果映射 case – 基于某些值的结果映射 嵌入结果映射 – 这种情形结果也映射它本身,因此可以包含很多相 同的元素,或者它可以参照一个外部的结果映射。
  • 37. constructor
  • 38. id & resultid 和 result 映射一个单独列的值到简单数据类型(字符串,整型,双精度浮点数,日期等)的属性或字段。
  • 39. 关联关联元素处理“有一个”类型的关系。比如:一个订单对应着一个客户。 MyBatis 在这方面会有两种不同的 方式: 嵌套查询:通过执行另外一个 SQL 映射语句来返回预期的复杂类型。 嵌套结果:使用嵌套结果映射来处理重复的联合结果的子集。
  • 40. 关联的嵌套查询属性如下:
  • 41. 关联的嵌套查询
  • 42. 延迟加载Mybatis 配置文件中添加如下配置: 加入 jar 包: asm-3.3.1.jar cglib-2.2.2.jar javassist-3.17.1-GA.jar
  • 43. N + 1 问题N+1 查询问题:执行了一个单独的 SQL 语句来获取结果列表(就是“+1”)。对返回的每条记录, 执行了一个查询语句来加载每一个细节(就是“N”)。N + 1 问题会导致成百上千的 SQL 语句被执行。 MyBatis 能延迟加载这样的查询:可以分散这些语句同时运行的消耗。然而, 如果加载一个列表, 之后迅速迭代来访问嵌套的数据, 会调用所有的延迟加载, 这样的行为可能是很糟糕的。
  • 44. 关联的嵌套结果
  • 45. 关联的嵌套结果外部结果映射元素来映射关联。使得 Customer 结果映射可以重用。然而, 如果不需要重用它的话, 可以嵌套结果映射:
  • 46. columnPrefix
  • 47. 集合集合元素的作用几乎和关联是相同的。
  • 48. 集合的嵌套查询
  • 49. 集合的嵌套结果
  • 50. 自动映射在简单的场景下,MyBatis可以完成自动映射查询结果。 如果遇到复杂的场景,需要构建一个result map。 也可以混合使用这两种策略。 当自动映射查询结果时,MyBatis 会获取 SQL 返回的列名并在 java 类中查找相同名字的属性(忽略大小写)。 即:如果 Mybatis 发现了 ID 列和 id 属性,Mybatis 会将 ID 的值赋给 id 通常数据库列使用大写单词命名,单词间用下划线分隔;而 java 属性一般遵循驼峰命名法。 为了在这两种命名方式之间启用自动映射,需要将 mapUnderscoreToCamelCase 设置为 true。
  • 51. MyBatis 缓存MyBatis 支持声明式数据缓存。当一条 SQL 语句被标记为“可缓存”后,首次执行它时从数据库获取的所有数据会被存储在一段高速缓存中,今后执行这条语句时就会从高速缓存中读取结果,而不是再次查询数据库。MyBatis提供了默认下基于 Java HashMap 的缓存实现,以及用于与OSCache、Ehcache、Hazelcast 和 Memcached 连接的默认连接器。 MyBatis缓存有两种:一级缓存和二级缓存。 当在某一个作用域 (一级缓存Session/二级缓存Namespaces) 进行了 C/U/D 操作后,默认该作用域下所有 select 中的缓存将被clear。 当执行一条查询SQL时,流程为: 从二级缓存中进行查询 进入一级缓存中查询 执行 JDBC 查询。
  • 52. MyBatis 一级缓存一级缓存(local cache), 即本地缓存, 作用域默认为 Session。当 Session flush 或 close 后, 该 Session 中的所有 Cache 将被清空。 本地缓存不能被关闭, 但可以调用 clearCache() 来清空本地缓存, 或者改变缓存的作用域. 在SELECT语句中配置刷新缓存,如下: 
  • 54. MyBatis 二级缓存要开启二级缓存, 需要在 SQL 映射文件中添加: 的作用: 映射语句文件中的所有 select 语句将会被缓存。 映射语句文件中的所有 insert,update 和 delete 语句会刷新缓存。 缓存会使用 Least Recently Used(LRU, 最近最少使用的)算法来收回。 根据时间表(比如 no Flush Interval,没有刷新间隔), 缓存不会以任何时间顺序来刷新。 缓存会存储列表集合或对象(无论查询方法返回什么)的 1024 个引用。 缓存会为 read/write(可读/可写)的缓存, 即对象检索不是共享的, 而且可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。 所有的这些属性都可以通过缓存元素的属性来修改
  • 55. 缓存策略可用的收回策略有: LRU(默认) – 最近最少使用的: 移除最长时间不被使用的对象。 FIFO – 先进先出: 按对象进入缓存的顺序来移除它们。 SOFT – 软引用: 移除基于垃圾回收器状态和软引用规则的对象。 WEAK – 弱引用: 更积极地移除基于垃圾收集器状态和弱引用规则的对象。
  • 56. 缓存属性缓存属性: flushInterval(刷新间隔)可以被设置为任意的正整数, 而且它们代表一个合理的毫秒形式的时间段。默认情况下没有刷新间隔, 缓存仅仅调用语句时刷新。 size(引用数目)可以被设置为任意正整数, 默认值是 1024。 readOnly(只读)属性可以被设置为 true 或 false。只读的缓存会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。可读写的缓存会返回缓存对象的拷贝(通过序列化) 。这会慢一些, 但是安全, 默认是 false。
  • 57. 使用自定义缓存可以通过实现自己的缓存或为其他第三方缓存方案创建适配器来完全覆盖缓存行为。 type 属 性指定的 类必须实现 org.mybatis.cache.Cache 接口。
  • 58. 使用 EhCache加入 jar 包: ehcache-core-2.6.8.jar mybatis-ehcache-1.0.3.jar slf4j-api-1.6.1.jar 在 XxxMapper.xml 文件中配置使用 Ehcahce:
  • 59. 参照缓存若想在命名空间中共享相同的缓存配置和实例。可以使用 cache-ref 元素来引用另外一个缓存。
  • 60. 动态 SQL动态 SQL:解决 SQL 拼接问题 MyBatis 采用功能强大的基于 OGNL 表达式来消除其他元素 if choose (when, otherwise) trim (where, set) foreach
  • 61. if
  • 62. choose, when, otherwise
  • 63. wherewhere 元素知道只有在一个以上的 if 条件有值的情况下才去插入“WHERE”子句。而且,若最后的内容是“AND”或“OR”开头的,where 元素也知道如何将他们去除
  • 64. trimprefixOverrides 属性会忽略通过管道分隔的文本序列(注意:空格也是必要的)。它带来的结果就是所有在 prefixOverrides 属性中指定的内容将被移除,并且插入 prefix 属性中指定的内容 和 where 元素等价的自定义 trim 元素为:
  • 65. setset 元素可以被用于动态包含需要更新的列,而舍去其他的 set 元素会动态前置 SET 关键字,同时也会消除无关的逗号
  • 66. foreach动态 SQL 的另外一个常用的常用操作是需要对一个集合进行遍历,通常是在构建 IN 条件语句的时候 foreach 元素允许指定一个集合,声明集合项和索引变量,并可以指定开闭匹配的字符串以及在迭代之间放置分隔符。 可以将一个 List 实例或者数组作为参数对象传给 MyBatis,MyBatis 会自动将它包装在一个 Map 中并以名称为键。List 实例将会以“list”作为键,而数组实例的键将是“array”
  • 67. bindbind 元素可以从 OGNL 表达式中创建一个变量并将其绑定到上下文
  • 68. Multi-db vendor support若在 mybatis 配置文件中配置了 databaseIdProvider , 则可以使用 “_databaseId”变量,这样就可以根据不同的数据库厂商构建特定的语句
  • 69. openSession 方法默认的 openSession() 方法没有参数,它会创建有如下特性的 SqlSession: 会开启一个事务(也就是不自动提交) 连接对象会从由活动环境配置的数据源实例得到。 事务隔离级别将会使用驱动或数据源的默认设置。 预处理语句不会被复用,也不会批量处理更新。
  • 70. openSession 方法MyBatis 为事务隔离级别调用使用一个 Java 枚举包装器, 称为 TransactionIsolationLevel, 有 5 个级别: NONE,READ_UNCOMMITTED,READ_COMMITTED,REPEA TABLE_READ,SERIALIZA BLE openSession 方法的 ExecutorType 类型的参数,枚举类型: ExecutorType.SIMPLE: 这个执行器类型不做特殊的事情。它为每个语句的执行创建一个新的预处理语句。 ExecutorType.REUSE: 这个执行器类型会复用预处理语句。 ExecutorType.BATCH: 这个执行器会批量执行所有更新语句
  • 71. SqlSession语句执行方法
  • 72. SqlSession语句执行方法:允许限制返回行数的范围 RowBounds 参数会告诉 MyBatis 略过指定数量的记录, 还会限制返回结果的数量。 RowBounds 类有一个构造方法来接收 offset 和 limit。
  • 73. 使用映射器SqlSession 的 insert,update,delete 和 select 方法都很强大, 但没有类型安全(泛型)。 一个更通用的方式来执行映射语句是使用映射器类。 一个映射器类就是一个简单的接口, 其中方法名必须匹配映射语句的 ID。 返回类型必须匹配期望的结果类型。所有常用的类型都被支持, 包括: 原生类型, Map, POJO 和 JavaBean。 映射器接口不需要去实现任何接口或扩展任何类。 只要方法名可以被用来唯一标识对应的映射语句即可。 可以传递多个参数给一个映射器方法。 默认情况下它们将会以它们在参数列表中的位置来命名, 比如:#{param1},#{param2}等。如果想改变参数的名称(只在多参数情况下) ,那么可以在参数上使用@Param(“paramName”)注解。 可以给方法传递一个 RowBounds 实例来限制查询结果。
  • 74. (本页无文本内容)
  • 75. 映射器示例
  • 76. 映射器示例
  • 77. 映射器示例
  • 78. 映射器注解
  • 79. 映射器注解
  • 80. 映射器注解
  • 81. 映射器注解
  • 82. 整合 Spring加入 jar 包:mybatis-spring-1.2.2.jar 配置 SqlSessionFactoryBean:
  • 83. 整合 Spring配置事务管理器 配置扫描的 Mapper 所在的 package:
  • 84. (本页无文本内容)