【问题标题】:spring-data multiple data source configuration run but insert in wrong datasourcespring-data 多数据源配置运行但插入错误的数据源
【发布时间】:2017-11-03 11:04:57
【问题描述】:

配置

我已经按照本教程在spring-data中配置了两个数据源:

https://medium.com/@joeclever/using-multiple-datasources-with-spring-boot-and-spring-data-6430b00c02e7

tomcat启动,两个数据库用flyway初始化成功。

第一个DataSource配置是这样的

@Configuration
@EnableTransactionManagement
@EnableMybatisRepositories(
        value = "com.domain.api.userManagement.repository",
        mapperLocations = {
                "classpath*:/mappers/userManagement/*Mapper.xml",
                "classpath*:/beforemappers/userManagement/*Mapper.xml"
        }
)
public class UserManagementDbConfig {

    @Value("${api.db.userManagement.version}")
    private String version;

    @Primary
    @Bean(name = "dataSource")
    @ConfigurationProperties(prefix = "api.db.userManagement")
    public DataSource dataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    @Qualifier("userManagement")
    public PlatformTransactionManager transactionManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean
    public SqlSessionFactoryBean sqlSessionFactory() throws Exception {
        final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource());
        return sessionFactory;
    }


    @Bean
    public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }

    @Bean(initMethod = "migrate")
    public Flyway flyway() throws SQLException {
        Flyway flyway = new Flyway();
        flyway.setBaselineOnMigrate(true);
        flyway.setLocations("classpath:db/migration/userManagement");
        flyway.setSqlMigrationPrefix("V");
        flyway.setSqlMigrationSuffix(".sql");
        flyway.setEncoding("UTF-8");
        flyway.setValidateOnMigrate(false);
        flyway.setOutOfOrder(true);
        flyway.setTargetAsString(version);
        flyway.setDataSource(dataSource());
        return flyway;
    }
}

还有第二个DataSource:

@Configuration
@EnableTransactionManagement
@EnableMybatisRepositories(
        value = "com.domain.api.companyManagement.repository",
        mapperLocations = {
                "classpath*:/mappers/companyManagement/*Mapper.xml",
                "classpath*:/beforemappers/companyManagement/*Mapper.xml"
        }
)
public class CompanyManagementDbConfig {

    @Value("${api.db.companyManagement.version}")
    private String version;

    @Bean(name = "companyManagementDataSource")
    @ConfigurationProperties(prefix = "api.db.companyManagement")
    public DataSource dataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    @Qualifier("companyManagement")
    public PlatformTransactionManager transactionManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean(name = "companyManagementSqlSessionFactory")
    public SqlSessionFactoryBean sqlSessionFactory() throws Exception {
        final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource());
        return sessionFactory;
    }

    @Bean(name = "companyManagementSqlSessionTemplate")
    public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }


    @Bean(initMethod = "migrate", name = "companyManagementFlyway")
    public Flyway flyway() throws SQLException {
        Flyway flyway = new Flyway();
        flyway.setBaselineOnMigrate(true);
        flyway.setLocations("classpath:db/migration/companyManagement");
        flyway.setSqlMigrationPrefix("V");
        flyway.setSqlMigrationSuffix(".sql");
        flyway.setEncoding("UTF-8");
        flyway.setValidateOnMigrate(false);
        flyway.setOutOfOrder(true);
        flyway.setTargetAsString(version);
        flyway.setDataSource(dataSource());
        return flyway;
    }
}

这就是我编写负责插入的服务的方式:

@Service
public class TestServiceImpl extends AbstractCrudService<TestRepository, Test, Long> implements TestService {

  @Autowired
  public TestServiceImpl(TestRepository repository) {
    super(repository);
  }

  @Override
  @Transactional("companyManagement")
  public void insert(Test user) {
    super.insert(user);
  }

  @Override
  @Transactional("companyManagement")
  public void updateIgnore(Test user) {
    super.updateIgnore(user);
  }
}

application.yml:

server:
  port: 8080
  session:
    timeout: -1

