MyBatis配置详解

MyBatis简介

  MyBatis是一个开源的数据持久层框架,它内部封装了通过JDBC访问数据库的操作,支持普通的SQL查询、存储过程和高级映射,几乎消除了所有的JDBC代码和参数的手工设置以及结果集的检索。MyBatis作为持久层框架,其主要思想是将程序中大量SQL语句剥离出来,配置在配置文件中,实现SQL的灵活配置。这样做的好处是将SQL与程序代码分离,可以在不修改程序代码的情况下,直接在配置文件中修改SQL。Mybatis通过简单的XML或者注解进行配置和原始映射,将实体类和SQL语句之间建立映射关系,是一种半自动化的ORM实现。
  
  接口式编程
    原生: Dao ----> DaoImpl
    mybatis : Mapper —> xxMapper.xml
  SqlSession代表了和数据库的一次会话用完必须关闭
  SqlSession和connection一样,都是非线程安全的,每次使用都应该去获取新的对象
  mapper接口没有实现类,但是mybatis会为这个接口生成一个代理对象
  两个重要的配置文件
    mybatis的全局配置文件,包含数据库连接池信息,事务管理器信息等,系统运行环境
    sql映射文件,保存了每一个sql语句的映射信息
      将sql抽取出来,交给程序员来编写,区别于hibernate的黑箱操作
核心配置文件标签顺序

 
    
    	
    	
    	 
    	 
    	  
    	 
    	 
    		 
    		 
    			 
    		
    	
    	  
    	 
    

properties : 引入外部properties配置文件的内容
   resource : 引入类路径下的资源
   url : 引入网络路径或者磁盘路径下的资源
 settings : 包含很多重要的设置项
   setting : 用来设置每一个设置项
    name : 设置项名
    value : 设置项取值
    如 : 驼峰命名规范映射
 typeAliases : 别名处理器,可以为我们的java类型起别名 别名区分大小写
   typeAlias : 为某个java类型起别名
    type : 指定要起别名的类型全类名,默认别名就是类名小写
    alias : 指定新的别名 一般不设置
   package : 为某个包下的所有类批量起别名
    name : 指定包名(为当前包以及下面所有的后代包的每一个类都起一个默认别名,默认还是类名小写)
  注意 : 如果包下和子包下有两个类名相同的类,这时候会报错,可以使用@Alias注解再类上设置别名
 typeHandlers : 类型处理器
 environments : 环境,mybatis可以配置多种环境 default:指定使用某种环境,可以达到快速切换环境
   environment : 配置一个具体的环境信息 必须有两个标签, id : 代表当前环境的唯一标识
     transactionManager : 事务管理器,只做了解,以后事务都交给spring管理的
      type : 事务管理器的类型
        JDBC(JdbcTransactionFactory) : 使用了JDBC的提交和回滚设置,依赖于从数据源得到的连接来管理事务范围
        MANAGED(ManagedTransactionFactory) : 不提交或回滚一个连接、让容器来管理事务的整个生命周期
        自定义事务管理器 : 实现TransactionFactory接口,type指定为全类名
     dataSource : 数据源
      type : 数据源类型
       UNPOOLED : UnpooledDataSourceFactory 不使用连接池
       POOLED : PooledDataSourceFactory 使用连接池
       JNDI : JndiDataSourceFactory
       自定义数据源 : 实现DataSourceFactory接口,type 全类名
       推荐 : 再定义外部数据源文件的时候 带一个前缀 如: jdbc.driver 防止冲突
 databaseIdProvider : 支持多数据库厂商
   type : DB_VENDOR VendorDatabaseIdProvider
    作用就是得到数据厂商的标识,mybatis就能根据数据厂商标识来执行不同的sql
 mappers : 将sql映射注册到全局配置中
   mapper : 注册一个sql映射
    resource : 引用类路径下的sql映射文件
    url : 引用网络路径下或者磁盘路径下的sql映射文件
    class : 直接引用(注册)接口(写接口的全类名)
     有sql映射文件,映射文件名必须和接口同名,并且放在与接口同一目录下没有sql映射文件,所有的sql都是利用注解写在接口上
   推荐 :
     比较重要的,复杂的Dao接口我们来写sql映射文件
     不重要的,简单的Dao接口,为了开发快速可以使用注解
  package : 批量注册 如果是Maven项目,需要配置静态资源映射
    name : mapper所在包

