Mybatis多線程下如何使用Example詳解
前言
服務(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);
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)求都沒(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 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,也就不存在沖突的問(wèn)題,并且StudentExample沒(méi)有大量的創(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)文章
SpringBoot結(jié)合JSR303對(duì)前端數(shù)據(jù)進(jìn)行校驗(yàn)的示例代碼
這篇文章主要介紹了SpringBoot結(jié)合JSR303對(duì)前端數(shù)據(jù)進(jìn)行校驗(yàn)的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09
Java爬蟲實(shí)現(xiàn)爬取京東上的手機(jī)搜索頁(yè)面 HttpCliient+Jsoup
下面小編就為大家分享一篇Java爬蟲實(shí)現(xiàn)爬取京東上的手機(jī)搜索頁(yè)面 HttpCliient+Jsoup,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2017-11-11
java 靜態(tài)工廠代替多參構(gòu)造器的適用情況與優(yōu)劣
這篇文章主要介紹了java 靜態(tài)工廠代替多參構(gòu)造器的優(yōu)劣,幫助大家更好的理解和使用靜態(tài)工廠方法,感興趣的朋友可以了解下2020-12-12
SpringBoot整合thymeleaf 報(bào)錯(cuò)的解決方案
這篇文章主要介紹了SpringBoot整合thymeleaf 報(bào)錯(cuò)的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08
SpringBoot項(xiàng)目中@RestControllerAdvice全局異常失效問(wèn)題的解決
@RestController注解是一個(gè)用于定義RESTful Web服務(wù)的控制器的特殊注解,它是@Controller和@ResponseBody注解的結(jié)合體,意味著你不需要在每個(gè)處理請(qǐng)求的方法上都添加@ResponseBody,本文給大家介紹了解決SpringBoot項(xiàng)目中@RestControllerAdvice全局異常失效問(wèn)題2024-11-11
idea整合deepseek實(shí)現(xiàn)AI輔助編程的流程步驟
文章介紹了如何在IntelliJ IDEA中整合DeepSeek平臺(tái)實(shí)現(xiàn)AI輔助編程,步驟包括安裝CodeGPT插件、注冊(cè)DeepSeek開發(fā)者賬號(hào)、配置API密鑰以及設(shè)置API信息,需要的朋友可以參考下2025-02-02
spring-data-redis自定義實(shí)現(xiàn)看門狗機(jī)制
redission看門狗機(jī)制是解決分布式鎖的續(xù)約問(wèn)題,本文主要介紹了spring-data-redis自定義實(shí)現(xiàn)看門狗機(jī)制,具有一定的參考價(jià)值,感興趣的可以了解一下2024-03-03

