spring与mybatis整合 我这里就用springboot举例了 首先从
@MapperScan注解开始
当我们使用这个注解时 spring会导入一个处理类
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Import({MapperScannerRegistrar.class})
public @interface MapperScan {
String[] value() default {};
String[] basePackages() default {};
Class<?>[] basePackageClasses() default {};
Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
Class<? extends Annotation> annotationClass() default Annotation.class;
Class<?> markerInterface() default Class.class;
String sqlSessionTemplateRef() default "";
String sqlSessionFactoryRef() default "";
Class<? extends MapperFactoryBean> factoryBean() default MapperFactoryBean.class;
}
点开MapperScannerRegistrar进入 其实现了 ImportBeanDefinitionRegistrar, ResourceLoaderAware 这两个接口
这两个接口中对于扩展spring起到很重要作用 我就不细说了 我们关注 ImportBeanDefinitionRegistrar的实现接口 此接口会在spring启动时创建组件定义完成时调用 :
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
AnnotationAttributes annoAttrs = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(MapperScan.class.getName()));
ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
if (this.resourceLoader != null) {
scanner.setResourceLoader(this.resourceLoader);
}
Class<? extends Annotation> annotationClass = annoAttrs.getClass("annotationClass");
if (!Annotation.class.equals(annotationClass)) {
scanner.setAnnotationClass(annotationClass);
}
Class<?> markerInterface = annoAttrs.getClass("markerInterface");
if (!Class.class.equals(markerInterface)) {
scanner.setMarkerInterface(markerInterface);
}
Class<? extends BeanNameGenerator> generatorClass = annoAttrs.getClass("nameGenerator");
if (!BeanNameGenerator.class.equals(generatorClass)) {
scanner.setBeanNameGenerator((BeanNameGenerator)BeanUtils.instantiateClass(generatorClass));
}
Class<? extends MapperFactoryBean> mapperFactoryBeanClass = annoAttrs.getClass("factoryBean");
if (!MapperFactoryBean.class.equals(mapperFactoryBeanClass)) {
scanner.setMapperFactoryBean((MapperFactoryBean)BeanUtils.instantiateClass(mapperFactoryBeanClass));
}
scanner.setSqlSessionTemplateBeanName(annoAttrs.getString("sqlSessionTemplateRef"));
scanner.setSqlSessionFactoryBeanName(annoAttrs.getString("sqlSessionFactoryRef"));
List<String> basePackages = new ArrayList();
String[] var10 = annoAttrs.getStringArray("value");
int var11 = var10.length;
int var12;
String pkg;
for(var12 = 0; var12 < var11; ++var12) {
pkg = var10[var12];
if (StringUtils.hasText(pkg)) {
basePackages.add(pkg);
}
}
var10 = annoAttrs.getStringArray("basePackages");
var11 = var10.length;
for(var12 = 0; var12 < var11; ++var12) {
pkg = var10[var12];
if (StringUtils.hasText(pkg)) {
basePackages.add(pkg);
}
}
Class[] var14 = annoAttrs.getClassArray("basePackageClasses");
var11 = var14.length;
for(var12 = 0; var12 < var11; ++var12) {
Class<?> clazz = var14[var12];
basePackages.add(ClassUtils.getPackageName(clazz));
}
scanner.registerFilters();
scanner.doScan(StringUtils.toStringArray(basePackages));
}
public void setResourceLoader(ResourceLoader resourceLoader) {
//这个类可以帮助我们从文件系统中查找字节码文件
this.resourceLoader = resourceLoader;
}
}
这段代码主要就是new了一个ClassPathMapperScanner 并往其中添加一了些属性
ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
进入到此类的 doScan():
public Set<BeanDefinitionHolder> doScan(String... basePackages) { //不用管 大概就是从我们的项目中扫描到我们指定包下面的mapper接口类 并包装成BeanDefinitionHolder 添加到一个set里面返回 Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages); if (beanDefinitions.isEmpty()) { this.logger.warn("No MyBatis mapper was found in '" + Arrays.toString(basePackages) + "' package. Please check your configuration."); } else { //这个是重点 怎么处理我们的mapper接口 this.processBeanDefinitions(beanDefinitions); } return beanDefinitions; } private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) { Iterator var3 = beanDefinitions.iterator(); while(var3.hasNext()) { BeanDefinitionHolder holder = (BeanDefinitionHolder)var3.next(); GenericBeanDefinition definition = (GenericBeanDefinition)holder.getBeanDefinition(); if (this.logger.isDebugEnabled()) { this.logger.debug("Creating MapperFactoryBean with name '" + holder.getBeanName() + "' and '" + definition.getBeanClassName() + "' mapperInterface"); } //重点: 设置这个类的构造参数 参数为我们的接口类 definition.getConstructorArgumentValues().addGenericArgumentValue(definition.getBeanClassName()); //重点: 将包装接口类的beanClass替换为实现了FactoryBean接口的MapperFactoryBean的类 (不懂的可以了解下FactoryBean接口) 这样容器启动完成 我们接口的mappper 就全部替换成该接口对应的MapperFactoryBean了 达到偷天换日的作用 名字还是原来的 但是 实现其实已经改变了 后面我们就重点关注MapperFactoryBean这个类了 就是这个类帮我们得到可以与mybatis交互的SqlSession了。 definition.setBeanClass(this.mapperFactoryBean.getClass()); definition.getPropertyValues().add("addToConfig", this.addToConfig); boolean explicitFactoryUsed = false; //重点: 为MapperFactoryBean的属性赋值 if (StringUtils.hasText(this.sqlSessionFactoryBeanName)) { definition.getPropertyValues().add("sqlSessionFactory", new RuntimeBeanReference(this.sqlSessionFactoryBeanName)); explicitFactoryUsed = true; } else if (this.sqlSessionFactory != null) { definition.getPropertyValues().add("sqlSessionFactory", this.sqlSessionFactory); explicitFactoryUsed = true; } if (StringUtils.hasText(this.sqlSessionTemplateBeanName)) { if (explicitFactoryUsed) { this.logger.warn("Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored."); } definition.getPropertyValues().add("sqlSessionTemplate", new RuntimeBeanReference(this.sqlSessionTemplateBeanName)); explicitFactoryUsed = true; } else if (this.sqlSessionTemplate != null) { if (explicitFactoryUsed) { this.logger.warn("Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored."); } definition.getPropertyValues().add("sqlSessionTemplate", this.sqlSessionTemplate); explicitFactoryUsed = true; } if (!explicitFactoryUsed) { if (this.logger.isDebugEnabled()) { this.logger.debug("Enabling autowire by type for MapperFactoryBean with name '" + holder.getBeanName() + "'."); } definition.setAutowireMode(2); } } }
进入到MapperFactoryBean 它实现了 SqlSessionDaoSupport , FactoryBean
public class MapperFactoryBean<T> extends SqlSessionDaoSupport implements FactoryBean<T> { private Class<T> mapperInterface; private boolean addToConfig = true; public MapperFactoryBean() { } //请注意 这个构造参数 前面已经声明实例化时会调用此构造参数 参数就是我们的mapper接口类 public MapperFactoryBean(Class<T> mapperInterface) { this.mapperInterface = mapperInterface; } //类初始化时会调用 向mybatis注册mapper protected void checkDaoConfig() { super.checkDaoConfig(); Assert.notNull(this.mapperInterface, "Property 'mapperInterface' is required"); Configuration configuration = this.getSqlSession().getConfiguration(); if (this.addToConfig && !configuration.hasMapper(this.mapperInterface)) { try { configuration.addMapper(this.mapperInterface); } catch (Exception var6) { this.logger.error("Error while adding the mapper '" + this.mapperInterface + "' to configuration.", var6); throw new IllegalArgumentException(var6); } finally { ErrorContext.instance().reset(); } } } //重点: 我们向容器注册就是 这个方法返回的对象 很明显我们的接口被替换成这个方法返回的的值 请注意这里的 this.getSqlSession() 为实现了SqlSession的SqlSessionTemplate。 public T getObject() throws Exception { return this.getSqlSession().getMapper(this.mapperInterface); } public Class<T> getObjectType() { return this.mapperInterface; } public boolean isSingleton() { return true; } public void setMapperInterface(Class<T> mapperInterface) { this.mapperInterface = mapperInterface; } public Class<T> getMapperInterface() { return this.mapperInterface; } public void setAddToConfig(boolean addToConfig) { this.addToConfig = addToConfig; } public boolean isAddToConfig() { return this.addToConfig; } } 进入到this.getSqlSession()这个方法中 位置为mapperFactoryBean的父类SqlSessionDaoSupport中:
public abstract class SqlSessionDaoSupport extends DaoSupport { private SqlSession sqlSession; private boolean externalSqlSession; public SqlSessionDaoSupport() { } //注意: 前面声明的属性赋值会在这个方法中调用 public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) { if (!this.externalSqlSession) { //关键点:new了一个 SqlSessionTemplate this.sqlSession = new SqlSessionTemplate(sqlSessionFactory); } } public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) { this.sqlSession = sqlSessionTemplate; this.externalSqlSession = true; } public SqlSession getSqlSession() { return this.sqlSession; } protected void checkDaoConfig() { Assert.notNull(this.sqlSession, "Property 'sqlSessionFactory' or 'sqlSessionTemplate' are required"); } }
我们进入 SqlSessionTemplate去:
public class SqlSessionTemplate implements SqlSession, DisposableBean { private final SqlSessionFactory sqlSessionFactory; private final ExecutorType executorType; //SqlSession的代理类 它帮助我查询sql 详情请看最下面的解析 private final SqlSession sqlSessionProxy; private final PersistenceExceptionTranslator exceptionTranslator; //请注意 我们采用的是这个构造方法 它采用了默认的执行器也就是SIMPLE 这也就是我们不能动态声明执行器类型的原因了 public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory) { this(sqlSessionFactory, sqlSessionFactory.getConfiguration().getDefaultExecutorType()); } public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType) { this(sqlSessionFactory, executorType, new MyBatisExceptionTranslator(sqlSessionFactory.getConfiguration().getEnvironment().getDataSource(), true)); } public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator) { Assert.notNull(sqlSessionFactory, "Property 'sqlSessionFactory' is required"); Assert.notNull(executorType, "Property 'executorType' is required"); this.sqlSessionFactory = sqlSessionFactory; this.executorType = executorType; this.exceptionTranslator = exceptionTranslator; this.sqlSessionProxy = (SqlSession)Proxy.newProxyInstance(SqlSessionFactory.class.getClassLoader(), new Class[]{SqlSession.class}, new SqlSessionTemplate.SqlSessionInterceptor()); } public SqlSessionFactory getSqlSessionFactory() { return this.sqlSessionFactory; } public ExecutorType getExecutorType() { return this.executorType; } public PersistenceExceptionTranslator getPersistenceExceptionTranslator() { return this.exceptionTranslator; } public <T> T selectOne(String statement) { return this.sqlSessionProxy.selectOne(statement); } public <T> T selectOne(String statement, Object parameter) { return this.sqlSessionProxy.selectOne(statement, parameter); } public <K, V> Map<K, V> selectMap(String statement, String mapKey) { return this.sqlSessionProxy.selectMap(statement, mapKey); } public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey) { return this.sqlSessionProxy.selectMap(statement, parameter, mapKey); } public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds) { return this.sqlSessionProxy.selectMap(statement, parameter, mapKey, rowBounds); } public <T> Cursor<T> selectCursor(String statement) { return this.sqlSessionProxy.selectCursor(statement); } public <T> Cursor<T> selectCursor(String statement, Object parameter) { return this.sqlSessionProxy.selectCursor(statement, parameter); } public <T> Cursor<T> selectCursor(String statement, Object parameter, RowBounds rowBounds) { return this.sqlSessionProxy.selectCursor(statement, parameter, rowBounds); } public <E> List<E> selectList(String statement) { return this.sqlSessionProxy.selectList(statement); } public <E> List<E> selectList(String statement, Object parameter) { return this.sqlSessionProxy.selectList(statement, parameter); } public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) { return this.sqlSessionProxy.selectList(statement, parameter, rowBounds); } public void select(String statement, ResultHandler handler) { this.sqlSessionProxy.select(statement, handler); } public void select(String statement, Object parameter, ResultHandler handler) { this.sqlSessionProxy.select(statement, parameter, handler); } public void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler) { this.sqlSessionProxy.select(statement, parameter, rowBounds, handler); } public int insert(String statement) { return this.sqlSessionProxy.insert(statement); } public int insert(String statement, Object parameter) { return this.sqlSessionProxy.insert(statement, parameter); } public int update(String statement) { return this.sqlSessionProxy.update(statement); } public int update(String statement, Object parameter) { return this.sqlSessionProxy.update(statement, parameter); } public int delete(String statement) { return this.sqlSessionProxy.delete(statement); } public int delete(String statement, Object parameter) { return this.sqlSessionProxy.delete(statement, parameter); } public <T> T getMapper(Class<T> type) { return this.getConfiguration().getMapper(type, this); } public void commit() { throw new UnsupportedOperationException("Manual commit is not allowed over a Spring managed SqlSession"); } public void commit(boolean force) { throw new UnsupportedOperationException("Manual commit is not allowed over a Spring managed SqlSession"); } public void rollback() { throw new UnsupportedOperationException("Manual rollback is not allowed over a Spring managed SqlSession"); } public void rollback(boolean force) { throw new UnsupportedOperationException("Manual rollback is not allowed over a Spring managed SqlSession"); } public void close() { throw new UnsupportedOperationException("Manual close is not allowed over a Spring managed SqlSession"); } public void clearCache() { this.sqlSessionProxy.clearCache(); } public Configuration getConfiguration() { return this.sqlSessionFactory.getConfiguration(); } public Connection getConnection() { return this.sqlSessionProxy.getConnection(); } public List<BatchResult> flushStatements() { return this.sqlSessionProxy.flushStatements(); } public void destroy() throws Exception { } //注意 SqlSession的代理类 我们的sql操作就是它帮助我们完成的 private class SqlSessionInterceptor implements InvocationHandler { private SqlSessionInterceptor() { } //重点 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //拿到SqlSession (没有事务则每次都要打开一个新的 有则从事务中拿取原来的哪一个 这也是为什么有时候没有事务的时候 我们的mybatis一级缓存失效的原因 ) SqlSession sqlSession = SqlSessionUtils.getSqlSession(SqlSessionTemplate.this.sqlSessionFactory, SqlSessionTemplate.this.executorType, SqlSessionTemplate.this.exceptionTranslator); Object unwrapped; try { Object result = method.invoke(sqlSession, args); if (!SqlSessionUtils.isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) { sqlSession.commit(true); } unwrapped = result; } catch (Throwable var11) { unwrapped = ExceptionUtil.unwrapThrowable(var11); if (SqlSessionTemplate.this.exceptionTranslator != null && unwrapped instanceof PersistenceException) { SqlSessionUtils.closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory); sqlSession = null; Throwable translated = SqlSessionTemplate.this.exceptionTranslator.translateExceptionIfPossible((PersistenceException)unwrapped); if (translated != null) { unwrapped = translated; } } throw (Throwable)unwrapped; } finally { if (sqlSession != null) { SqlSessionUtils.closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory); } } return unwrapped; } } }
大概就是这样啦!
回到开始的问题我们怎么可以动态指定mapper的执行器?答案就是我们在new SqlSessionTemplate的时候根据接口指定一个执行器。具体做法多样。我这里是自己写了一个注解 一个MyClassPathMapperScanner(为什么不继承原先的的 ?因为原先的很多属性是私有的 无法更改与获取)一个继承MapperFactoryBean的类MyMapperFactoryBean
注解如下 :打在mapper接口类上
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ExecutorType {
org.apache.ibatis.session.ExecutorType value() default org.apache.ibatis.session.ExecutorType.SIMPLE;
}
MyClassPathMapperScanner如下:
public class MyClassPathMapperScanner extends ClassPathBeanDefinitionScanner {
private boolean addToConfig = true;
private SqlSessionFactory sqlSessionFactory;
private SqlSessionTemplate sqlSessionTemplate;
private String sqlSessionTemplateBeanName;
private String sqlSessionFactoryBeanName;
private Class<? extends Annotation> annotationClass;
private Class<?> markerInterface;
private MapperFactoryBean<?> mapperFactoryBean = new MapperFactoryBean();
public MyClassPathMapperScanner(BeanDefinitionRegistry registry) {
super(registry, false);
}
public void setAddToConfig(boolean addToConfig) {
this.addToConfig = addToConfig;
}
public void setAnnotationClass(Class<? extends Annotation> annotationClass) {
this.annotationClass = annotationClass;
}
public void setMarkerInterface(Class<?> markerInterface) {
this.markerInterface = markerInterface;
}
public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
this.sqlSessionFactory = sqlSessionFactory;
}
public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
this.sqlSessionTemplate = sqlSessionTemplate;
}
public void setSqlSessionTemplateBeanName(String sqlSessionTemplateBeanName) {
this.sqlSessionTemplateBeanName = sqlSessionTemplateBeanName;
}
public void setSqlSessionFactoryBeanName(String sqlSessionFactoryBeanName) {
this.sqlSessionFactoryBeanName = sqlSessionFactoryBeanName;
}
public void setMapperFactoryBean(MapperFactoryBean<?> mapperFactoryBean) {
this.mapperFactoryBean = mapperFactoryBean != null ? mapperFactoryBean : new MapperFactoryBean();
}
public void registerFilters() {
boolean acceptAllInterfaces = true;
if (this.annotationClass != null) {
this.addIncludeFilter(new AnnotationTypeFilter(this.annotationClass));
acceptAllInterfaces = false;
}
if (this.markerInterface != null) {
this.addIncludeFilter(new AssignableTypeFilter(this.markerInterface) {
protected boolean matchClassName(String className) {
return false;
}
});
acceptAllInterfaces = false;
}
if (acceptAllInterfaces) {
this.addIncludeFilter(new TypeFilter() {
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
return true;
}
});
}
this.addExcludeFilter(new TypeFilter() {
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
String className = metadataReader.getClassMetadata().getClassName();
return className.endsWith("package-info");
}
});
}
public Set<BeanDefinitionHolder> doScan(String... basePackages) {
Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages);
if (beanDefinitions.isEmpty()) {
this.logger.warn("No MyBatis mapper was found in '" + Arrays.toString(basePackages) + "' package. Please check your configuration.");
} else {
this.processBeanDefinitions(beanDefinitions);
}
return beanDefinitions;
}
private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) {
Iterator var3 = beanDefinitions.iterator();
while(var3.hasNext()) {
BeanDefinitionHolder holder = (BeanDefinitionHolder)var3.next();
GenericBeanDefinition definition = (GenericBeanDefinition)holder.getBeanDefinition();
if (this.logger.isDebugEnabled()) {
this.logger.debug("Creating MapperFactoryBean with name '" + holder.getBeanName() + "' and '" + definition.getBeanClassName() + "' mapperInterface");
}
String interfaceName=definition.getBeanClassName();
definition.getConstructorArgumentValues().addGenericArgumentValue(interfaceName);
definition.getPropertyValues().add("addToConfig", this.addToConfig);
boolean explicitFactoryUsed = false;
if (StringUtils.hasText(this.sqlSessionFactoryBeanName)) {
//请注意这里的代码 根据接口上的注解来决定采用那个代理类
try {
aClass = Class.forName(interfaceName);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
ExecutorType annotation = aClass.getAnnotation(ExecutorType.class);
if(annotation!=null){
definition.setBeanClass(MyMapperFactoryBean.class);
org.apache.ibatis.session.ExecutorType value = annotation.value();
definition.getPropertyValues().add("executorType", value);
definition.getPropertyValues().add("sqlSessionFactory", new RuntimeBeanReference(this.sqlSessionFactoryBeanName));
explicitFactoryUsed = true;
}else {
definition.setBeanClass(this.mapperFactoryBean.getClass());
definition.getPropertyValues().add("sqlSessionFactory", new RuntimeBeanReference(this.sqlSessionFactoryBeanName));
explicitFactoryUsed = true;
}
} else if (this.sqlSessionFactory != null) {
definition.getPropertyValues().add("sqlSessionFactory", this.sqlSessionFactory);
explicitFactoryUsed = true;
}
if (StringUtils.hasText(this.sqlSessionTemplateBeanName)) {
if (explicitFactoryUsed) {
this.logger.warn("Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored.");
}
definition.getPropertyValues().add("sqlSessionTemplate", new RuntimeBeanReference(this.sqlSessionTemplateBeanName));
explicitFactoryUsed = true;
} else if (this.sqlSessionTemplate != null) {
if (explicitFactoryUsed) {
this.logger.warn("Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored.");
}
definition.getPropertyValues().add("sqlSessionTemplate", this.sqlSessionTemplate);
explicitFactoryUsed = true;
}
if (!explicitFactoryUsed) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Enabling autowire by type for MapperFactoryBean with name '" + holder.getBeanName() + "'.");
}
definition.setAutowireMode(2);
}
}
}
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
return beanDefinition.getMetadata().isInterface() && beanDefinition.getMetadata().isIndependent();
}
protected boolean checkCandidate(String beanName, BeanDefinition beanDefinition) {
if (super.checkCandidate(beanName, beanDefinition)) {
return true;
} else {
this.logger.warn("Skipping MapperFactoryBean with name '" + beanName + "' and '" + beanDefinition.getBeanClassName() + "' mapperInterface. Bean already defined with the same name!");
return false;
}
}
}
MyMapperFactoryBean如下:重写了setSqlSessionFactory()方法
public class MyMapperFactoryBean<T> extends MapperFactoryBean {
private ExecutorType executorType;
private Map<String,Field> cache=new HashMap<>();
public MyMapperFactoryBean(Class mapperInterface) {
super(mapperInterface);
}
@Override
public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
SqlSessionTemplate sqlSessionTemplate=null;
if(executorType==null){
sqlSessionTemplate=new SqlSessionTemplate(sqlSessionFactory);
}else {
sqlSessionTemplate=new SqlSessionTemplate(sqlSessionFactory,executorType);
}
Field sqlSession=cache.get("sqlSession");
if(sqlSession==null) {
Class<SqlSessionDaoSupport> sqlSessionDaoSupportClass = SqlSessionDaoSupport.class;
try {
sqlSession = sqlSessionDaoSupportClass.getDeclaredField("sqlSession");
sqlSession.setAccessible(true);
cache.put("sqlSession",sqlSession);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
try {
sqlSession.set(this, sqlSessionTemplate);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
public ExecutorType getExecutorType() {
return executorType;
}
public void setExecutorType(ExecutorType executorType) {
this.executorType = executorType;
}
}
这样就可以达到我们的目标了 当然需要自己更改下@MapperScan注解处理器的逻辑 就不再细说了 下面来看看效果:
我的mapper
@ExecutorType(org.apache.ibatis.session.ExecutorType.BATCH) public interface TestMapper2 { int insert(Shop shop); }
效果:
完成 !