如何使用
mybatis L2缓存?
了解更多关于MyBatis L2缓存的信息
首先,创建缓存的整个过程
我们从SqlSessionFactoryBuilder解析mybatis-config.xml配置文件开始:
reader reader = resources . getresourceasreader(& quot;my batis-config . XML & quot;);
SqlSessionFactory SqlSessionFactory = new SqlSessionFactory builder()。构建(阅读器);
然后:
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream,environment,properties);
返回build(parser . parse());
看看parser.parse()方法:
parse configuration(parser . eval node(& quot;/配置& quot));
查看处理Mapper.xml文件的位置:
mapper element(root . eval node(& quot;地图绘制者& quot));
看看处理Mapper.xml的XMLMapperBuilder:
XML mapper builder mapper parser = new XML mapper builder(inputStream,configuration,
resource,configuration . getsql fragments());
mapperparser . parse();
继续看看解析方法:
configuration element(parser . eval node/mapper & quot;));
转到此处:
string namespace = context . getstring attribute(& quot;命名空间& quot);
if(namespace . equals(& quot;& quot)) {
抛出new builder exception(& quot;映射器& # 39;的命名空间不能为空);
}
builder assistant . setcurrentnamespace(命名空间);
cacheRefElement(context . eval node(& quot;cache-ref & quot;));
cacheElement(context . eval node(& quot;缓存& quot));
看这里,名称空间是
看看我的巴蒂斯如何处理
私有void cacheElement(XNode上下文)引发异常{
如果(上下文!= null) {
string type = context . getstring attribute(& quot;键入& quot,& quot永久& quot);
Class & lt马鞭延伸缓存& gttype class = typealiasregistry . resolve alias(type);
string eviction = context . getstring attribute(& quot;驱逐& quot,& quotLRU & quot;);
Class & lt马鞭延伸缓存& gteviction class = typealiasregistry . resolve alias(eviction);
long flush interval = context . getlong attribute(& quot;flushInterval");
integer size = context . getint attribute(& quot;尺寸& quot);
布尔读写=!context . get boolean attribute(& quot;只读,假);
boolean blocking = context . getbooleanattribute(& quot;阻止& quot,假);
properties props = context . getchildrenaspproperties();
builderasistant . use new cache(type class,evictionClass,
flushInterval、size、readWrite、blocking、props);
}
}
从源代码中可以看到MyBatis已经读取了那些属性,很容易就可以得到这些属性的默认值。
Java的cache对象方法是builderAssistant.useNewCache我们来看看这段代码:
公共缓存useNewCache(Class & lt;马鞭延伸缓存& gttypeClass,
Class & lt马鞭延伸缓存& gt驱逐阶级,
长冲洗间隔,
整数大小,
布尔读写,
布尔阻塞,
属性道具){
type class = valueOrDefault(type class,perpetual cache . class);
eviction class = valueOrDefault(eviction class,lrucache . class);
Cache cache =新的CacheBuilder(当前命名空间)
.实现(类型类)
.addDecorator(evictionClass)
.清除时间间隔
.尺寸(大小)
.读写(读写)
.阻断(阻断)
.属性(道具)
.build();
configuration.addCache(缓存);
currentCache = cache
返回缓存;
}
从调用这个方法的地方我们可以看到,并没有使用返回值缓存,而是在后面的过程中创建MappedStatement时使用了currentCache。
第二,使用缓存过程
在系统中,使用缓存的地方是在CachingExecutor中:
@覆盖
公共& ltE & gt列表& ltE & gt查询(
mapped语句ms,Object参数Object,
RowBounds rowBounds,ResultHandler resultHandler
CacheKey key,BoundSql boundSql)抛出SQLException {
cache cache = ms . get cache();
获取缓存后,先确定是否有二级缓存。
仅通过,& ltcache-ref/>或者@ cachenamespace,@ cachenamespaceref标签使用cached Mapper.xml或者Mapper接口(不能同时使用同一个命名空间)拥有L2缓存。
如果(缓存!= null) {
如果缓存存在,它将根据sql(
flushCacheIfRequired(毫秒);
然后根据xml配置的属性useCache判断是否使用缓存(resultHandler常用的默认值很少为null)。
if(ms . isusecache()& & result handler = = null){
确保该方法没有Out类型的参数。mybatis不支持存储过程的缓存,所以如果是存储过程,这里会报错。
ensureNoOutParams(ms,parameterObject,boundSql);
如果没有问题,将根据键从缓存中获取值:
@ suppress warnings(& quot;未选中& quot)
列表& ltE & gtList =(List & lt;E & gt)tcm.getObject(cache,key);
如果没有缓存,将执行查询,并将查询结果放入缓存中。
if (list == null) {
列表=委托。& ltE & gt查询(毫秒,参数对象,
rowBounds、resultHandler、key、boundSql);
tcm.putObject(缓存、键、列表);//问题#578和#116
}
返回结果
退货单;
}
}
没有缓存时,直接执行查询。
返回委托。& ltE & gtquery(ms,parameterObject,rowBounds,resultHandler,key,boundSql);
}
在上面的代码中,tcm.putObject(cache,key,list);这段代码缓存结果。但实际上,直到sqlsession关闭,MyBatis才以序列化的形式保存在Map(默认缓存配置)中。
三、使用缓存时的注意事项
1.缓存只能用于具有单表操作的表。
只需要保证这个表在整个系统中只有一个表操作,所有和这个表相关的操作都必须在一个命名空间中。
2.当您可以保证查询远远大于插入、更新和删除操作时,请使用缓存。
这不用我说,大家应该都知道。记住,这需要在1的前提下保证!
第四,避免使用L2缓存。
这里可能有很多人不理解。L2缓存带来的好处远远小于隐患。
缓存在命名空间中,不同命名空间中的操作互不影响。
插入、更新和删除操作将清除空所在的名称空间中的所有缓存。
通常在MyBatis Generator生成的代码中,每个表都是独立的,每个表都有自己的命名空间。
为什么避免使用L2缓存?
符合【缓存使用注意事项
mybatis collection的三种用法?
mybatis使用foreach中collection的三种用法
foreach的主要用在构建in条件中,它可以在SQL语句中进行迭代一个集合。
foreach元素的属性主要有 item,index,collection,open,separator,close。
item表示集合中每一个元素进行迭代时的别名,
index指 定一个名字,用于表示在迭代过程中,每次迭代到的位置,
open表示该语句以什么开始,
separator表示在每次进行迭代之间以什么符号作为分隔 符,
close表示以什么结束。
在使用foreach的时候最关键的也是最容易出错的就是collection属性,该属性是必须指定的,但是在不同情况 下,该属性的值是不一样的,主要有一下3种情况:
1. 如果传入的是单参数且参数类型是一个List的时候,collection属性值为list
2. 如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array
3. 如果传入的参数是多个的时候,我们就需要把它们封装成一个Map了,当然单参数也可
以封装成map,实际上如果你在传入参数的时候,在breast里面也是会把它封装成一个Map的,map的key就是参数名,所以这个时候collection属性值就是传入的List或array对象在自己封装的map里面的key 下面分别来看看上述三种情况的示例代码
mybatis怎么将一个表中符合查询条件的多条记录,返回为一个list+map的形式?
xml中配置好pojo对象 然后将properties和数据库字段匹配即可