使用springBoot+ShardingSphere5.1.2+mybatisPlus+人大金仓出现多表查询报错 (修改人大金仓在ShardingSphere中的策略)

报错原因

人大金仓在ShardingSphere中使用默认sql92,因为通过数据的url开头的jdbc:kingbase8:找不到对应的解决方案。

ShardingSphere在程序启动的时候通过ServiceLoader.load去获取DatabaseType和OptimizerSQLDialectBuilder的实现类从而找到数据的处理方案, 就可以在META-INF/services中放入对应的路经。

因为使用方式和mysql类似,就仿照ShardingSphere中的mysql的方式,创建一个KingBase8DatabaseType和KingBaseOptimizerBuilder

pom

            <!-- MyBatis Plus-->
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-boot-starter</artifactId>
                <version>3.5.3.1</version>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>8.0.30</version>
            </dependency>
            <dependency>
                <groupId>org.apache.shardingsphere</groupId>
                <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
                <version>5.1.2</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-jpa</artifactId>
                <version>${spring.boot.version}</version>
            </dependency>
            <!-- yaml配置读取-->
            <dependency>
                <groupId>org.yaml</groupId>
                <artifactId>snakeyaml</artifactId>
                <version>1.33</version>
            </dependency>

        <dependency>
            <groupId>com.kingbase</groupId>
            <artifactId>kingbase8</artifactId>
            <version>8.6.0</version>
            <scope>system</scope>
            <systemPath>${project.basedir}/lib/kingbase8-8.6.0.jar</systemPath>
        </dependency>

        <dependency>
            <groupId>org.hibernate.dialect</groupId>
            <artifactId>Kingbase8Dialect</artifactId>
            <version>4</version>
            <scope>system</scope>
            <systemPath>${project.basedir}/lib/hibernate-4.dialect.jar</systemPath>
        </dependency>

配置

spring:
  #shardingjdbc主要配置 使用HikariDataSource连接池
  shardingsphere:
    # 是否启用sharding
    #enabled: true
    props:
      # 是否显示sql
      sql-show: true
    datasource:
      names: iot #数据源名称,多个以逗号隔开
      iot:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.kingbase8.Driver
        url: jdbc:kingbase8://localhost:54321/test?currentSchema=test&characterEncoding=UTF-8
        username: root
        password: 123123
    rules:
      sharding:
        tables:
          wssl_terminal_data_b: # 分表,逻辑表名
            # 节点表添加下初始的表,后续会在新增租户的时候新增表且刷新节点
            actual-data-nodes: iot.wssl_terminal_data_b
            table-strategy: # 配置分表策略
              complex: # 用于单分片键的标准分片场景
                sharding-columns: terminal_type,create_time
                sharding-algorithm-name: real-data-inline
        # 分片算法配置
        sharding-algorithms:
          real-data-inline: # 分片算法名称
            type: CLASS_BASED #自定义策略
            props:
              strategy: complex
              # 包名+类名
              algorithmClassName: com.qzsoft.common.config.shardingsphere.DataShardingAlgorithm
  jpa:
    properties:
      hibernate:
        dialect: com.qzsoft.common.config.KingbaseDialect
        hbm2ddl:
          auto: update
        format_sql: true
    show-sql: true
    generate-ddl: true
    hibernate:
      ddl-auto: update

创建一个KingBase8DatabaseType

public class KingBase8DatabaseType implements BranchDatabaseType {
    //需要和驱动url中的jdbc:kingbase8 保持一致,不区分大小写,这里用kingbase8
    public String getName() {
        return "kingbase8";
    }

    @Override
    public String getType() {
        return "kingbase8";
    }

    public Collection getJdbcUrlPrefixAlias() {

        return Collections.emptyList();

    }

    @Override
    public QuoteCharacter getQuoteCharacter() {
        return QuoteCharacter.QUOTE;
    }

    @Override
    public Collection<String> getJdbcUrlPrefixes() {
        return Collections.singleton(String.format("jdbc:%s:", getType().toLowerCase()));
    }

    //达梦数据库的数据源元数据
    public KingBase8DataSourceMetaData getDataSourceMetaData(String url, String username) {
        return new KingBase8DataSourceMetaData(url);
    }

    @Override
    public Optional<String> getDataSourceClassName() {
        return Optional.empty();
    }

    @Override
    public Map<String, Collection<String>> getSystemDatabaseSchemaMap() {
        return Collections.emptyMap();
    }

    @Override
    public Collection<String> getSystemSchemas() {
        return Collections.emptyList();
    }

