Mybatis-Plus 自定义 Mapper

1. 问题

在真实的使用过程中,可能不同的 mapper 接口使用的 sqlSessionFactory 不一样。就比如下面这个例子。

1
2
3
4
5
6
7
8
9
// 这个注解虽然可以指定 sqlSessionFactory, 但是最终使用的 configuration 对象是同一份。
@MapperScan("com.ooooo.**.mapper1")
@MapperScan("com.ooooo.**.mapper2")
public class DemoApplication {

  public static void main(String[] args) {
    SpringApplication.run(DemoApplication.class, args);
  }
}

2. 解决方式

可以使用 MapperFactoryBean 来扩展,下面我给出相应的示例代码。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
@Configuration
public class ComponentConfigMybatiPlusConfiguration {

  @Getter
  public static SqlSessionFactory sqlSessionFactory;
  
  @Bean
  public MapperFactoryBean<ComponentTreeMapper> componentTreeMapper() {
    return createMapper(ComponentTreeMapper.class);
  }

  private <T> MapperFactoryBean<T> createMapper(Class<T> clazz) {
    MapperFactoryBean<T> factoryBean = new MapperFactoryBean<>(clazz);
    factoryBean.setSqlSessionFactory(sqlSessionFactory());
    return factoryBean;
  }

  private synchronized SqlSessionFactory sqlSessionFactory() {
    if (sqlSessionFactory != null) {
      return sqlSessionFactory;
    }
    // 使用默认的dataSource
    DataSource dataSource = SpringUtil.getBean(DataSource.class);

    Environment environment = new Environment(COMPONENT_CONFIG, new SpringManagedTransactionFactory(), dataSource);
    // build configuration
    MybatisConfiguration configuration = new MybatisConfiguration();
    configuration.setEnvironment(environment);
    configuration.setCacheEnabled(false);
    configuration.setLocalCacheScope(LocalCacheScope.STATEMENT);
    setInterceptors(configuration);
    setMapperLocations(configuration, new String[]{"classpath*:/mapper/**/*.xml"});
    setGlobalConfig(configuration);
    // factory
    sqlSessionFactory = new MybatisSqlSessionFactoryBuilder().build(configuration);
    return sqlSessionFactory;
  }

  private void setInterceptors(MybatisConfiguration configuration) {
    MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
    mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
    configuration.addInterceptor(mybatisPlusInterceptor);
  }

  private void setMapperLocations(MybatisConfiguration configuration, String[] mapperLocations) {
    ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();
    for (String mapperLocation : mapperLocations) {
      try {
        Resource[] resources = resourceResolver.getResources(mapperLocation);
        for (Resource resource : resources) {
          if (resource.exists()) {
            XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(resource.getInputStream(),
                configuration, resource.toString(), configuration.getSqlFragments());
            xmlMapperBuilder.parse();
          }
        }
      } catch (IOException ignored) {
      }
    }
  }

  private void setGlobalConfig(MybatisConfiguration configuration) {
    GlobalConfig globalConfig = GlobalConfigUtils.getGlobalConfig(configuration);
    // MetaObjectHandler
    globalConfig.setMetaObjectHandler(new ComponentMetaObjectHandler());
  }
}

手动创建 Mapper

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// 用法
DataSource dataSource = DBUtil.buildDataSource(dbProperties);
SqlSession sqlSession = DBUtil.buildSqlSession(dbProperties.getName(), dataSource,
        MockInfoMapper.class);
mockInfoMapper = sqlSession.getMapper(MockInfoMapper.class);

// 工具类
public class DBUtil {

    public static DataSource buildDataSource(AbstractDBProperties dbProperties) {
        HikariConfig config = new HikariConfig();
        config.setPoolName("pool-" + dbProperties.getName());
        config.setDriverClassName(dbProperties.getDriverClassName());
        config.setJdbcUrl(dbProperties.getUrl());
        config.setUsername(dbProperties.getUsername());
        config.setPassword(dbProperties.getPassword());
        return new HikariDataSource(config);
    }

    public static SqlSessionTemplate buildSqlSession(String id, DataSource dataSource, Class<?>... mapperClazz) {
        Environment environment = new Environment(id, new SpringManagedTransactionFactory(), dataSource);
        MybatisConfiguration configuration = new MybatisConfiguration(environment);
        if (ArrayUtil.isNotEmpty(mapperClazz)) {
            for (Class<?> clazz : mapperClazz) {
                configuration.addMapper(clazz);
            }
        }
        configuration.addInterceptor(buildInterceptor());
        SqlSessionFactory sqlSessionFactory = new MybatisSqlSessionFactoryBuilder().build(configuration);
        return new SqlSessionTemplate(sqlSessionFactory);
    }

    private static MybatisPlusInterceptor buildInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        return interceptor;
    }
}
0%