Spring Boot多数据源(H2+MySQL):H2表未创建,访问提示表不存在
解决Spring Boot双数据源下H2数据库表未生成的问题
我之前也踩过双数据源配置的坑,你的情况核心问题就是自定义数据源时没有为H2单独配置实体扫描、DDL生成策略,导致Hibernate不知道要为H2数据源创建对应的表。下面是具体的排查和解决步骤:
1. 检查自定义数据源的实体扫描配置
每个数据源对应的EntityManagerFactory必须明确指定自己要扫描的实体包路径,不然Hibernate会混淆两个数据源的实体,甚至直接忽略H2的实体。
举个配置示例:
// H2数据源的EntityManager配置 @Bean(name = "h2EntityManagerFactory") public LocalContainerEntityManagerFactoryBean h2EntityManagerFactory( EntityManagerFactoryBuilder builder, @Qualifier("h2DataSource") DataSource dataSource) { return builder .dataSource(dataSource) .packages("com.yourproject.h2.entity") // 替换成你的H2实体所在包 .persistenceUnit("h2PU") // 给H2单独指定持久化单元 .build(); } // MySQL数据源的EntityManager配置 @Bean(name = "mysqlEntityManagerFactory") public LocalContainerEntityManagerFactoryBean mysqlEntityManagerFactory( EntityManagerFactoryBuilder builder, @Qualifier("mysqlDataSource") DataSource dataSource) { return builder .dataSource(dataSource) .packages("com.yourproject.mysql.entity") // 替换成你的MySQL实体所在包 .persistenceUnit("mysqlPU") // MySQL单独的持久化单元 .build(); }
2. 为H2单独配置DDL自动生成策略
全局的spring.jpa.hibernate.ddl-auto配置会被两个数据源共用,你需要给H2单独设置DDL生成规则(比如update或create),确保Hibernate会自动创建表。
第一步:在配置文件中拆分数据源配置(以YAML为例)
spring: datasource: mysql: url: jdbc:mysql://localhost:3306/ibdemo username: root password: your-mysql-pwd driver-class-name: com.mysql.cj.jdbc.Driver h2: url: jdbc:h2:mem:testdb username: sa password: driver-class-name: org.h2.Driver h2: console: enabled: true # 单独给H2配置JPA参数 h2: jpa: hibernate: ddl-auto: update properties: hibernate: dialect: org.hibernate.dialect.H2Dialect # MySQL的JPA参数 mysql: jpa: hibernate: ddl-auto: update properties: hibernate: dialect: org.hibernate.dialect.MySQL8Dialect
第二步:在EntityManagerFactory中加载对应配置
修改H2的EntityManager配置,加入DDL和方言参数:
@Bean(name = "h2EntityManagerFactory") public LocalContainerEntityManagerFactoryBean h2EntityManagerFactory( EntityManagerFactoryBuilder builder, @Qualifier("h2DataSource") DataSource dataSource, @Value("${h2.jpa.properties.hibernate.dialect}") String h2Dialect, @Value("${h2.jpa.hibernate.ddl-auto}") String h2DdlAuto) { Map<String, Object> h2Properties = new HashMap<>(); h2Properties.put("hibernate.dialect", h2Dialect); h2Properties.put("hibernate.hbm2ddl.auto", h2DdlAuto); return builder .dataSource(dataSource) .packages("com.yourproject.h2.entity") .persistenceUnit("h2PU") .properties(h2Properties) .build(); }
3. 配置对应数据源的事务管理器
每个数据源要绑定自己的事务管理器,避免操作H2时误用MySQL的事务管理器导致数据源混淆:
// H2事务管理器 @Bean(name = "h2TransactionManager") public PlatformTransactionManager h2TransactionManager( @Qualifier("h2EntityManagerFactory") EntityManagerFactory entityManagerFactory) { return new JpaTransactionManager(entityManagerFactory); } // MySQL事务管理器 @Bean(name = "mysqlTransactionManager") public PlatformTransactionManager mysqlTransactionManager( @Qualifier("mysqlEntityManagerFactory") EntityManagerFactory entityManagerFactory) { return new JpaTransactionManager(entityManagerFactory); }
之后在操作H2的Service方法上,指定使用H2的事务管理器:
@Transactional(value = "h2TransactionManager") public void saveH2Entity(H2Entity entity) { h2Repository.save(entity); }
4. 排除Spring Boot默认的数据源自动配置
在启动类上排除默认的数据源自动配置,避免自定义数据源被覆盖:
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class}) public class YourApplication { public static void main(String[] args) { SpringApplication.run(YourApplication.class, args); } }
按照上面的步骤配置后,Hibernate会为H2数据源单独扫描实体并生成表,同时MySQL的功能也能正常工作。
内容的提问来源于stack exchange,提问作者Ansar Samad
相关产品推荐
相关产品推荐

