這篇文章主要介紹了Mybatis多線程下使用Example的示例,具有一定借鑒價(jià)值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
成都創(chuàng)新互聯(lián)-成都網(wǎng)站建設(shè)公司,專注網(wǎng)站制作、網(wǎng)站建設(shè)、網(wǎng)站營(yíng)銷推廣,域名與空間,網(wǎng)站空間,網(wǎng)站托管運(yùn)營(yíng)有關(guān)企業(yè)網(wǎng)站制作方案、改版、費(fèi)用等問(wèn)題,請(qǐng)聯(lián)系成都創(chuàng)新互聯(lián)。
前言
服務(wù)器每收到一個(gè)請(qǐng)求,都會(huì)從線程池中調(diào)度一個(gè)空閑線程來(lái)處理,spring整合的web時(shí),controller和service一般都是單例的,這樣導(dǎo)致無(wú)論你的Example標(biāo)注的是單例還是多例,同一個(gè)service下的Example也只有一個(gè),多線程訪問(wèn)時(shí)產(chǎn)生的
問(wèn)題如下
問(wèn)題詳情
工程目錄結(jié)構(gòu)如下
MyService 的service()方法接收兩個(gè)參數(shù)并據(jù)此查詢數(shù)據(jù)庫(kù)
@Service public class MyService { @Autowired StudentMapper studentMapper; @Autowired StudentExample studentExample; public void service(Integer begin,Integer end){ StudentExample.Criteria criteria1 = studentExample.createCriteria(); criteria1.andAgeBetween(begin,end); Listlist=studentMapper.selectByExample(studentExample); studentExample.clear(); System.out.println(list); } }
當(dāng)同時(shí)有兩個(gè)請(qǐng)求時(shí),兩個(gè)請(qǐng)求的StudentExample相同
請(qǐng)求1如下
begin=2,end=8
請(qǐng)求2如下
begin=4,end=8
先放行請(qǐng)求1,請(qǐng)求1成功添加條件
再放行請(qǐng)求2,請(qǐng)求2添加失敗
這時(shí)如果請(qǐng)求2在請(qǐng)求1執(zhí)行查詢操作前就已經(jīng)執(zhí)行完studentExample.clear (),請(qǐng)求1的查詢條件就失效了
至此兩個(gè)請(qǐng)求都沒(méi)有得到正確的結(jié)果。
解決方案
可以使用ThreadLocal為每個(gè)線程配備單獨(dú)的Example,為保證每次都能獲取到值,這里對(duì)ThreadLocal簡(jiǎn)單擴(kuò)展一下,如果當(dāng)前線程沒(méi)有對(duì)應(yīng)的Example(多例),就從spring容器中獲取一個(gè)并與這個(gè)線程綁定。
ThreadLocalExtension
public class ThreadLocalExtensionextends ThreadLocal { //獲取ApplicationContext方法見下 @Autowired ApplicationContext applicationContext; public ThreadLocalExtension(){ super(); } public T get(Class example){ T bean=super.get(); if(bean==null){ super.set((T) applicationContext.getBean(example)); } return super.get(); } }
spring泛型依賴注入
由于Example會(huì)有很多個(gè),所以這里使用了泛型,spring4.0提供了對(duì)泛型依賴注入的支持。
首先實(shí)際類型對(duì)應(yīng)的ThreadLocalExtension交由spring管理
@Repository public class StudentExampleThreadLocal extends ThreadLocalExtension{ }
然后直接在代碼中注入
@Autowired ThreadLocalExtensionstudentExampleThreadLocal;
修改后的MyService
@Service public class MyService { @Autowired StudentMapper studentMapper; @Autowired ThreadLocalExtensionstudentExampleThreadLocal; public void service(Integer begin,Integer end){ StudentExample studentExample = studentExampleThreadLocal.get(StudentExample.class); StudentExample.Criteria criteria1 = studentExample.createCriteria(); criteria1.andAgeBetween(begin,end); List list=studentMapper.selectByExample(studentExample); studentExample.clear(); System.out.println(list); } }
獲取ApplicationContext
創(chuàng)建一個(gè)類實(shí)現(xiàn)ApplicationContextAware,并向spring容器中注入applicationContext
@Component public class ApplicationContextHelper implements ApplicationContextAware { private static ApplicationContext applicationContext; public ApplicationContextHelper() { } @Bean(name="applicationContext") public ApplicationContext getApplicationContext(){ return applicationContext; } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { ApplicationContextHelper.applicationContext = applicationContext; } public static Object getBean(String beanName) { return applicationContext != null?applicationContext.getBean(beanName):null; } }
結(jié)果
至此,整個(gè)改造完成,看看效果
請(qǐng)求1
請(qǐng)求2
每個(gè)請(qǐng)求獲取到了不同的StudentExample,也就不存在沖突的問(wèn)題,并且StudentExample沒(méi)有大量的創(chuàng)建與銷毀,最多只創(chuàng)建了與服務(wù)器線程池中線程相同的個(gè)數(shù),實(shí)現(xiàn)了重復(fù)使用
感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“Mybatis多線程下使用Example的示例”這篇文章對(duì)大家有幫助,同時(shí)也希望大家多多支持創(chuàng)新互聯(lián),關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,更多相關(guān)知識(shí)等著你來(lái)學(xué)習(xí)!