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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:19:41