高级结果映射
数据模型
一对一
association分为:镶嵌查询、镶套结果
镶嵌查询
<resultMap id="findSaler" type="xx.xx.saler">
<id column="saler_id" property="salerid"></id>
<result column="saler_name" property="salername"></result>
<association column="user_id" property="user" select="findeUser" javaType="xx.xx.user" >//colunm外键列名
<id column="user_id" property="userid"></id>
<result column="user_name" property="username"></result>
</association>
</resultMap>
<select id="findeUser" resultType="xx.xx.user">
SELECT * from user where id = #{id};
</select>
<select id="findeSaler" resultMap="findSaler" parameterType="String">
SELECT * from saler where id = #{id};
</select>
这种查询会发生n+1现象,即本来查询一条sql,现在却需要查询1+n条 1指查询saler n指查询saler相关的user,可以使用延迟加载,但是延迟加载在一些情景下(快速迭代)就会很糟糕,使用镶套查询解决。
镶套查询
<resultMap id="findSaler" type="xx.xx.saler">
<id column="saler_id" property="salerid"></id>
<result column="saler_name" property="salername"></result>
<association property="user" javaType="xx.xx.user" >
<id column="user_id" property="userid"></id>
<result column="user_name" property="username"></result>
</association>
</resultMap>
<select id="findeSaler" resultMap="findSaler" parameterType="String">
SELECT * from saler,user where user.id=saler.id
</select>
一对多
<resultMap id="findSaler" type="xx.xx.saler">
<id column="saler_id" property="salerid"></id>
<result column="saler_name" property="salername"></result>
<collection property="customs" javaType="ArrayList" ofType="xx.xx.customs">
<id column="cusotom_id" property="cusotomid"></id>
<result column="cusotom_name" property="cusotomname"></result>
</collection>
</resultMap>
<select id="findeSaler" resultMap="findSaler" parameterType="String">
SELECT * from saler,customs where cusoms.saler_id=saler.id
</select>
缓存
一级缓存
a.一级缓存指的就是sqlsession,创建一个新的SqlSession对象,SqlSession对象中会有一个新的Executor对象,Executor对象中持有一个新的PerpetualCache对象; ,Cache最核心的实现其实就是一个Map,将本次查询使用的特征值作为key,将查询结果作为value存储到Map中。,CacheKey由以下条件决定:statementId + rowBounds + 传递给JDBC的SQL + 传递给JDBC的参数值
b. 如果SqlSession调用了close()方法,会释放掉一级缓存PerpetualCache对象,一级缓存将不可用;
c. 如果SqlSession调用了clearCache(),会清空PerpetualCache对象中的数据,但是该对象仍可使用;
d.SqlSession中执行了任何一个update操作(update()、delete()、insert()) ,都会清空PerpetualCache对象的数据,但是该对象可以继续使用;
注意:
1、对于数据变化频率很大,并且需要高时效准确性的数据要求,我们使用SqlSession查询的时候,要控制好SqlSession的生存时间,SqlSession的生存时间越长,它其中缓存的数据有可能就越旧,从而造成和真实数据库的误差;同时对于这种情况,用户也可以手动地适时清空SqlSession中的缓存;
2、对于只执行、并且频繁执行大范围的select操作的SqlSession对象,SqlSession对象的生存时间不应过长。
二级缓存
相关实体类需要实现序列化接口
执行查询后需要close或者commit才会把数据提交到二级缓存中。
执行增删改commit之后会清空二级缓存
MyBatis在为SqlSession对象创建Executor对象时,会对Executor对象加上一个装饰者:
CachingExecutor,这时SqlSession使用CachingExecutor对象来完成操作请求。
CachingExecutor对于查询请求,会先判断该查询请求在Application级别的二级缓存中是
否有缓存结果,如果有查询结果,则直接返回缓存结果;如果缓存中没有,再交给真正的
Executor对象来完成查询操作,之后CachingExecutor会将真正Executor返回的查
询结果放置到缓存中,然后在返回给用户
MyBatis二级缓存的划分
MyBatis并不是简单地对整个Application就只有一个Cache缓存对象,它将缓存划分的更
细,即是Mapper级别的,即每一个Mapper都可以拥有一个Cache对象,具体如下:
a.为每一个Mapper分配一个Cache缓存对象(使用<cache>节点配置);
MyBatis将Application级别的二级缓存细分到Mapper级别,即对于每一个Mapper.xml,如果
在其中使用了<cache> 节点,则MyBatis会为这个Mapper创建一个Cache缓存对象,
b.多个Mapper共用一个Cache缓存对象(使用<cache-ref>节点配置);
如果你想让多个Mapper公用一个Cache的话,你可以使用<cache-ref namespace="">节点,
来指定你的这个Mapper使用到了哪一个Mapper的Cache缓存。