溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Mybatis多線程下使用Example的案例

發(fā)布時間:2021-03-05 15:19:32 來源:億速云 閱讀:146 作者:小新 欄目:編程語言

這篇文章主要介紹了Mybatis多線程下使用Example的案例,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

前言

服務(wù)器每收到一個請求,都會從線程池中調(diào)度一個空閑線程來處理,spring整合的web時,controller和service一般都是單例的,這樣導(dǎo)致無論你的Example標注的是單例還是多例,同一個service下的Example也只有一個,多線程訪問時產(chǎn)生的

問題如下

問題詳情

工程目錄結(jié)構(gòu)如下

MyService 的service()方法接收兩個參數(shù)并據(jù)此查詢數(shù)據(jù)庫

@Servicepublic 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í)行查詢操作前就已經(jīng)執(zhí)行完studentExample.clear (),請求1的查詢條件就失效了

至此兩個請求都沒有得到正確的結(jié)果。

解決方案

可以使用ThreadLocal為每個線程配備單獨的Example,為保證每次都能獲取到值,這里對ThreadLocal簡單擴展一下,如果當前線程沒有對應(yīng)的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提供了對泛型依賴注入的支持。

首先實際類型對應(yīng)的ThreadLocalExtension交由spring管理

@Repositorypublic class StudentExampleThreadLocal extends ThreadLocalExtension<StudentExample> {}

然后直接在代碼中注入

@AutowiredThreadLocalExtension<StudentExample> studentExampleThreadLocal;

修改后的MyService

@Servicepublic 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)建一個類實現(xiàn)ApplicationContextAware,并向spring容器中注入applicationContext

@Componentpublic 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é)果

至此,整個改造完成,看看效果

請求1

請求2

每個請求獲取到了不同的StudentExample,也就不存在沖突的問題,并且StudentExample沒有大量的創(chuàng)建與銷毀,最多只創(chuàng)建了與服務(wù)器線程池中線程相同的個數(shù),實現(xiàn)了重復(fù)使用

感謝你能夠認真閱讀完這篇文章,希望小編分享的“Mybatis多線程下使用Example的案例”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關(guān)注億速云行業(yè)資訊頻道,更多相關(guān)知識等著你來學(xué)習(xí)!

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI