Mybatis学习笔记(二)

映射器主要元素
select/insert/update/delete
parameterMap/resultMap
sql/cache/cache-ref

select元素配置 useCache,flushCache,fetchSize等,还有result相关配置,如resultType,resultMap等
insert元素配置 keyPropperty,keyColumn,useGeneratedKeys,flushCache等,没有useCache以及result相关
update/delete与insert基本一样
这四个标签共有的元素配置:id,parameterType,parameterMap,timeout(秒),statementType,默认使用PreparedStatement
fulshCache:调用SQL后,是否清空之前查询的本地缓存和二级缓存,默认false
useCache:启动二级缓存开关,是否要求将此次结果缓存,默认true


传递多参数:当n<=5时,使用@Param注解传递最佳,当n>5时,建议使用JavaBean方式

存储过程支持
:mode(IN,OUT,INOUT)
#{role,mode=OUT,jdbcType=CURSOR,javaType=ResultSet,resultMap=roleResultMap}

特殊字符处理:使用美元符号,如:${columns}

sql标签:<sql id="***"></sql>配合 <include refid="***"/>使用。


resultMap元素构成
<resultMap id='**' type='com.learn.**.Role' extends=""> <!--type:指定POJO, extends表示继承某一个resultMap-->
  <constructor> <!--构造方法-->
     <idArg column='**' javaType='**'/> <!--标记该入参为主键-->
     <arg column='**' javaType='**'/> <!--标记该入参为普通字段-->
  </constructor>
  <id property='' column='' javaType='' jdbcType='' typeHandler=''/> <!--主键,允许多个表示联合主键-->
  <result/> <!--属性同id,普通字段映射-->
  <association property='' column='id,id1,id2,****' select='com.learn.**.Student.findById' fetchTpye='' />
  <!--一对一关系,column(对应该获取map的SQL语句中返回的列名)指定传递给select的参数,可以多个,fetchType:eager和lazy(延迟加载)-->

  <collection ofType=''/><!--属性同association,一对多关系,ofType:类似javaType,定义的是collection里面的泛型是什么Java类型-->

  <discriminator javaType="" column=""> <!--根据特定条件关联不同的结果集-->
     <case value="" resultMap=""/>
  </discriminator>
</resultMap>

超过三层关联时尽量少用级联,会有N+1(调用一次执行N+1个SQL)问题,导致性能下降

延迟加载:layLoadingEnabled(默认false,开启延迟加载)和aggressiveLazyLoading(默认true---true按内容层级加载,反之按需加载)
<settings>
  <setting name="layLoadingEnabled" value="true"/>
  <setting name="aggressiveLazyLoading" value="false"/>
</settings>
默认MyBatis按层级加载,resultMap与discriminator是一层,association与collection是一层

延迟加载的原理是通过动态代理来实现的,默认情况下,3.3或以上版本采用JAVASSIST的动态代理,低版本采用CGLIB.
原理:它先生成一个动态代理对象,里面保存着相关的SQL和参数,一旦使用这个代理对象,它会进入对象的方法里,并通过发送SQL和参数,把相应的结果从数据库中查找出来。

缓存
Mybatis默认开启一级缓存(相对同一个SqlSession而言),只发生一次SQL查询,第二次查询就从缓存中取出
二级缓存:SqlSessionFactory层面的(可以多个SqlSession共享),默认不开启,需要配置 如:<cache/>, 要求返回的POJO必须是可序列化的

<cache eviction='**' flushInterval='***' size='**' readOnly='false'/>意味着:
1.所有select语句会被缓存
2.所有insert/update/delete语句会刷新缓存
3.默认使用LRU(最近最少使用的)算法来回收
4.根据时间表,比如(CNFI,没有刷新间隔),缓存不会以任何时间顺序来刷新
5.缓存存储1024个集合或对象的引用
6.缓存被视为read/write,意味者对象检索不是共享的,而且可以安全地被调用者修改,不干扰其他调用者或线程所做的潜在修改

eviction:缓存回收策略
LRU-最近最少使用,移除最长时间不用的,默认
FIFO-先进先出
SOFT-软引用,移除基于垃圾回收器状态和软引用规则的对象
WEAK-弱引用,更积极地移除基于垃圾收集器状态和弱引用规则的对象,这里采用LRU算法

flushInterval:刷新时间间隔,单位毫秒,默认是SQL被执行的时候刷新缓存
size:缓存最多可以存储多少个对象,默认1024个,不宜过大
readOnly:只读,意味着只能读取不能修改(好处是快速读取缓存),默认false,不建议修改

自定义缓存
需要实现 org.apache.ibatis.cache.Cache接口
String getId()//获取缓存编号
void putObject(Object key, Object value)
Object getObject(Object key)
Object removeObject(Object key)
void clear()//清空缓存
int getSize()//获取缓存对象大小
ReadWriteLock getReadWriteLock()//获取缓存读写锁
<cache type='com.learn.***.MyCache'> <!--type指向具体的实现类,当然也可以加上其他一些属性如eviction-->
  <property name='host' value='localhost'/> <!--name对应set方法,如setHost(String host) -->

</cache>

动态SQL

<if test="a != null and/or a != ''"><!--if 条件判断 -->

<choose> <!--choose(when otherwise)相当于switch-->
   <when test='***'>
   <when test='***'>
   <otherwise></otherwise>
<choose>

<trim prefix='where' prefixOverrides='and' suffixOverrides=','>
prefix代表语句加上前缀,prefixOverrides代表去掉前面这个字符,suffixOverrides代表去掉后面这个字符
trim用于辅助where,set进行SQL拼装


<foreach item='' index='' collection='' open="(" separator="," close=",">
collection:传递进来的参数名称
item:循环中当前元素
index:循环中当前元素所在的下标
open和close表示配置是以什么符号将这些集合元素包装起来 如:(1,2,3,4)
separator是元素之间的间隔符
常配合in使用

<bind name="pattern_roleName" value="'%'+roleName+'%'"/>
<bind name="pattern_note" value="'%'+note+'%'"/>
使用:#{pattern_roleName} #{pattern_note},模糊查询的时候用,可以跨库使用,提高了移植性
如果用“concat %”则在使用Oracle数据库的时候不可用,Oracle用的连接符号是“||”,用bind就没问题

猜你喜欢

转载自blog.csdn.net/lovewebeye/article/details/79885132