Mybatis多線程下如何使用Example詳解
前言
服務器每收到一個請求,都會從線程池中調度一個空閑線程來處理,spring整合的web時,controller和service一般都是單例的,這樣導致無論你的Example標注的是單例還是多例,同一個service下的Example也只有一個,多線程訪問時產生的
問題如下
問題詳情
工程目錄結構如下

MyService 的service()方法接收兩個參數并據此查詢數據庫
@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);
}
}
當同時有兩個請求時,兩個請求的StudentExample相同
請求1如下
begin=2,end=8

請求2如下
begin=4,end=8

先放行請求1,請求1成功添加條件

再放行請求2,請求2添加失敗

這時如果請求2在請求1執(zhí)行查詢操作前就已經執(zhí)行完studentExample.clear (),請求1的查詢條件就失效了

至此兩個請求都沒有得到正確的結果。
解決方案
可以使用ThreadLocal為每個線程配備單獨的Example,為保證每次都能獲取到值,這里對ThreadLocal簡單擴展一下,如果當前線程沒有對應的Example(多例),就從spring容器中獲取一個并與這個線程綁定。
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會有很多個,所以這里使用了泛型,spring4.0提供了對泛型依賴注入的支持。
首先實際類型對應的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)建一個類實現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;
}
}
結果
至此,整個改造完成,看看效果
請求1

請求2

每個請求獲取到了不同的StudentExample,也就不存在沖突的問題,并且StudentExample沒有大量的創(chuàng)建與銷毀,最多只創(chuàng)建了與服務器線程池中線程相同的個數,實現了重復使用
總結
以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對腳本之家的支持。
相關文章
SpringBoot結合JSR303對前端數據進行校驗的示例代碼
這篇文章主要介紹了SpringBoot結合JSR303對前端數據進行校驗的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-09-09
Java爬蟲實現爬取京東上的手機搜索頁面 HttpCliient+Jsoup
下面小編就為大家分享一篇Java爬蟲實現爬取京東上的手機搜索頁面 HttpCliient+Jsoup,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2017-11-11
java 靜態(tài)工廠代替多參構造器的適用情況與優(yōu)劣
這篇文章主要介紹了java 靜態(tài)工廠代替多參構造器的優(yōu)劣,幫助大家更好的理解和使用靜態(tài)工廠方法,感興趣的朋友可以了解下2020-12-12
SpringBoot項目中@RestControllerAdvice全局異常失效問題的解決
@RestController注解是一個用于定義RESTful Web服務的控制器的特殊注解,它是@Controller和@ResponseBody注解的結合體,意味著你不需要在每個處理請求的方法上都添加@ResponseBody,本文給大家介紹了解決SpringBoot項目中@RestControllerAdvice全局異常失效問題2024-11-11