    //作为MySQL的子集,sql解析等操作使用MySQL的实现
    @Override
    public DatabaseType getTrunkDatabaseType() {
        return DatabaseTypeFactory.getInstance("MySQL");

    }


}

创建一个KingBase8DataSourceMetaData

@Getter
public class KingBase8DataSourceMetaData implements DataSourceMetaData {
    private static final int DEFAULT_PORT = 54321;

    private final String hostname;

    private final int port;

    private final String catalog;

    private final String schema;

    private final Properties queryProperties;

    private final Properties defaultQueryProperties = new Properties();

    public KingBase8DataSourceMetaData(final String url) {
        JdbcUrl jdbcUrl = new StandardJdbcUrlParser().parse(url);
        hostname = jdbcUrl.getHostname();
        port = -1 == jdbcUrl.getPort() ? DEFAULT_PORT : jdbcUrl.getPort();
        catalog = jdbcUrl.getDatabase();
        schema = null;
        queryProperties = jdbcUrl.getQueryProperties();
    }

    @Override
    public Properties getDefaultQueryProperties() {
        return new Properties();
    }


    private void buildDefaultQueryProperties() {
        defaultQueryProperties.setProperty("useServerPrepStmts", Boolean.TRUE.toString());
        defaultQueryProperties.setProperty("cachePrepStmts", Boolean.TRUE.toString());
        defaultQueryProperties.setProperty("prepStmtCacheSize", "200000");
        defaultQueryProperties.setProperty("prepStmtCacheSqlLimit", "2048");
        defaultQueryProperties.setProperty("useLocalSessionState", Boolean.TRUE.toString());
        defaultQueryProperties.setProperty("rewriteBatchedStatements", Boolean.TRUE.toString());
        defaultQueryProperties.setProperty("cacheResultSetMetadata", Boolean.FALSE.toString());
        defaultQueryProperties.setProperty("cacheServerConfiguration", Boolean.TRUE.toString());
        defaultQueryProperties.setProperty("elideSetAutoCommits", Boolean.TRUE.toString());
        defaultQueryProperties.setProperty("maintainTimeStats", Boolean.FALSE.toString());
        defaultQueryProperties.setProperty("netTimeoutForStreamingResults", "0");
        defaultQueryProperties.setProperty("tinyInt1isBit", Boolean.FALSE.toString());
        defaultQueryProperties.setProperty("useSSL", Boolean.FALSE.toString());
        defaultQueryProperties.setProperty("serverTimezone", "UTC");
        defaultQueryProperties.setProperty("zeroDateTimeBehavior", "round");
    }
}

创建一个KingBaseOptimizerBuilder

public class KingBaseOptimizerBuilder implements OptimizerSQLDialectBuilder {
    @Override
    public Properties build() {
        Properties result = new Properties();
        result.setProperty(CalciteConnectionProperty.LEX.camelName(), Lex.JAVA.name());
        result.setProperty(CalciteConnectionProperty.CONFORMANCE.camelName(), SqlConformanceEnum.BABEL.name());
        result.setProperty(CalciteConnectionProperty.FUN.camelName(), SqlLibrary.POSTGRESQL.fun);
        return result;
    }

    @Override
    public String getType() {
        return "kingbase8";
    }

    @Override
    public boolean isDefault() {
        return true;
    }
}

最后把添加的KingBase8DatabaseType和KingBaseOptimizerBuilder 导入进程序中

在META-INF/services路径下

添加文件

文件分别为

org.apache.shardingsphere.infra.database.type.DatabaseType

com.qzsoft.common.config.shardingsphere.KingBase8DatabaseType
org.apache.shardingsphere.infra.database.type.dialect.H2DatabaseType
org.apache.shardingsphere.infra.database.type.dialect.MariaDBDatabaseType
org.apache.shardingsphere.infra.database.type.dialect.MySQLDatabaseType
org.apache.shardingsphere.infra.database.type.dialect.OpenGaussDatabaseType
org.apache.shardingsphere.infra.database.type.dialect.OracleDatabaseType
org.apache.shardingsphere.infra.database.type.dialect.PostgreSQLDatabaseType
org.apache.shardingsphere.infra.database.type.dialect.SQL92DatabaseType
org.apache.shardingsphere.infra.database.type.dialect.SQLServerDatabaseType

org.apache.shardingsphere.infra.federation.optimizer.context.parser.dialect.OptimizerSQLDialectBuilder

内容:

