spring shardingSphere 多数据源

本文详细介绍如何在Spring Boot应用中集成Apache ShardingSphere,实现Oracle和MySQL的异构数据库分库分表,包括自定义数据源配置和关键组件的整合。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

主要内容

Apache ShardingSphere

Apache ShardingSphere 是一套开源的分布式数据库解决方案组成的生态圈。Spring集成Apache ShardingSphere 是一套目前比较好的分库分表的方案。

Apache ShardingSphere JDBC 目前只支持同构数据库,本文通用自定义数据源实现异构数据库(spring boot + jpa + oracle + mysql)的分库分表。

版本:

spring boot V2.6.1

Apache ShardingSphere V5.1.0

更新历史

Apache ShardingSphere JDBC 目前只支持同构数据库, 可通用自定义数据源实现异构数据库(oracle + mysql)的分库分表。

以 oracle 数据库 作为 ShardingSphere JDBC 支持的主数据库。

主要步骤:

DataSource
EntityManagerFactory
EntityManager
TransactionManager
JdbcTemplate

源码

pom

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.6.1</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>org.apache.shardingsphere</groupId>
        <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
        <version>5.1.0</version>
    </dependency>
</dependencies>

Application

@SpringBootApplication(exclude = JtaAutoConfiguration.class) //使用ShardingSphere的分布式管理
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(XgfyBridgeApplication.class, args);
    }

}

DataSource

Apache ShardingSphere 的数据源作为主DataSource

@Configuration
public class DataSourceConfig {

    @Autowired
    @Qualifier("shardingSphereDataSource")
    private DataSource shardingSphereDataSource;  // 使用ShardingSphere 自动装载的 DataSource

    @Bean(name = "primaryDataSource")
    @Primary
    @Qualifier("primaryDataSource")
    public DataSource primaryDatasource() {
        return shardingSphereDataSource;
    }

}

多数据源配置

  • 优先数据源

    @Configuration
    @EnableTransactionManagement
    @EnableJpaRepositories(
            entityManagerFactoryRef = "entityManagerFactoryPrimary",
            transactionManagerRef = "transactionManagerPrimary",
            basePackages = {"xxx.xxxx"}) //设置Repository所在位置
    public class PrimaryConfig {
    
        @Autowired
        private JpaProperties jpaProperties;
    
    
        @Autowired
        @Qualifier("primaryDataSource")
        private DataSource primaryDataSource;
    
    
        // 2) EntityManagerFactory
        @Primary
        @Bean(name = "entityManagerFactoryPrimary")
        public EntityManagerFactory entityManagerFactory() {
            HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
            vendorAdapter.setDatabase(Database.ORACLE);
            vendorAdapter.setGenerateDdl(false);
            vendorAdapter.setShowSql(true);
            LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
            factory.setJpaVendorAdapter(vendorAdapter);
            factory.setPersistenceUnitName("default");
            factory.setPackagesToScan("xxxxxxxxx.entity");
            factory.setDataSource(primaryDataSource);
            factory.setJpaPropertyMap(jpaProperties.getProperties());
            factory.afterPropertiesSet();
            return factory.getObject();
        }
    
        
        // 3) EntityManager
        @Bean(name = "entityManagerPrimary")
        @Primary
        public EntityManager entityManager(@Qualifier("entityManagerFactoryPrimary") EntityManagerFactory entityManagerFactory){
            return SharedEntityManagerCreator.createSharedEntityManager(entityManagerFactory);
        }
    
        
        // 4) TransactionManager
        @Bean(name = "transactionManagerPrimary")
        @Primary
        public PlatformTransactionManager transactionManager(@Qualifier("entityManagerFactoryPrimary") EntityManagerFactory entityManagerFactory){
            JpaTransactionManager txManager = new JpaTransactionManager();
            txManager.setEntityManagerFactory(entityManagerFactory);
            return txManager;
        }
    
        
        // 5) JdbcTemplate
        @Bean(name = "jdbcTemplateSharding")
        @Primary
        public JdbcTemplate jdbcTemplateSharding() {
            JdbcTemplate jdbcTemplate = new JdbcTemplate();
            jdbcTemplate.setDataSource(primaryDataSource);
            return jdbcTemplate;
        }
    }
    
  • 其他数据源

    @Configuration
    @EnableTransactionManagement
    @EnableJpaRepositories(
            entityManagerFactoryRef = "entityManagerFactoryYixing",
            transactionManagerRef = "transactionManagerYixing",
            basePackages = {"xx.xxxx"}) //设置Repository所在位置
    public class SecondConfig {
        @Autowired
        private JpaProperties jpaProperties;
    
    
        @Bean(name = "yixingDataSource")
        @ConfigurationProperties(prefix = "spring.datasource.yixing")
        public DataSource yixingDataSource() {
            return DataSourceBuilder.create().build();
        }
    
    
        @Bean(name = "entityManagerYixing")
        public EntityManager entityManager() {
            return entityManagerFactoryyixing().createEntityManager();
        }
    
    
    
        @Bean(name = "entityManagerFactoryYixing")
        public EntityManagerFactory entityManagerFactoryyixing() {
            HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
            vendorAdapter.setDatabase(Database.MYSQL);
            vendorAdapter.setGenerateDdl(false);
            vendorAdapter.setShowSql(true);
            LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
            factory.setJpaVendorAdapter(vendorAdapter);
            factory.setPersistenceUnitName("yixing");
            factory.setPackagesToScan("xxxx.entity");
            factory.setDataSource(yixingDataSource());
            factory.setJpaPropertyMap(jpaProperties.getProperties());
            factory.afterPropertiesSet();
            return factory.getObject();
        }
    
    
        @Bean(name = "transactionManageryixing")
        public PlatformTransactionManager transactionManageryixing(@Qualifier("entityManagerFactoryYixing") EntityManagerFactory entityManagerFactory){
            JpaTransactionManager txManager = new JpaTransactionManager();
            txManager.setEntityManagerFactory(entityManagerFactory);
            return txManager;
        }
    
        @Bean(name = "jdbcTemplateYixing")
        public JdbcTemplate jdbcTemplateYixing() {
            JdbcTemplate jdbcTemplate = new JdbcTemplate();
            jdbcTemplate.setDataSource(yixingDataSource());
            return jdbcTemplate;
        }
    }
    