Mapper配置文件

mapper
  namespace : 名称空间,指定为接口的全类名
  cache : 命名空间的二级缓存配置
  cache-ref : 其他命名空间缓存配置的引用
  select : 映射查询语句
  insert : 映射插入语句
  update: 映射修改语句
  delete : 映射删除语句
  
  insert、update、delete属性设置
    id: 唯一标识符
    parameterType : 要传入语句的参数的完全限定名或别名,这个属性是可选的,因为MyBatis可以通过TypeHandler推断出具体传入语句的参数类型 默认值为unset
    flushCache : true:任何时候只要语句被调用,都会导致本地缓存和二级缓存都会被清空,默认值:true(对应增删改语句)
    timeout : 在抛出异常之前,驱动程序等待数据库返回请求结果的秒数,默认值为unset(依赖驱动)
    useGeneratedKeys :(仅对insert和update有用)这会令Mybatis使用JDBC的getGeneratedKeys方法来取出由数据库内部生成的主键 默认值为false
    keyProperty: 仅对insert和update有用)唯一标识一个属性,mybatis会通过getGeneratedKeys的返回值或者通过insert语句的selectKey子元素设置它的键值,默认unset
    databaseId : 如果配置了databaseIdProvider,mybatis会加载所有的不带databaseId或匹配当前databaseId的语句,如果带或者不带的语句都有,则不带的会被忽略
    
    主键生成方式
      useGeneratedKeys=“true” : 使用自增主键获取主键值策略
      keyProperty : 指定对应的主键属性,也就是mybatis获取到主键值以后,将这个值封装给javaBean的哪个属性
      注意 : Oracle不支持自增 : Oracle使用序列来模拟自增
每次插入的数据的主键是从序列中拿到的值
      selectKey
       keyProperty : selectKey语句结果应该被设置的目标属性
       resultType : 结果的类型,mybatis允许任何简单类型作为主键类型,包括字符串
       order :
        BEFORE: 首先选择主键,设置keyProperty然后执行插入语句
        AFTER: 先执行插入语句,然后是selectKey元素
        
  参数传递
    单个参数: 可以接收基本类型,对象类型,集合类型的值,这种情况,mybatis可直接使用这个参数,不需要经过任何处理
    多个参数: 任意多个参数,都会被封装成一个map
     key: 就是 param1…paramN,或者参数的索引也可以
     value: 传入的参数值
    命名参数: 使用@Param注解为参数起一个名字 如@Param(“id”)
     多个参数会被封装成map
     key: 使用@Param注解指定的值
     value: 参数值
    POJO: 如果多个参数正好是我们业务逻辑的数据模型,我们就可以直接传入pojo
     取值 : #{属性名}
    Map: 如果多个参数不是业务模型中的数据,没有对应的pojo,不经常使用,为了方便,我们可以出传入map
    TO: 如果多个参数不是业务模型中的数据,但是经常要使用,推荐编写一个TO(Transfer Object)数据传输对象
  特殊一点的

public Employee selEmp(@Param("id")Integer id, String lastName);

    取值: id :#{id / param1} lastName:#{param2}

public Employee selEmp(Integer id, Employee emp); // 如果emp加了 @Param("e")  注解

    取值:id:#{param1} lastName:没有加注解#{param2.lastName} 加了注解#{e.lastName}

特别注意 : 如果是Collection(List Set) 类型或者是数组
     也会特殊处理,也是吧传入的list或数组封装在map中
     key: Conllection:conllection List :list 数组 : array

public Employee selEmpById(List ids);

    取出第一个值:#{list[0]}

参数值的获取

#{} :可以获取map中值或者pojo对象属性的值
${} :可以获取map中值或者pojo对象属性的值

区别
    #{}:是以预编译的形式,将参数设置到sql语句中,PreparedStatement防止sql注入
    ${}:取出的值,直接拼接在sql语句中,有安全问题
     大多数情况下,我们去参数的值都应该使用#{}
     原生JDBC不支持占位符的地方我们就可以使用${}进行取值
     如:按照年份 分表拆分

 select * from ${year}_salary where xxx;
 select * from tbl order by ${f_name} ${order};

