分開的兩個程序使用共同的mysql,一端更新了表,另一端怎麼及時更新緩存,使用mybatis

    目前項目中由於業務系統和管理系統是分開的,管理端只負責對數據庫表的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就可以輕鬆調用方法啦~~

(下篇準備寫一下項目中使用到的線程池機制,使用到了信號量等東西,做系統中統一的池挺不錯,大師出品,值得依賴,敬請期待)






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章