yml文件

spring:
  thymeleaf:
    cache: false
  jpa:
    hibernate:
      ddl-auto: none
      database-platform: org.hibernate.dialect.Oracle12cDialect
    open-in-view: false
    show-sql: true

  datasource:
    yixing:
      database-platform: org.hibernate.dialect.MySQL8Dialect
      type: com.zaxxer.hikari.HikariDataSource
      jdbc-url: jdbc:mysql://192.168.1.x:3306/qz?serverTimezone=UTC&useSSL=false
      driver-class-name: com.mysql.cj.jdbc.Driver
      username: "xxx"
      password: "xxx"
      hikari:
        maximumPoolSize: 50
        poolName: yixing_HikariPool

  shardingsphere:
    enabled: true
    datasource:
      names: ds-master, ds-dr
      ds-master:
        type: com.zaxxer.hikari.HikariDataSource
        jdbc-url: jdbc:oracle:thin:@(DESCRIPTION =(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.x)(PORT = 1521) )  (CONNECT_DATA =(SERVICE_NAME = orcl)) )
        driver-class-name: oracle.jdbc.OracleDriver
        username: xxx
        password: xxx
        hikari:
          maximumPoolSize: 50
          poolName: master_HikariPool
      ds-dr:
        type: com.zaxxer.hikari.HikariDataSource
        jdbc-url: jdbc:oracle:thin:@(DESCRIPTION =(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.x)(PORT = 1521) )  (CONNECT_DATA =(SERVICE_NAME = ORCL)) )
        driver-class-name: oracle.jdbc.OracleDriver
        username: "xxx"
        password: "xxx"
        hikari:
          maximumPoolSize: 50
          poolName: dr_HikariPool
    rules:
      sharding:
        # tables -----------------------------------------------------
        tables:
          t_acid_result_dr:
            actual-data-nodes: ds-master.t_acid_result_dr_$->{0..31}
            table-strategy:
              standard:
                sharding-column: id_card_hash
                sharding-algorithm-name: acid-inline
            key-generate-strategy:
              column: id
              key-generator-name: mysnowflake
          t_acid_result_yx:
            actual-data-nodes: ds-master.t_acid_result_yx_$->{0..31}
            table-strategy:
              standard:
                sharding-column: id_card_hash
                sharding-algorithm-name: acid-yx-inline
            key-generate-strategy:
              column: id
              key-generator-name: yxsnowflake
          t_machan_check_dr:
            actual-data-nodes: ds-master.t_machan_check_dr


        # key-generators ------------------------
        key-generators:
          mysnowflake:
            type: SNOWFLAKE
            props:
              worker-id: 11
          yxsnowflake:
            type: SNOWFLAKE
            props:
              worker-id: 12
        # sharding-algorithms ------------------------------------------------
        sharding-algorithms:
          acid-inline:
            type: INLINE
            props:
              algorithm-expression: t_acid_result_dr_$->{id_card_hash % 32}
          acid-yx-inline:
            type: INLINE
            props:
              algorithm-expression: t_acid_result_yx_$->{id_card_hash % 32}