#{}更丰富的用法
  规定参数的一些规则
    javaType: java类型
    jdbcType: jdbc类型
    mode: 存储过程
    numericScale: 保留几位小数
    resultMap: 结果类型
    typeHandler: 类型处理器
    jabcTypeName
    expression:表达式,未来准备支持的功能
    
  jdbcType通常需要在某种特定的条件下被设置
    在外面数据为null的时候,有些数据库可能不能识别mybatis对null的默认处理,比如Oracle(报错)
    JdbcType OTHER : 无效的类型 : 因为mybatis对所有的null都映射的是原生jdbc里的OTHER类型 oracle不能正确处理
      由于全局配置中: jdbcTypeForNull = OTHER; oracle不支持 两种办法
       1. #{可能为空的字段,jdbcType=NULL}
       2. jdbcTypeForNull = NULL;

 

select属性
  **id:**唯一标识符 用来引用这条语句,需要和接口的方法名一致
  parameterType: 参数类型
  resultType: 返回值类型,别名或者全类名,如果返回的是集合,定义集合中元素的类型,不能和resultMap同时使用
  resultMap: 外部resultMap的命名引用
  flushCache: true:任何时候只要语句被调用,都会导致本地缓存和二级缓存都会被情况默认为false
  useCache: true:将会导致本条语句的结果被二级缓存,默认值:对select元素为true
  timeout: 在抛出异常之前,驱动程序等待数据库返回请求结果的秒数,默认值unset
  databaseId: 如果配置了databaseIdProvider,mybatis会加载所有的不带databaseId或匹配当前databaseId的语句,如果带或者不带的语句都有,则不带的会被忽略
  
 resultMap : 自定义结果集映射
  constructor: 类在实例化时,用来注入结果到构造方法中
    idArg: ID参数,标记结果作为ID可以帮助提高整体性能
    arg: 注入到构造方法的一个普通结果
  id: 一个ID结果,标记结果作为ID可以帮助提高整体性能
  result: 注入到字段或JavaBean属性的普通结果
  association: 定义关联对象的封装规则
    select: 表名当前属性是调用select指定的方法查出的结果
    column: 指定将哪一列的值传递给这个方法
 整个流程: 使用select指定的方法(传入column指定的这列参数的值)查出对象,并封装给property指定的属性
  collection: 定义关联集合类型的属性封装规则
   property: 关联的属性
   ofType: 指定集合里元素类型
   select: 表明当前属性是调用select指定的方法查出结果
   column: 指定将哪一列的值传给这个方法
     column传递 多列{key=value} key取名为接收方法的参数名
  
 动态sql
  动态sql是mybatis强大特性之一,极大的简化我们拼装SQL的操作
  if:判断
   test: 判断表达式,从参数中取值进行判断,遇见特殊符号应该使用转义字符
  choose(when、otherwise): 分支选择,带了break的switch-case
  trim:
   prefix: 给拼串后的整个字符串加一个前缀
   prefixOverrides: 前缀覆盖,去掉整个字符串前面多余的字符串
   suffix: 后缀,给拼串后的整个字符串加一个后缀
   suffixOverrides: 去掉整个字符串后面多余的字符
  where:
   会将标签中多出来的and或者or去掉,只能去掉第一个多出来的
  set:
   封装修改条件
  foreach:
   collection: 指定要遍历的集合
     list类型的参数会特殊处理 封装在map中,map的key就叫list
   item: 将当前遍历出的元素赋值给指定的遍历
   separator: 每个元素之间的分隔符
   open: 遍历出所有结果,拼接一个开始字符
   close: 遍历出所有结果,拼接一个结束的字符
   index: 索引,遍历list的时候index就是所有,item就是当前值
     遍历map的时候,index表示的就是map的key,item就是map的值
    可以用于批量插入
  bind: 可以将OGNL表达式的值绑定到一个变量中,方便后来引用这个变量的值
  sql: 抽取可重用的sql片段 可以方便后面引用
   sql抽取: 经常将要查询的列名或者插入用的列名抽取出来方便引用
   include来引用以抽取的sql
   include:还可以自定一些property,sql标签内部就能使用自定义的属性
    取值${prop} 不能使用#{}这种方式
  include: 引用外部的sql
   refid: 引用的sql片段id

