目前項目中由於業務系統和管理系統是分開的,管理端只負責對數據庫表的CRUD,而業務系統也需要交互db。現在就存在一個問題,在管理端上改了某個表的值,業務端是無從得知的。因爲業務端一直用相同的語句查詢db,mybatis的二級緩存會緩存這些數據,不會真正發sql去查詢真實數據。所以就需要管理端在修改表的時候,通知一下業務端是更新二級緩存,這樣才能及時使用新值。
起初在想mybatis的sqlSessionFactory有沒有提供可以更新全局二級緩存的接口,發現真的沒有。那就手動更新嘛~ ~ ~。方法是:
首先我們的mapper是一個*Mapper.java加上*Mapper.xml,在.java中定義接口:
@Repository
public interface AppConfMapper {
public List<Map> getBizConf(@Param("jobId") long jobId);
public void refreshCache();
}
*Mapper.xml:
<mapper namespace="com.szkingdom.kisp.mapper.AppConfMapper">
<!-- 開啓二級緩存 -->
<cache />
<select id="getBizConf" parameterType="long" resultType="map" useCache="true">
SELECT * FROM kisp_biz_conf t
</select>
<!-- 刷新緩存 -->
<update id="refreshCache" flushCache="true">
SELECT 1;
</update>
</mapper>
<cache />是一個全局的配置,但在每個子元素是可以配置自身。
(1)當爲select語句時:
flushCache默認爲false,表示任何時候語句被調用,都不會去清空本地緩存和二級緩存。
useCache默認爲true,表示會將本條語句的結果進行二級緩存。
(2)當爲insert、update、delete語句時:
flushCache默認爲true,表示任何時候語句被調用,都會導致本地緩存和二級緩存被清空。
useCache屬性在該情況下沒有。
上面的信息我是從MyBatis官方文檔中找到的,會發現當爲select語句的時候,如果沒有去配置flushCache、useCache,那麼默認是啓用緩存的。 我們寫一個refleshCache方法,在xml中用<update />,但是不用寫一條真正的update語句,用個select 1就行了,因爲貌似mybatis只認標籤的類型,而不是具體是什麼語句,這裏發現是<update flushCache="true"/>,就會更新這個mapper中所有<select>使用的二級緩存了。
這裏我們提供一個http接口給管理端用,他們每次更新db,就調一次接口,我們就知道要更新。如果說,mapper.xml有很多,那是不是要在作業類裏調用每個mapper的refleshCache() ?不是的。可以利用Reflect。
具體做法是寫所有要更新的xml定義起來,比如放在spring配置文件中
<bean id="flush_mapper_cache_list" class="java.util.ArrayList">
<constructor-arg>
<list>
<value>appConfMapper</value>
<value>exceptionMapper</value>
<value>kispCoreBizDataMapper</value>
</list>
</constructor-arg>
</bean>
由於每個mapper.java都用了註解,所有spring容器可以產生他們的實例。
private void flush(String mapperInstanceName) throws Exception {
Object instance = BeanHoldFactory.getSpringBean(mapperInstanceName);
Method method = instance.getClass().getMethod("refleshCache");
method.invoke(instance);
logger.info(mapperInstanceName + "二級緩存刷新成功!");
}
利用Method的invode就可以輕鬆調用方法啦~~(下篇準備寫一下項目中使用到的線程池機制,使用到了信號量等東西,做系統中統一的池挺不錯,大師出品,值得依賴,敬請期待)