### ShardingSphere 多数据源配置教程 #### 1. Maven依赖配置 在项目的`pom.xml`文件中,需要引入ShardingSphere的核心依赖以及其他必要的组件。以下是常见的Maven依赖配置: ```xml <dependencies> <!-- ShardingSphere 核心依赖 --> <dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>sharding-jdbc-core</artifactId> <version>5.0.0</version> </dependency> <!-- Spring 命名空间支持 --> <dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>sharding-jdbc-spring-namespace</artifactId> <version>5.0.0</version> </dependency> <!-- 动态数据源支持 (可选) --> <dependency> <groupId>com.baomidou</groupId> <artifactId>dynamic-datasource-spring-boot-starter</artifactId> <version>3.5.0</version> </dependency> <!-- MyBatis Plus 支持 (如果使用MyBatis) --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.3</version> </dependency> </dependencies> ``` 以上配置涵盖了ShardingSphere核心功能以及动态数据源的支持[^4]。 --- #### 2. 数据源配置 可以通过Spring Boot的`application.yml`或者XML方式进行多数据源配置。以下是一个基于YAML的示例配置: ```yaml spring: shardingsphere: datasource: names: ds_0,ds_1 ds_0: type: com.zaxxer.hikari.HikariDataSource driver-class-name: com.mysql.cj.jdbc.Driver jdbc-url: jdbc:mysql://localhost:3306/db_0?useSSL=false&serverTimezone=UTC username: root password: root ds_1: type: com.zaxxer.hikari.HikariDataSource driver-class-name: com.mysql.cj.jdbc.Driver jdbc-url: jdbc:mysql://localhost:3306/db_1?useSSL=false&serverTimezone=UTC username: root password: root rules: sharding: tables: t_order: actual-data-nodes: ds_${0..1}.t_order_${0..1} table-strategy: standard: sharding-column: order_id sharding-algorithm-name: mod-sharding-algorithm binding-tables: - t_order,t_order_item default-database-strategy: standard: sharding-column: user_id sharding-algorithm-name: database-inline default-table-strategy: none: props: sql-show: true ``` 此配置定义了两个数据源(`ds_0`, `ds_1`)并设置了分片策略[^2]。 --- #### 3. Java配置类 对于更复杂的场景,可以编写Java配置类来管理数据源和事务。以下是一个典型的配置示例: ```java @Configuration public class DataSourceConfig { @Bean public DataSource dataSource() { Map<String, DataSource> dataSourceMap = new HashMap<>(); HikariDataSource ds0 = createDataSource("jdbc:mysql://localhost:3306/db_0", "root", "root"); HikariDataSource ds1 = createDataSource("jdbc:mysql://localhost:3306/db_1", "root", "root"); dataSourceMap.put("ds_0", ds0); dataSourceMap.put("ds_1", ds1); ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration(); shardingRuleConfig.getTableRules().add(getOrderTableRule()); shardingRuleConfig.getBindingTableGroups().add("t_order,t_order_item"); return ShardingDataSourceFactory.createDataSource(dataSourceMap, shardingRuleConfig, new HashMap<>(), new Properties()); } private TableRule getOrderTableRule() { KeyGenerator keyGenerator = new SnowflakeKeyGenerator(); StrategyConfiguration dbStrategyConfig = new InlineShardingStrategyConfiguration("user_id", "ds_${user_id % 2}"); StrategyConfiguration tbStrategyConfig = new StandardShardingStrategyConfiguration("order_id", new ModuloShardingAlgorithm()); return TableRule.builder("t_order") .actualDataNodes("ds_${0..1}.t_order_${0..1}") .databaseShardingStrategy(dbStrategyConfig) .tableShardingStrategy(tbStrategyConfig) .keyGenerator(keyGenerator) .build(); } private HikariDataSource createDataSource(String url, String username, String password) { HikariDataSource dataSource = new HikariDataSource(); dataSource.setJdbcUrl(url); dataSource.setUsername(username); dataSource.setPassword(password); return dataSource; } } ``` 这段代码展示了如何通过编程方式创建多个数据源,并应用分片规则[^1]。 --- #### 4. SQL生成与调试 启用SQL日志可以帮助开发者验证分片逻辑是否正确。可以在`props`节点下设置`sql-show=true`以打印执行的SQL语句。例如: ```sql -- 查询订单表 SELECT * FROM t_order WHERE order_id = ? AND user_id = ? ``` 实际执行时会根据分片算法路由到对应的物理表,如`ds_0.t_order_0`或`ds_1.t_order_1`[^2]。 --- #### 5. 测试代码 以下是一个简单的单元测试案例,用于验证多数据源配置的功能: ```java @SpringBootTest class MultiDataSourceTest { @Autowired private OrderMapper orderMapper; @Test void testInsertAndQuery() { OrderEntity order = new OrderEntity(); order.setOrderId(1L); order.setUserId(10L); order.setStatus("PENDING"); orderMapper.insert(order); List<OrderEntity> orders = orderMapper.selectByUserId(10L); assertNotNull(orders); assertFalse(orders.isEmpty()); } } ``` 确保Mapper接口已正确定义并与实体类绑定[^5]。 --- ### 总结 ShardingSphere提供了强大的多数据源管理和分片能力,能够满足复杂业务场景下的需求。通过合理配置数据源、分片规则以及事务管理,可以显著提升系统的扩展性和性能[^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值