在 spring-mybatis 中使用类路径配置映射器位置:*

问题描述 投票:0回答:5

所以我希望这个能发挥作用

@Bean
@ConfigurationProperties("datasource.mybatis-factory")
public SqlSessionFactoryBean sqlSessionFactoryBean() {
  SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
  sqlSessionFactoryBean.setDataSource(dataSource());
  return sqlSessionFactoryBean;
}

拥有财产(除其他外)

datasource.mybatis-factory.mapper-locations=classpath*:sqlmap/*.xml

但是,即使文件在那里,它也会失败:

Caused by: java.io.FileNotFoundException: class path resource [classpath*:sqlmap/*.xml] cannot be opened because it does not exist

看着

setMapperLocations()
我没有做错任何事,他们显然希望我使用
classpath*:...

/**
 * Set locations of MyBatis mapper files that are going to be merged into the {@code SqlSessionFactory} configuration
 * at runtime.
 *
 * This is an alternative to specifying "<sqlmapper>" entries in an MyBatis config file. This property being
 * based on Spring's resource abstraction also allows for specifying resource patterns here: e.g.
 * "classpath*:sqlmap/*-mapper.xml".
 *
 * @param mapperLocations
 *          location of MyBatis mapper files
 */
public void setMapperLocations(Resource... mapperLocations) {
  this.mapperLocations = mapperLocations;
}