api:
  db:
    userManagement:
      version: 0.0.17
      url: jdbc:postgresql://localhost:3333/UM?autoReconnect=true&useUnicode=true&connectionCollation=utf8_general_ci&characterSetResults=utf8&characterEncoding=UTF-8
      username: ******
      password: ******
      driver-class-name: org.postgresql.Driver
      minIdle: 0
      maxIdle: 10
      maxActive: 50
      maxWait: 6000
      testOnBorrow: true
      validationQuery: SELECT 1
      timeBetweenEvictionRunsMillis: 1800000
      numTestsPerEvictionRun: 50
      minEvictableIdleTimeMillis: 10
      testWhileIdle: true
    companyManagement:
      version: 0.0.17
      url: jdbc:postgresql://localhost:3334/CM?autoReconnect=true&useUnicode=true&connectionCollation=utf8_general_ci&characterSetResults=utf8&characterEncoding=UTF-8
      username: ******
      password: ******
      driver-class-name: org.postgresql.Driver
      minIdle: 0
      maxIdle: 10
      maxActive: 50
      maxWait: 6000
      testOnBorrow: true
      validationQuery: SELECT 1
      timeBetweenEvictionRunsMillis: 1800000
      numTestsPerEvictionRun: 50
      minEvictableIdleTimeMillis: 10
      testWhileIdle: true

结果

Fri Nov 03 17:18:46 ICT 2017
There was an unexpected error (type=Internal Server Error, status=500).
### Error updating database. Cause: org.postgresql.util.PSQLException: ERROR: relation "cm_test" does not exist Position: 13 ### The error may involve com.domain.api.companyManagement.domain.Test._insert-Inline ### The error occurred while setting parameters ### SQL: insert into "cm_test"("name") values(?) ### Cause: org.postgresql.util.PSQLException: ERROR: relation "cm_test" does not exist Position: 13 ; bad SQL grammar []; nested exception is org.postgresql.util.PSQLException: ERROR: relation "cm_test" does not exist Position: 13

此存储库应尝试插入第二个数据源,但它尝试使用第一个(主)数据源。

复制

网址:https://github.com/kopax/spring-data-mybatis-test 需要使用docker-compose up -d或者手动不使用docker启动这两个数据库。

您是如何设法使用多个 DataSource 的?

【问题讨论】:

  • 你能分享你的 application.yml/.properties 文件吗?
  • @TurbutAlin 我已经添加了我的application.yml的相关部分
  • 另外两件事: - 默认的 spring.datasource 呢?初始化了吗? - 您的配置类型中缺少 basePackages 扫描。我看到它有 mapperLocations。不确定这是否有用。也许我以后会找时间在本地尝试。
  • 我没有使用属性spring.datasource,而是使用api.db.userManagement。 basePackage 扫描发生在 Application.java 使用 @SpringBootApplication(scanBasePackages={"com.domain.api.userManagement","com.domain.api.companyManagement"})
  • 请为 transactionManager 添加限定符并将其用于您的。方法事务注释。

标签: java spring spring-mvc spring-data datasource


【解决方案1】:

如果使用两个 DB,则应创建并指定单独的 TransactionManager-s

@Bean(name = "companyTransactionManager")
public PlatformTransactionManager transactionManager() 
{
    return new DataSourceTransactionManager(dataSource());
}

RoleServiceImpl

 @Override
 @Transactional("companyTransactionManager", readOnly = true)
 public Role getByName(String name) {

【讨论】:

  • 用于命名 transactionManager 我应该使用@TurbutAlin 推荐的@Qualifier,还是您推荐的@Bean
  • @BigDong 您应该使用 Bean (name = ) 进行命名。限定符用于指定其中一些具有相同类型的具体 bean。见docs.spring.io/spring-framework/docs/current/javadoc-api/org/…
  • 我的接口没有public class UserServiceImpl extends AbstractCrudService&lt;UserRepository, User, Long&gt; implements UserService {}这样的方法,如何直接为所有方法设置transactionManager?
  • 在设置 @Bean(name = "myService") 和不使用 @Qualifier("namemyService") 后,我也会遇到类似 No qualifying bean of type 'org.springframework.transaction.PlatformTransactionManager' available: expected single matching bean but found 2: transactionManager,companyManagement 的问题。它使用正确的设置进行了不同的操作,但我无法实现可运行的示例
  • 对于没有方法问题的接口,我应该创建一个public abstract class AbstractCompanyManagementCrudService 并在此处注释我的DataSource 的所有方法吗?
【解决方案2】:

我认为您遇到了这个问题,因为您在两个配置中都有名称为 dataSorce 的 bean,并且在创建 Spring Context 之后,只能存在一个具有相同名称的 bean。尝试重命名你的豆子,也许这会对你有所帮助。

【讨论】:

    【解决方案3】:

    对我来说,问题是在我阅读的所有教程中,没有看到 transactionManager 需要 @Primary

    我在主数据库中的transactionManager 上添加@Primary 后,它就起作用了!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-04-30
      • 2021-03-16
      • 1970-01-01
      • 2018-01-04
      • 2018-09-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多