Mybatis缓存

  MyBatis 包含一个非常强大的查询缓存特性,它可以非 常方便地配置和定制。缓存可以极大的提升查询效率
  mybatis系统中默认定义了两级缓存
  一级缓存:(本地缓存): sqlSession级别的缓存,一级缓存是一致开启的,SqlSession级别的一个Map
    与数据库同一次会话期间查询到的数据会放在本地缓存
    以后如果需要获取相同的数据,之间从缓存中拿,没必要再去查询数据库
    本地缓存不能被关闭,但可以调用clearCache()来清空本地缓存,或者改变缓存的作用域
    在mybatis3.1之后,可以在全局配置文件中配置缓存的作用域
    localCacheScope: 本地缓存作用域 (一级缓存 SESSION)当前会话的所有数据保存在会话缓存中
      STATEMENT :  可以禁用一级缓存
    一级缓存失效的情况
      sqlSession不同
      sqlSession相同,查询条件不同(当前一级缓存中还没有这个数据)
      sqlSession相同,两次查询之间执行了增删改操作,(这次增删改可能对当前数据又影响)
      sqlSession相同,手动清除了一级缓存(缓存清空了)
  
  二级缓存:(全局缓存): sqlSession级别的缓存,一个namespace对应一个二级缓存
   工作机制
    一个会话,查询一条数据,这个数据会被放在当前会话的一级缓存中
    如果当前会话关闭,那么一级缓存中的数据会被保存到二级缓存中,新的会话查询信息,就可以参照二级缓存中的内容
    不同的namespace查出的数据会放在自己对应的缓存中(Map)
     效果: 数据会从二级缓存中获取
      查出的数据都会被默认先放在一级缓存中
      只有会话提交或者关闭以后,一级缓存中的数据才会被放到二级缓存中
   使用步骤:
    开启全局二级缓存配置:
    去每个mapper.xml中配置使用二级缓存
     
    pojo需要实现序列化接口
    
和缓存有关的设置 / 属性
  cacheEnabled = true; false,关闭缓存(二级缓存关闭 一级缓存一直可用)
  每个select标签都有useCache=true
    false: 不适用缓存(一级缓存依然使用,二级缓存不使用)
  每个增删改标签的flushCache=true默认都是true(一级二级都会清除)重点
    增删改执行完后就会清除缓存
    测试:flushCache=“true” 一级缓存清空,二级缓存也会被清除
    select标签,flushCache=“false” 默认为false不会清除缓存,如果设置为true每次查询之后都会清空缓存
  sqlSession.clearCache(): 只是清除当前session的一级缓存
  localCacheScope: 本地缓存作用域
    SESSION: 当前会话的所有数据保存在会话缓存中
    STATEMENT: 可用禁用一级缓存
 在mapper中的配置
  
   eviction: 缓存的回收策略(缓存中的内容超了之后,吧哪些内容删掉)
     LRU: 最近最少使用的,移除最长时间不被使用的对象
     FIFO: 先进先出,按对象 进入缓存的顺序来移除他们
     SOFT: 软引用,移除基于垃圾回收器状态和软引用规则的对象
     WEAK: 弱引用,更积极地移除基于垃圾收集器状态和弱引用规则的对象
     默认是LRU
   flushInterval: 缓存刷新间隔
     缓存多长时间清空一次,默认不清空,设置一个毫秒值
   readOnly: 缓存是否只读
     true: 只读,mybatis任务所有从缓存中获取数的操作都是只读操作,不会修改数据
      mybatis为了加快获取速度,直接就会将数据在缓存中的引用交给用户,(如果用户改变了,缓存中的值也会改变,不安全但是速度快)
     false: 非只读,mybatis认为获取的数据可能会被修改
      mybatis会利用序列化与反序列化的技术克隆一份新的数据给你,安全、速度慢,默认为false
     size: 缓存存放多少元素
     tyep: 指定自定义缓存的全类名,实现Cache接口即可

你可能感兴趣的:(互联网架构)