亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

SpringBoot多數(shù)據(jù)源配置完整指南

 更新時(shí)間:2025年04月22日 14:09:19   作者:北辰alk  
在復(fù)雜的企業(yè)應(yīng)用中,經(jīng)常需要連接多個(gè)數(shù)據(jù)庫(kù),Spring Boot 提供了靈活的多數(shù)據(jù)源配置方式,以下是詳細(xì)的實(shí)現(xiàn)方案,需要的朋友可以參考下

一、基礎(chǔ)多數(shù)據(jù)源配置

1. 添加依賴

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- 或者使用其他數(shù)據(jù)庫(kù)驅(qū)動(dòng) -->

2. 配置多個(gè)數(shù)據(jù)源

# 主數(shù)據(jù)源
spring.datasource.primary.url=jdbc:mysql://localhost:3306/db1
spring.datasource.primary.username=root
spring.datasource.primary.password=123456
spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driver

# 次數(shù)據(jù)源
spring.datasource.secondary.url=jdbc:mysql://localhost:3306/db2
spring.datasource.secondary.username=root
spring.datasource.secondary.password=123456
spring.datasource.secondary.driver-class-name=com.mysql.cj.jdbc.Driver

3. 配置數(shù)據(jù)源Bean

@Configuration
public class DataSourceConfig {

    // 主數(shù)據(jù)源
    @Bean
    @Primary
    @ConfigurationProperties(prefix="spring.datasource.primary")
    public DataSource primaryDataSource() {
        return DataSourceBuilder.create().build();
    }

    // 次數(shù)據(jù)源
    @Bean
    @ConfigurationProperties(prefix="spring.datasource.secondary")
    public DataSource secondaryDataSource() {
        return DataSourceBuilder.create().build();
    }
}

二、JPA多數(shù)據(jù)源配置

1. 配置主數(shù)據(jù)源JPA

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
    basePackages = "com.example.repository.primary",
    entityManagerFactoryRef = "primaryEntityManagerFactory",
    transactionManagerRef = "primaryTransactionManager"
)
public class PrimaryJpaConfig {
    
    @Autowired @Qualifier("primaryDataSource")
    private DataSource primaryDataSource;
    
    @Primary
    @Bean
    public LocalContainerEntityManagerFactoryBean primaryEntityManagerFactory(
            EntityManagerFactoryBuilder builder) {
        return builder
            .dataSource(primaryDataSource)
            .packages("com.example.entity.primary")
            .persistenceUnit("primaryPersistenceUnit")
            .properties(jpaProperties())
            .build();
    }
    
    private Map<String, Object> jpaProperties() {
        Map<String, Object> props = new HashMap<>();
        props.put("hibernate.hbm2ddl.auto", "update");
        props.put("hibernate.dialect", "org.hibernate.dialect.MySQL8Dialect");
        return props;
    }
    
    @Primary
    @Bean
    public PlatformTransactionManager primaryTransactionManager(
            @Qualifier("primaryEntityManagerFactory") EntityManagerFactory emf) {
        return new JpaTransactionManager(emf);
    }
}

2. 配置次數(shù)據(jù)源JPA

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
    basePackages = "com.example.repository.secondary",
    entityManagerFactoryRef = "secondaryEntityManagerFactory",
    transactionManagerRef = "secondaryTransactionManager"
)
public class SecondaryJpaConfig {
    
    @Autowired @Qualifier("secondaryDataSource")
    private DataSource secondaryDataSource;
    
    @Bean
    public LocalContainerEntityManagerFactoryBean secondaryEntityManagerFactory(
            EntityManagerFactoryBuilder builder) {
        return builder
            .dataSource(secondaryDataSource)
            .packages("com.example.entity.secondary")
            .persistenceUnit("secondaryPersistenceUnit")
            .properties(jpaProperties())
            .build();
    }
    
    private Map<String, Object> jpaProperties() {
        Map<String, Object> props = new HashMap<>();
        props.put("hibernate.hbm2ddl.auto", "update");
        props.put("hibernate.dialect", "org.hibernate.dialect.MySQL8Dialect");
        return props;
    }
    
