You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot双数据库配置:仅更新指定库Schema,另一个设为只读

解决Spring Boot多数据源下Schema更新权限控制问题

你现在遇到的问题是两个数据源都被JPA自动更新Schema,想要让其中一个(application.properties配置的)负责更新,另一个只读不修改Schema。核心原因是JPA的ddl-auto默认是全局生效的,所以得给第二个数据源单独配置JPA属性,或者改用非JPA的方式操作它。

下面分两种场景给你解决方案:

场景1:第二个数据源需要使用JPA Repository

如果你的第二个数据库还是要通过JPA的Repository接口来操作,那需要给它单独配置一套JPA组件,禁用Schema更新:

第一步:调整application.properties配置

把要负责Schema更新的数据源设为默认数据源,全局JPA配置只应用到它:

# 默认数据源(负责Schema更新)
spring.datasource.url=jdbc:mysql://10.10.10:3306/db1
spring.datasource.username=user
spring.datasource.password=pass
spring.datasource.driverClassName=com.mysql.jdbc.Driver

# 默认JPA配置(仅作用于默认数据源)
spring.jpa.database-platform=org.hibernate.dialect.MySQL5Dialect
spring.jpa.hibernate.ddl-auto=update

第二步:修改第二个数据源的配置类

给第二个数据源创建独立的EntityManagerFactory和TransactionManager,明确禁用Schema更新:

@Configuration
@EnableJpaRepositories(
        basePackages = "com.yourproject.secondrepo", // 替换成你第二个数据源对应的Repository包路径
        entityManagerFactoryRef = "secondEntityManagerFactory",
        transactionManagerRef = "secondTransactionManager"
)
public class SecondDbConnectionConfig {

    @Bean(name = "secondDataSource")
    public DriverManagerDataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setUrl("jdbc:mysql://20.20.20:3306/db2");
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUsername("user");
        dataSource.setPassword("pass");
        return dataSource;
    }

    @Bean(name = "secondEntityManagerFactory")
    public LocalContainerEntityManagerFactoryBean secondEntityManagerFactory(
            EntityManagerFactoryBuilder builder,
            @Qualifier("secondDataSource") DataSource dataSource) {
        Map<String, Object> jpaProperties = new HashMap<>();
        // 关键:禁用这个数据源的Schema更新
        jpaProperties.put("hibernate.hbm2ddl.auto", "none");
        jpaProperties.put("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");

        return builder
                .dataSource(dataSource)
                .packages("com.yourproject.secondentity") // 替换成第二个数据源对应的实体类包路径(如果有的话)
                .persistenceUnit("secondDb")
                .properties(jpaProperties)
                .build();
    }

    @Bean(name = "secondTransactionManager")
    public PlatformTransactionManager secondTransactionManager(
            @Qualifier("secondEntityManagerFactory") EntityManagerFactory entityManagerFactory) {
        return new JpaTransactionManager(entityManagerFactory);
    }
}

场景2:第二个数据源仅做只读JDBC操作

如果第二个数据库只需要执行简单的SQL查询,不需要JPA实体映射,那直接用JdbcTemplate更简单,完全不会触发Schema更新:

修改第二个数据源的配置类如下:

@Configuration
public class SecondDbConnectionConfig {

    @Bean(name = "secondDataSource")
    public DriverManagerDataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setUrl("jdbc:mysql://20.20.20:3306/db2");
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUsername("user");
        dataSource.setPassword("pass");
        return dataSource;
    }

    @Bean(name = "secondJdbcTemplate")
    public JdbcTemplate secondJdbcTemplate(@Qualifier("secondDataSource") DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }
}

之后在需要操作第二个数据库的地方,用@Autowired @Qualifier("secondJdbcTemplate")注入JdbcTemplate即可,所有操作都是纯JDBC,不会涉及任何Schema修改。

验证方式

启动应用后,检查db2的表结构,应该不会有任何新增/修改的痕迹,而db1的表会正常根据你的领域模型更新。

内容的提问来源于stack exchange,提问作者jarosik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 08:52:55