Spring Boot中基于JPA Repository配置单实体多数据源连接
Spring Boot JPA 单实体多数据源完整配置指南
你已经搭好了两个MySQL数据源的基础Bean,接下来咱们把剩下的配置补全,让同一个实体类能无缝对接两个数据源进行操作。下面是一步步的实操步骤:
1. 配置两个 EntityManagerFactory(对应不同数据源)
每个数据源都需要自己的EntityManagerFactory,用来管理实体和数据源的映射关系。注意给它们指定不同的persistenceUnitName,方便后续区分:
主数据源配置类
@Configuration @EnableJpaRepositories( basePackages = "com.yourpackage.repository", // 你的Repository所在包 entityManagerFactoryRef = "primaryEntityManagerFactory", transactionManagerRef = "primaryTransactionManager" ) public class PrimaryJpaConfig { @Autowired private Environment env; @Primary @Bean(name = "primaryEntityManagerFactory") public LocalContainerEntityManagerFactoryBean primaryEntityManagerFactory(EntityManagerFactoryBuilder builder) { return builder .dataSource(primaryDataSource()) .packages("com.yourpackage.entity") // 你的实体类所在包 .persistenceUnit("primaryPU") .properties(jpaProperties()) .build(); } @Primary @Bean public DataSource primaryDataSource() { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName(env.getProperty("mpfp.db.write.driver")); dataSource.setUrl(env.getProperty("mpfp.db.write.url")); dataSource.setUsername(env.getProperty("mpfp.db.write.username")); dataSource.setPassword(env.getProperty("mpfp.db.write.password")); return dataSource; } private Map<String, Object> jpaProperties() { Map<String, Object> props = new HashMap<>(); props.put("hibernate.hbm2ddl.auto", env.getProperty("spring.jpa.hibernate.ddl-auto")); props.put("hibernate.show_sql", env.getProperty("spring.jpa.show-sql")); // 其他JPA配置按需添加 return props; } }
从数据源配置类
@Configuration @EnableJpaRepositories( basePackages = "com.yourpackage.repository.secondary", // 可单独放一套Repository,或同包靠注解区分 entityManagerFactoryRef = "secondaryEntityManagerFactory", transactionManagerRef = "secondaryTransactionManager" ) public class SecondaryJpaConfig { @Autowired private Environment env; @Bean(name = "secondaryEntityManagerFactory") public LocalContainerEntityManagerFactoryBean secondaryEntityManagerFactory(EntityManagerFactoryBuilder builder) { return builder .dataSource(secondaryDataSource()) .packages("com.yourpackage.entity") // 关联同一个实体包 .persistenceUnit("secondaryPU") .properties(jpaProperties()) .build(); } @Bean public DataSource secondaryDataSource() { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName(env.getProperty("mpfp.db.read.driver")); dataSource.setUrl(env.getProperty("mpfp.db.read.url")); dataSource.setUsername(env.getProperty("mpfp.db.read.username")); dataSource.setPassword(env.getProperty("mpfp.db.read.password")); return dataSource; } private Map<String, Object> jpaProperties() { Map<String, Object> props = new HashMap<>(); props.put("hibernate.hbm2ddl.auto", env.getProperty("spring.jpa.hibernate.ddl-auto")); props.put("hibernate.show_sql", env.getProperty("spring.jpa.show-sql")); return props; } }
2. 配置对应的事务管理器
每个EntityManagerFactory都需要配套的事务管理器,确保操作时的事务一致性:
主库事务管理器(添加到PrimaryJpaConfig)
@Primary @Bean(name = "primaryTransactionManager") public PlatformTransactionManager primaryTransactionManager( @Qualifier("primaryEntityManagerFactory") EntityManagerFactory entityManagerFactory) { return new JpaTransactionManager(entityManagerFactory); }
从库事务管理器(添加到SecondaryJpaConfig)
@Bean(name = "secondaryTransactionManager") public PlatformTransactionManager secondaryTransactionManager( @Qualifier("secondaryEntityManagerFactory") EntityManagerFactory entityManagerFactory) { return new JpaTransactionManager(entityManagerFactory); }
3. 用同一个实体操作不同数据源的两种方式
方式一:创建两套Repository接口
分别为两个数据源创建Repository,操作同一个实体:
// 主库Repository public interface UserRepository extends JpaRepository<User, Long> { } // 从库Repository public interface SecondaryUserRepository extends JpaRepository<User, Long> { }
在Service层注入并指定事务管理器:
@Service public class UserService { @Autowired private UserRepository primaryUserRepo; @Autowired private SecondaryUserRepository secondaryUserRepo; // 写入主库 @Transactional(value = "primaryTransactionManager") public User saveToPrimary(User user) { return primaryUserRepo.save(user); } // 读取从库 @Transactional(value = "secondaryTransactionManager", readOnly = true) public User getFromSecondary(Long id) { return secondaryUserRepo.findById(id).orElse(null); } }
方式二:单Repository指定不同事务管理器
如果不想创建两套Repository,可以在接口方法上直接指定事务管理器:
public interface UserRepository extends JpaRepository<User, Long> { @Query("select u from User u where u.id = ?1") @Transactional(value = "secondaryTransactionManager", readOnly = true) User findFromSecondary(Long id); // 默认使用主库事务管理器 @Override @Transactional(value = "primaryTransactionManager") <S extends User> S save(S entity); }
4. 配置文件补充
确保application.properties里的数据源配置完整:
# 主数据源(写) mpfp.db.write.driver=com.mysql.cj.jdbc.Driver mpfp.db.write.url=jdbc:mysql://localhost:3306/primary_db?useSSL=false&serverTimezone=UTC mpfp.db.write.username=root mpfp.db.write.password=your_password # 从数据源(读) mpfp.db.read.driver=com.mysql.cj.jdbc.Driver mpfp.db.read.url=jdbc:mysql://localhost:3306/secondary_db?useSSL=false&serverTimezone=UTC mpfp.db.read.username=root mpfp.db.read.password=your_password # JPA通用配置 spring.jpa.hibernate.ddl-auto=update spring.jpa.show-sql=true spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
内容的提问来源于stack exchange,提问作者Veswanth
相关产品推荐
相关产品推荐