    @Bean
    public PlatformTransactionManager secondaryTransactionManager(
            @Qualifier("secondaryEntityManagerFactory") EntityManagerFactory emf) {
        return new JpaTransactionManager(emf);
    }
}

三、MyBatis多數(shù)據(jù)源配置

1. 主數(shù)據(jù)源配置

@Configuration
@MapperScan(
    basePackages = "com.example.mapper.primary",
    sqlSessionFactoryRef = "primarySqlSessionFactory"
)
public class PrimaryMyBatisConfig {

    @Primary
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.primary")
    public DataSource primaryDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Primary
    @Bean
    public SqlSessionFactory primarySqlSessionFactory(
            @Qualifier("primaryDataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource);
        sessionFactory.setMapperLocations(
            new PathMatchingResourcePatternResolver()
                .getResources("classpath:mapper/primary/*.xml"));
        return sessionFactory.getObject();
    }

    @Primary
    @Bean
    public SqlSessionTemplate primarySqlSessionTemplate(
            @Qualifier("primarySqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

2. 次數(shù)據(jù)源配置

@Configuration
@MapperScan(
    basePackages = "com.example.mapper.secondary",
    sqlSessionFactoryRef = "secondarySqlSessionFactory"
)
public class SecondaryMyBatisConfig {

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.secondary")
    public DataSource secondaryDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    public SqlSessionFactory secondarySqlSessionFactory(
            @Qualifier("secondaryDataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource);
        sessionFactory.setMapperLocations(
            new PathMatchingResourcePatternResolver()
                .getResources("classpath:mapper/secondary/*.xml"));
        return sessionFactory.getObject();
    }

    @Bean
    public SqlSessionTemplate secondarySqlSessionTemplate(
            @Qualifier("secondarySqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

四、動(dòng)態(tài)數(shù)據(jù)源配置(運(yùn)行時(shí)切換)

1. 抽象路由數(shù)據(jù)源

public class DynamicDataSource extends AbstractRoutingDataSource {

    @Override
    protected Object determineCurrentLookupKey() {
        return DataSourceContextHolder.getDataSourceType();
    }
}

2. 數(shù)據(jù)源上下文持有者

public class DataSourceContextHolder {

    private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();

    public static void setDataSourceType(String dataSourceType) {
        contextHolder.set(dataSourceType);
    }

    public static String getDataSourceType() {
        return contextHolder.get();
    }

    public static void clearDataSourceType() {
        contextHolder.remove();
    }
}

3. 配置動(dòng)態(tài)數(shù)據(jù)源

@Configuration
public class DynamicDataSourceConfig {

    @Bean
    @ConfigurationProperties(prefix="spring.datasource.primary")
    public DataSource primaryDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    @ConfigurationProperties(prefix="spring.datasource.secondary")
    public DataSource secondaryDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Primary
    @Bean
    public DataSource dynamicDataSource(
            @Qualifier("primaryDataSource") DataSource primaryDataSource,
            @Qualifier("secondaryDataSource") DataSource secondaryDataSource) {
        
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put("primary", primaryDataSource);
        targetDataSources.put("secondary", secondaryDataSource);
        
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        dynamicDataSource.setTargetDataSources(targetDataSources);
        dynamicDataSource.setDefaultTargetDataSource(primaryDataSource);
        
        return dynamicDataSource;
    }
}

4. 使用AOP切換數(shù)據(jù)源

@Aspect
@Component
public class DataSourceAspect {

    @Pointcut("@annotation(com.example.annotation.TargetDataSource)")
    public void dataSourcePointCut() {}

    @Before("dataSourcePointCut()")
    public void before(JoinPoint point) {
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        TargetDataSource ds = method.getAnnotation(TargetDataSource.class);
        
        if (ds == null) {
            DataSourceContextHolder.setDataSourceType("primary");
        } else {
            DataSourceContextHolder.setDataSourceType(ds.value());
        }
    }

    @After("dataSourcePointCut()")
    public void after(JoinPoint point) {
        DataSourceContextHolder.clearDataSourceType();
    }
}

5. 自定義注解

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TargetDataSource {
    String value() default "primary";
}

6. 使用示例

@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;
    
    // 使用主數(shù)據(jù)源
    public User getPrimaryUser(Long id) {
        return userMapper.selectById(id);
    }
    
    // 使用次數(shù)據(jù)源
    @TargetDataSource("secondary")
    public User getSecondaryUser(Long id) {
        return userMapper.selectById(id);
    }
}

五、多數(shù)據(jù)源事務(wù)管理

1. JTA分布式事務(wù)(Atomikos)

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jta-atomikos</artifactId>
</dependency>

2. 配置JTA數(shù)據(jù)源

# 主數(shù)據(jù)源
spring.jta.atomikos.datasource.primary.unique-resource-name=primaryDS
spring.jta.atomikos.datasource.primary.xa-data-source-class-name=com.mysql.cj.jdbc.MysqlXADataSource
spring.jta.atomikos.datasource.primary.xa-properties.url=jdbc:mysql://localhost:3306/db1
spring.jta.atomikos.datasource.primary.xa-properties.user=root
spring.jta.atomikos.datasource.primary.xa-properties.password=123456

# 次數(shù)據(jù)源
spring.jta.atomikos.datasource.secondary.unique-resource-name=secondaryDS
spring.jta.atomikos.datasource.secondary.xa-data-source-class-name=com.mysql.cj.jdbc.MysqlXADataSource
spring.jta.atomikos.datasource.secondary.xa-properties.url=jdbc:mysql://localhost:3306/db2
spring.jta.atomikos.datasource.secondary.xa-properties.user=root
spring.jta.atomikos.datasource.secondary.xa-properties.password=123456

3. 使用分布式事務(wù)

@Service
public class OrderService {

    @Transactional // 跨數(shù)據(jù)源事務(wù)
    public void placeOrder(Order order) {
        // 操作主數(shù)據(jù)源
        primaryRepository.save(order);
        
        // 操作次數(shù)據(jù)源
        auditRepository.logOrder(order);
        
        // 如果此處拋出異常,兩個(gè)操作都會(huì)回滾
    }
}

六、最佳實(shí)踐

  1. 命名規(guī)范

    • 為每個(gè)數(shù)據(jù)源使用清晰的命名(如customerDS, orderDS)
    • 包結(jié)構(gòu)按數(shù)據(jù)源分離(com.example.repository.primary / .secondary)
  2. 連接池配置

spring.datasource.primary.hikari.maximum-pool-size=10
spring.datasource.secondary.hikari.maximum-pool-size=5
  1. 監(jiān)控指標(biāo)

    • 為每個(gè)數(shù)據(jù)源配置獨(dú)立的監(jiān)控
    • 使用Spring Actuator暴露數(shù)據(jù)源健康指標(biāo)
  2. 性能考慮

    • 高頻訪問(wèn)的數(shù)據(jù)源使用更大的連接池
    • 讀寫分離場(chǎng)景考慮主從數(shù)據(jù)源
  3. 測(cè)試策略

    • 為每個(gè)數(shù)據(jù)源編寫?yīng)毩⒌臏y(cè)試類
    • 測(cè)試跨數(shù)據(jù)源事務(wù)的回滾行為

七、常見(jiàn)問(wèn)題解決

問(wèn)題1:循環(huán)依賴

// 解決方法:使用@DependsOn
@Bean
@DependsOn("dynamicDataSource")
public PlatformTransactionManager transactionManager() {
    return new DataSourceTransactionManager(dynamicDataSource());
}

問(wèn)題2:MyBatis緩存沖突

// 解決方法:為每個(gè)SqlSessionFactory配置獨(dú)立的緩存環(huán)境
sqlSessionFactory.setConfiguration(configuration);
configuration.setEnvironment(new Environment(
    "primaryEnv", 
    transactionFactory, 
    dataSource
));

問(wèn)題3:事務(wù)傳播行為異常

// 解決方法:明確指定事務(wù)管理器
@Transactional(transactionManager = "primaryTransactionManager")
public void primaryOperation() {...}

通過(guò)以上配置,Spring Boot應(yīng)用可以靈活地支持多數(shù)據(jù)源場(chǎng)景,無(wú)論是簡(jiǎn)單的多庫(kù)連接還是復(fù)雜的動(dòng)態(tài)數(shù)據(jù)源切換需求。根據(jù)實(shí)際業(yè)務(wù)場(chǎng)景選擇最適合的配置方式,并注意事務(wù)管理和性能調(diào)優(yōu)。

以上就是SpringBoot多數(shù)據(jù)源配置完整指南的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot多數(shù)據(jù)源配置的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java 單例模式的實(shí)現(xiàn)資料整理

    Java 單例模式的實(shí)現(xiàn)資料整理

    這篇文章主要介紹了Java 單例模式的實(shí)現(xiàn)的相關(guān)資料,并附簡(jiǎn)單實(shí)例代碼,需要的朋友可以參考下
    2016-10-10
  • JAVA JVM面試題總結(jié)

    JAVA JVM面試題總結(jié)

    JVM 可以屏蔽與具體操作系統(tǒng)平臺(tái)相關(guān)的信息,使 Java 程序只需生成在 Java 虛擬機(jī)上運(yùn)行的目標(biāo)代碼,就可以在不同的平臺(tái)上運(yùn)行。這篇文章主要介紹了JAVA JVM面試題總結(jié),大家可以參考一下
    2021-08-08
  • java編程常用技術(shù)(推薦)

    java編程常用技術(shù)(推薦)

    下面小編就為大家?guī)?lái)一篇java編程常用技術(shù)(推薦)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-06-06
  • java正則表達(dá)式匹配規(guī)則超詳細(xì)總結(jié)

    java正則表達(dá)式匹配規(guī)則超詳細(xì)總結(jié)

    正則表達(dá)式并不僅限于某一種語(yǔ)言,但是在每種語(yǔ)言中有細(xì)微的差別,下面這篇文章主要給大家介紹了關(guān)于java正則表達(dá)式匹配規(guī)則的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-10-10
  • 教你怎么用java一鍵自動(dòng)生成數(shù)據(jù)庫(kù)文檔

    教你怎么用java一鍵自動(dòng)生成數(shù)據(jù)庫(kù)文檔

    最近小編也在找這樣的插件,就是不想寫文檔了,浪費(fèi)時(shí)間和心情啊,果然我找到一款比較好用,操作簡(jiǎn)單不復(fù)雜.screw 是一個(gè)簡(jiǎn)潔好用的數(shù)據(jù)庫(kù)表結(jié)構(gòu)文檔的生成工具,支持 MySQL、Oracle、PostgreSQL 等主流的關(guān)系數(shù)據(jù)庫(kù).需要的朋友可以參考下
    2021-05-05
  • java連接mysql數(shù)據(jù)庫(kù)的方法

    java連接mysql數(shù)據(jù)庫(kù)的方法

    這篇文章主要為大家詳細(xì)介紹了java連接mysql數(shù)據(jù)庫(kù)的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • 通過(guò)Java創(chuàng)建Socket連接到服務(wù)器方式

    通過(guò)Java創(chuàng)建Socket連接到服務(wù)器方式

    這篇文章主要介紹了通過(guò)Java創(chuàng)建Socket連接到服務(wù)器方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • Spring Boot中使用Activiti的方法教程(二)

    Spring Boot中使用Activiti的方法教程(二)

    工作流(Workflow),就是“業(yè)務(wù)過(guò)程的部分或整體在計(jì)算機(jī)應(yīng)用環(huán)境下的自動(dòng)化”,下面這篇文章主要給大家介紹了關(guān)于Spring Boot中使用Activiti的相關(guān)資料,需要的朋友可以參考下
    2018-08-08
  • JMETER用戶變量作用域測(cè)試流程

    JMETER用戶變量作用域測(cè)試流程

    這篇文章主要介紹了JMETER用戶變量作用域測(cè)試流程,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-05-05
  • SpringCloud中的@RefreshScope注解與使用場(chǎng)景方式

    SpringCloud中的@RefreshScope注解與使用場(chǎng)景方式

    SpringCloud中的@RefreshScope注解用于動(dòng)態(tài)刷新Bean配置,解決外部配置變化時(shí)的問(wèn)題,避免重啟應(yīng)用,通過(guò)本文的詳細(xì)介紹,希望讀者能夠更好地掌握@RefreshScope的使用技巧,在實(shí)際項(xiàng)目中靈活應(yīng)用,提升微服務(wù)應(yīng)用的動(dòng)態(tài)配置管理能力
    2024-12-12

最新評(píng)論