当前位置 主页 > 网站技术 > 代码类 >

    Mybatis多线程下如何使用Example详解

    栏目:代码类 时间:2019-12-15 12:08

    前言

    服务器每收到一个请求,都会从线程池中调度一个空闲线程来处理,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执行查询操作前就已经执行完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);
      }
    }