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
相关产品推荐
相关产品推荐