进一步查看代码,只有这样:

    for (Resource mapperLocation : this.mapperLocations) {
      if (mapperLocation == null) {
        continue;
      }
      try {
        XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(mapperLocation.getInputStream(),
            targetConfiguration, mapperLocation.toString(), targetConfiguration.getSqlFragments());
        xmlMapperBuilder.parse();

没有代码可以将

classpath*:sqlmap/*.xml
转换为可打开的资源,或者至少我没有看到它。或者我在这里错过了什么?

解决方法:
我现在拥有的和正在运行的(请注意,我不使用

datasource.mybatis-factory.mapper-locations
,因为这会再次覆盖我设置的内容):

@Bean
@ConfigurationProperties("datasource.mybatis-factory")
public SqlSessionFactoryBean sqlSessionFactoryBean(
    @Value("${datasource.mybatis-factory.mapper-location-pattern}") String mapperLocations) {
  SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
  sqlSessionFactoryBean.setDataSource(dataSource());
  sqlSessionFactoryBean.setMapperLocations(findMapperLocations(mapperLocations));
  return sqlSessionFactoryBean;
}

private Resource[] findMapperLocations(String resourcePaths) {
  PathMatchingResourcePatternResolver patternResolver = new PathMatchingResourcePatternResolver();
  return Stream.of(resourcePaths.split(","))
      .map(LambdaExceptionUtilities.rethrowFunction(patternResolver::getResources))
      .flatMap(Stream::of)
      .toArray(Resource[]::new);
}

有财产

datasource.mybatis-factory.mapper-location-pattern=classpath*:sqlmap/*.xml

那么:如果没有解决办法,这里缺少什么才能使其正常工作?类路径上的 XML 如何找到进入 MyBatis 的路径?也许 Spring-Bootish 缺少一些东西?

spring-boot mybatis spring-mybatis
5个回答
1
投票
我最近遇到了同样的问题。我相信这就是您正在寻找的:

@Bean @ConfigurationProperties("datasource.mybatis-factory") public SqlSessionFactoryBean sqlSessionFactoryBean( @Value("${datasource.mybatis-factory.mapper-location-pattern}") String mapperLocations) { SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); sqlSessionFactoryBean.setDataSource(dataSource()); sqlSessionFactoryBean.setMapperLocations( new PathMatchingResourcePatternResolver().getResources("classpath*:sqlmap/*.xml") ); return sqlSessionFactoryBean; }
基本上,您需要的是上面 @Bean 定义中的这行代码:

sqlSessionFactoryBean.setMapperLocations(

new PathMatchingResourcePatternResolver().getResources("classpath*:sqlmap/*.xml") ); 注意:方法名称是 getResource
s(复数)而不是 getResource

您可以随意将

classpath*:sqlmap/*.xml

 的硬编码值替换为 
@Value("datasource.mybatis-factory.mapper-location-pattern")
 注入值。

因为您将 MyBatis 与 Spring 一起使用,所以这里的问题与其说是 MyBatis 问题,不如说是 Spring 问题。更具体地说,您想要用来加载多个资源的通配符功能,即

classpath*:sqlmap/*.xml

 是 Spring 特有的,而不是 MyBatis 特有的。

我知道,MyBatis-Spring 文档中记录的方式可能会让您相信这是一个 MyBatis 功能,可以让您执行这种类型的通配符资源加载,但事实并非如此。这是 MyBatis-Spring 文档的相关部分(来源:

https://mybatis.org/spring/factorybean.html#properties):

mapperLocations 属性获取资源位置列表。该属性可用于指定 MyBatis XML 映射器文件的位置。

该值可以包含 Ant 样式模式来加载目录中的所有文件或从基本位置递归搜索所有路径。

然而,遗憾的是文档只提供了基于 XML 的 Spring 示例,而不是 Java 配置。如果您阅读

SqlSessionFactoryBean

 的 Java 文档,您会发现以下内容(来源: 
https://mybatis.org/spring/apidocs/org/mybatis/spring/SqlSessionFactoryBean.html#setMapperLocations(org.springframework. core.io.Resource...)):

public void setMapperLocations(org.springframework.core.io.Resource... mapperLocations) Set locations of MyBatis mapper files that are going to be merged into the SqlSessionFactory configuration at runtime. This is an alternative to specifying "<sqlmapper>" entries in an MyBatis config file. This property being based on Spring's resource abstraction also allows for specifying resource patterns here: e.g. "classpath*:sqlmap/*-mapper.xml". Parameters: mapperLocations - location of MyBatis mapper files
因此,

setMapperLocations

方法需要一个或多个
org.springframework.core.io.Resource
对象。因此,使用 Spring 
ClassPathResource
 在这里不起作用,因为 
ClassPathResource
 只需要单个资源。你需要使用 Spring 的 
PathMatchingResourcePatternResolver
 类。请参阅:
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/core/io/support/PathMatchingResourcePatternResolver.html

您可能还会发现这篇 Stack Overflow 帖子很有用:

如何在基于 Java 的 Spring 配置中搜索资源时使用通配符?

我希望这有帮助!


0
投票
尝试在 MybatisConfig 类中添加另一个方法,其返回类型为 MapperScannerConfiguerer,它将有助于从 mybatisConfig.xml 设置标签。

@Bean public MapperScannerConfigurer mapperScannerConfigurer(){ MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer(); mapperScannerConfigurer.setBasePackage("packagePath"); return mapperScannerConfigurer; }
    

-1
投票
你的财产应该是这样的。 如果您使用默认配置,

mybatis.mapper-locations: classpath*:sqlmap/**/*.xml
如果您使用上面提到的自己的,

datasource.mybatis-factory.mapper-locations= classpath*:sqlmap/**/*.xml
    

-1
投票
这是一个工作示例代码,您可以从中得到一些想法。

@Configuration @MapperScans( { @MapperScan( basePackages = {"com.example.seeker.repository"}, sqlSessionFactoryRef = "sqlSessionFactorySeeker", sqlSessionTemplateRef = "sqlSessionTemplateSeeker" ) } ) public class SeekerDataSourceConfig { @Autowired Environment environment; @Bean(value = "dsSeeker") @ConfigurationProperties(prefix = "spring.datasource.seeker") DataSource dsSeeker() { return DataSourceBuilder.create().build(); } @Qualifier("dsSeeker") @Autowired private DataSource dsSeeker; @Bean(value = "sqlSessionFactorySeeker") public SqlSessionFactory sqlSessionFactorySeeker() { SqlSessionFactory sessionFactory = null; try { SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); PathMatchingResourcePatternResolver pathM3R = new PathMatchingResourcePatternResolver(); bean.setMapperLocations(pathM3R.getResources("classpath*:sqlmap/**/*.xml")); bean.setDataSource(dsSeeker); sessionFactory = bean.getObject(); } catch (Exception e) { e.printStackTrace(); } return sessionFactory; } @Bean(value = "sqlSessionTemplateSeeker") public SqlSessionTemplate sqlSessionTemplateSeeker() { return new SqlSessionTemplate(sqlSessionFactorySeeker()); } @Bean(name = StaticResource.TxManager.TX_MANAGER_SEEKER) public PlatformTransactionManager txManager() { return new DataSourceTransactionManager(dsSeeker); } }
财产档案

spring.datasource.seeker.jdbc-url=jdbc:mysql://********* spring.datasource.seeker.username=seeker*** spring.datasource.seeker.password=ewfky4eyrmggxbw6** spring.datasource.seeker.driver-class-name=com.mysql.cj.jdbc.Driver
    

-1
投票
如果您想与

yml

 文件一起使用,您可以在以下路径中添加您的 application.yml 文件

mybatis: mapperLocations: classpath:sql/*.xml config-location: classpath:config/mybatis.xml
    
© www.soinside.com 2019 - 2024. All rights reserved.