mybatis学习笔记(关于映射文件和mybatis缓存)

2018-10-02



insert into administrator(id,name,age,job) VALUES
(#{id},#{administrator.name},${administrator.age},#{administrator.job})

只有insert和update标签中有useGenaratedKeys和keyProperty两个属性,这两个属性是为了获取
数据库中自增字段用的,将返回的值复制给keyProperty中设置的变量,然后可以在下面的sql语句这样
使用,你发现,我的administrator只有插入了三个属性,id属性是没有插入的,这个属性是为了接收
用的,也就是说在执行完这条语句后,我调用administrator.getId()会获取到数据库自增字段id的值。

参考链接:https://blog.csdn.net/hellostory/article/details/6790248

对于不支持自动生成主键的JDBC驱动或者数据库,需要在insert标签中加上标签
例如:

select CAST(RANDOM()*1000000 as INTEGER) a from SYSIBM.SYSDUMMY1

其中属性值order需要注意,这个属性值只有两个值,一个是BEFORE,另一个是AFTER
如果设置为 BEFORE,那么它会首先选择主键,设置 keyProperty 然后执行插入语句。
如果设置为 AFTER,那么先执行插入语句,然后是 selectKey 元素

标签可以被用来定义可重用的SQL代码段,可以包含在其他语句中

标签里有个标签
使用这个标签的时候要注意
我们知道在include标签中有个属性refid用来指向一个sql标签的
那么这个property标签则是对sql标签中的值进行复制用的,我们来看下例子:
${tt}

这条语句返回结果是错的,它显示找不到程序员这行,
我们在引用语句左右两边都加上引号,现在我们来看下输出的sql语句:
select * from administrator where job = " 程序员 "
发现了吧,我们传入值的左右两边都有空格,也就是说,在使用字段是字符串的情况下,不能这样写,否则会出现上面的情况。

#{变量名,属性:xxxx,属性:xxx}

关于使用和不使用@Param()注释的区别
1、不使用@Param注释,参数只能有一个,并且参数是对象,这样使用#{}和使用{}都可以取值 2、不使用@Param注释,参数只有一个,如果参数是基本类型和String类型,则使用#{}正常取值,{}取不到值
3、使用@Param注释,#{}和${}都可以取到值,并且单个参数和多个参数的情况都适用


2018-10-09

以作用域+返回值+绝对路径的方法名
e.g:
public abstract java.until.List com.dao.PersonDao.select_PersonAndJob() 这个作为key
将MapperMethod作为value

MapperMethod中有两个比较重要的内部类
1、sqlCommand //封装了SQL标签的类型:insert update delete select
2、MethodSignature //封装了方法的参数信息 返回类型信息等

mybatis缓存

1、一级缓存是通过SqlSession来实现的

image.png

图片来自链接:https://blog.csdn.net/qq_25689397/article/details/52066179
这是只有mybatis框架的情况下,缓存的大体过程

如果只有mybatis的时候,当进入到MapperMethod类中调用selectList方法的时候,进入的是DefaultSqlSession类
然后在这个类中调用执行器executor的query方法,在执行器中有个成员变量用于存储缓存,就是PerpetualCache类
这个类中的成员变量cache存储缓存,这个成员变量类型是hashmap类型,也就是mybatis的缓存数据是存储在hashmap中的

注意:获取mapperMethod
将路径作为key,通过方法cachedMapperMethod()方法来操作,如果key存在则直接取出MapperMethod对象
如果key不存在则新建一个mapperMethod对象,并将对象存入ConcurrentHashMap集合中,然后返回该对象。
接着是调用mapperMethod的execute()方法,根据mapperMethod的command的属性类型,进行相对应的操作,
基本就是sqlSession的四个操作:insert update delete select
下面以select为例
调试进入这个方法发现是进入SqlSessionTemplate类,因为我是整合好的SSM框架,所以在这个时候是spring在
对这些sqlSession进行代理操作,在调用这个方法的时候,会进入到这个类的内部类SqlSessionInterceptor
在这个类invoke方法中,我们发现,他在finally{}代码块中对sqlSession进行了关闭操作,这也是为什么我们
每一次调用sql语句,不是从缓存中取出来,而是直接跟数据库打交道,也就是每个session运行完一个方法后,就
会被销毁,即创建快销毁的也快

2、二级缓存是通过mapper的namespace实现共享

也就是不同的session对于namespace的操作是共享的,每个namespace都有一块缓存,在执行查询的时候默认不刷新缓存,
而在执行增删改的时候是默认要刷新缓存的,mybatis提供给我们两个属性进行设置,一个是useCache一个是flushCache
并且默认值如下: