您好,登錄后才能下訂單哦!
這篇文章主要介紹了Mybatis多線程下使用Example的案例,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
前言
服務器每收到一個請求,都會從線程池中調度一個空閑線程來處理,spring整合的web時,controller和service一般都是單例的,這樣導致無論你的Example標注的是單例還是多例,同一個service下的Example也只有一個,多線程訪問時產生的
問題如下
問題詳情
工程目錄結構如下
MyService 的service()方法接收兩個參數并據此查詢數據庫
@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執行查詢操作前就已經執行完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管理
@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
創建一個類實現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; }}
結果
至此,整個改造完成,看看效果
請求1
請求2
每個請求獲取到了不同的StudentExample,也就不存在沖突的問題,并且StudentExample沒有大量的創建與銷毀,最多只創建了與服務器線程池中線程相同的個數,實現了重復使用
感謝你能夠認真閱讀完這篇文章,希望小編分享的“Mybatis多線程下使用Example的案例”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。