Mybatis多線程下如何使用Example詳解
前言
服務(wù)器每收到一個(gè)請(qǐng)求,都會(huì)從線程池中調(diào)度一個(gè)空閑線程來處理,spring整合的web時(shí),controller和service一般都是單例的,這樣導(dǎo)致無論你的Example標(biāo)注的是單例還是多例,同一個(gè)service下的Example也只有一個(gè),多線程訪問時(shí)產(chǎ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); List<Student> list=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)求都沒有得到正確的結(jié)果。
解決方案
可以使用ThreadLocal為每個(gè)線程配備單獨(dú)的Example,為保證每次都能獲取到值,這里對(duì)ThreadLocal簡(jiǎn)單擴(kuò)展一下,如果當(dāng)前線程沒有對(duì)應(yīng)的Example(多例),就從spring容器中獲取一個(gè)并與這個(gè)線程綁定。
ThreadLocalExtension
public class ThreadLocalExtension<T> extends ThreadLocal<T> { //獲取ApplicationContext方法見下 @Autowired ApplicationContext applicationContext; public ThreadLocalExtension(){ super(); } public T get(Class<T> 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<StudentExample> { }
然后直接在代碼中注入
@Autowired ThreadLocalExtension<StudentExample> studentExampleThreadLocal;
修改后的MyService
@Service public class MyService { @Autowired StudentMapper studentMapper; @Autowired ThreadLocalExtension<StudentExample> studentExampleThreadLocal; public void service(Integer begin,Integer end){ StudentExample studentExample = studentExampleThreadLocal.get(StudentExample.class); StudentExample.Criteria criteria1 = studentExample.createCriteria(); criteria1.andAgeBetween(begin,end); List<Student> 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,也就不存在沖突的問題,并且StudentExample沒有大量的創(chuàng)建與銷毀,最多只創(chuàng)建了與服務(wù)器線程池中線程相同的個(gè)數(shù),實(shí)現(xiàn)了重復(fù)使用
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
Springcloud Stream消息驅(qū)動(dòng)工具使用介紹
SpringCloud Stream由一個(gè)中間件中立的核組成,應(yīng)用通過SpringCloud Stream插入的input(相當(dāng)于消費(fèi)者consumer,它是從隊(duì)列中接收消息的)和output(相當(dāng)于生產(chǎn)者producer,它是發(fā)送消息到隊(duì)列中的)通道與外界交流2022-09-09Java編程中隨機(jī)數(shù)的生成方式總結(jié)
在Java中利用自帶的類庫(kù)可以有三種途徑可以產(chǎn)生隨機(jī)數(shù),這里我們舉了一些簡(jiǎn)單的例子來進(jìn)行Java編程中隨機(jī)數(shù)的生成方式總結(jié),需要的朋友可以參考下2016-05-05深入分析Spring BeanDefinition的構(gòu)造元信息
Bean Definition是一個(gè)包含Bean元數(shù)據(jù)的對(duì)象,它描述了如何創(chuàng)建Bean實(shí)例、Bean屬性的值以及Bean之間的依賴關(guān)系,本文將帶大家深入分析Spring BeanDefinition的構(gòu)造元信息,需要的朋友可以參考下2024-01-01詳解Spring boot使用Redis集群替換mybatis二級(jí)緩存
本篇文章主要介紹了詳解Spring boot使用Redis集群替換mybatis二級(jí)緩存,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-05-05基于Spark實(shí)現(xiàn)隨機(jī)森林代碼
這篇文章主要為大家詳細(xì)介紹了基于Spark實(shí)現(xiàn)隨機(jī)森林代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-08-08springboot中的controller注意事項(xiàng)說明
這篇文章主要介紹了springboot中的controller注意事項(xiàng)說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03Java數(shù)據(jù)結(jié)構(gòu)及算法實(shí)例:插入排序 Insertion Sort
這篇文章主要介紹了Java數(shù)據(jù)結(jié)構(gòu)及算法實(shí)例:插入排序 Insertion Sort,本文直接給出實(shí)例代碼,代碼中包含詳細(xì)注釋,需要的朋友可以參考下2015-06-06