com.qzsoft.common.config.shardingsphere.KingBaseOptimizerBuilder
org.apache.shardingsphere.infra.federation.optimizer.context.parser.dialect.impl.H2OptimizerBuilder
org.apache.shardingsphere.infra.federation.optimizer.context.parser.dialect.impl.MariaDBOptimizerBuilder
org.apache.shardingsphere.infra.federation.optimizer.context.parser.dialect.impl.MySQLOptimizerBuilder
org.apache.shardingsphere.infra.federation.optimizer.context.parser.dialect.impl.OpenGaussOptimizerBuilder
org.apache.shardingsphere.infra.federation.optimizer.context.parser.dialect.impl.OracleOptimizerBuilder
org.apache.shardingsphere.infra.federation.optimizer.context.parser.dialect.impl.PostgreSQLOptimizerBuilder
org.apache.shardingsphere.infra.federation.optimizer.context.parser.dialect.impl.SQLServerOptimizerBuilder
org.apache.shardingsphere.infra.federation.optimizer.context.parser.dialect.impl.SQL92OptimizerBuilder
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是一个基于shardingsphere-sharding-boot-starter 5.1.2版本实现分库分表的例子: 1. 添加依赖 在pom.xml文件添加以下依赖: ```xml <dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>shardingsphere-jdbc-core</artifactId> <version>5.1.2</version> </dependency> <dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>shardingsphere-proxy-backend-common</artifactId> <version>5.1.2</version> </dependency> <dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId> <version>5.1.2</version> </dependency> <dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>shardingsphere-proxy-frontend-common</artifactId> <version>5.1.2</version> </dependency> <dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>shardingsphere-proxy-bootstrap</artifactId> <version>5.1.2</version> </dependency> ``` 2. 配置数据源 在application.yml文件配置数据源信息,例如: ```yaml spring: datasource: sharding: datasource: ds_0: type: com.alibaba.druid.pool.DruidDataSource driverClassName: com.mysql.jdbc.Driver url: jdbc:mysql://localhost:3306/db1?useUnicode=true&characterEncoding=UTF8&serverTimezone=Asia/Shanghai username: root password: root ds_1: type: com.alibaba.druid.pool.DruidDataSource driverClassName: com.mysql.jdbc.Driver url: jdbc:mysql://localhost:3306/db2?useUnicode=true&characterEncoding=UTF8&serverTimezone=Asia/Shanghai username: root password: root # 配置分库规则 shardingRule: # 分库策略 defaultDatabaseStrategy: inline: shardingColumn: user_id algorithmExpression: ds_${user_id % 2} # 分表策略 defaultTableStrategy: inline: shardingColumn: order_id algorithmExpression: t_order_${order_id % 2} # 绑定表 bindingTables: - t_order # 分库分表算法 shardingAlgorithms: inline: type: INLINE props: algorithm-expression: ds_${user_id % 2} algorithm-expression: t_order_${order_id % 2} # 配置默认数据源 url: jdbc:mysql://localhost:3306/db1?useUnicode=true&characterEncoding=UTF8&serverTimezone=Asia/Shanghai username: root password: root driver-class-name: com.mysql.jdbc.Driver ``` 3. 创建实体类 创建一个简单的实体类,例如: ```java public class Order { private Long orderId; private Long userId; private String status; // getter and setter } ``` 4. 创建DAO 创建一个简单的DAO类,通过注解来指定表名和主键,例如: ```java @Repository @Mapper public interface OrderDao { @Insert("insert into t_order (order_id, user_id, status) values (#{orderId}, #{userId}, #{status})") @Options(useGeneratedKeys = true, keyProperty = "orderId") int insert(Order order); @Select("select * from t_order where order_id = #{orderId}") @Results({ @Result(column = "order_id", property = "orderId"), @Result(column = "user_id", property = "userId"), @Result(column = "status", property = "status") }) Order selectByPrimaryKey(Long orderId); } ``` 5. 编写测试用例 编写一个简单的测试用例,例如: ```java @RunWith(SpringRunner.class) @SpringBootTest public class OrderDaoTest { @Autowired private OrderDao orderDao; @Test public void testInsert() { Order order = new Order(); order.setUserId(1L); order.setStatus("INIT"); orderDao.insert(order); System.out.println(order.getOrderId()); } @Test public void testSelectByPrimaryKey() { Order order = orderDao.selectByPrimaryKey(1L); System.out.println(order); } } ``` 6. 运行测试用例 通过运行测试用例来验证分库分表是否正常工作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值