达梦数据库使用ShardingSphere
ShardingSphere只支持主流数据库,国产的数据库并不支持,就比如达梦数据库,所以我们自己扩展。
1. 下载 shardingsphere源码
下载地址:https://github.com/apache/shardingsphere
进入网址后,选择自己使用的 Tags 分支,并下载代码。我使用的版本是 4.0.0-RC2

再下载代码,目前支持 git clone,和 zip 压缩包下载。

2. 达梦扩展
在 sharding-core-common 模块下
实现 org.apache.shardingsphere.spi.database.DataSourceMetaData 接口,实现类写到 org.apache.shardingsphere.core.metadata.datasource.dialect 目录下
package org.apache.shardingsphere.core.metadata.datasource.dialect; import com.google.common.base.Strings; import org.apache.shardingsphere.core.metadata.datasource.UnrecognizedDatabaseURLException; import org.apache.shardingsphere.spi.database.DataSourceMetaData; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * @author zhanghe */ public final class DMDataSourceMetaData implements DataSourceMetaData { private static final int DEFAULT_PORT = 5236; private final String hostName; private final int port; private final String catalog; private final String schemaName; private final Pattern pattern = Pattern.compile("jdbc:dm://([\\w\\-\\.]+):?([0-9]*)/([\\w\\-]+)", Pattern.CASE_INSENSITIVE); public DMDataSourceMetaData(String url) { Matcher matcher = pattern.matcher(url); if (!matcher.find()) { throw new UnrecognizedDatabaseURLException(url, pattern.pattern()); } this.hostName = matcher.group(1); this.port = Strings.isNullOrEmpty(matcher.group(2)) ? DEFAULT_PORT : Integer.valueOf(matcher.group(2)); this.catalog = matcher.group(3); this.schemaName = matcher.group(3); } @Override public String getHostName() { return this.hostName; } @Override public int getPort() { return this.port; } @Override public String getSchemaName() { return this.schemaName; } public Pattern getPattern() { return this.pattern; } }
实现 org.apache.shardingsphere.spi.database.BranchDatabaseType 接口,实现类写到 org.apache.shardingsphere.core.spi.database 目录下
package org.apache.shardingsphere.core.spi.database; import org.apache.shardingsphere.core.database.DatabaseTypes; import org.apache.shardingsphere.core.metadata.datasource.dialect.DMDataSourceMetaData; import org.apache.shardingsphere.spi.database.BranchDatabaseType; import org.apache.shardingsphere.spi.database.DataSourceMetaData; import org.apache.shardingsphere.spi.database.DatabaseType; import java.util.Collection; import java.util.Collections; /** * @author zhanghe */ public class DMDatabaseType implements BranchDatabaseType { @Override public String getName() { return "DM"; } @Override public Collection<String> getJdbcUrlPrefixAlias() { return Collections.emptyList(); } @Override public DataSourceMetaData getDataSourceMetaData(String url) { return new DMDataSourceMetaData(url); } // sql解析等操作使用MySQL的实现 @Override public DatabaseType getTrunkDatabaseType() { return DatabaseTypes.getActualDatabaseType("MySQL"); } }
并且在 /resources/META-INF.services 下的 org.apache.shardingsphere.spi.database.DatabaseType 文件中,记录了当前支持的数据类型,用于初始化。把刚创建好的类型添加上。
org.apache.shardingsphere.core.spi.database.DMDatabaseType
关于 getTrunkDatabaseType 方法,要说明一下,这里我们使用的MySQL的实现解析SQL,当然也可以选择 Oracle 等其他数据库,如果需要自己来实现,就需要在 sharding-core-parse下创建自己的module

本来还想着一个微服务同时支持MySQL和达梦库的,但发现sharding并不支持不同数据库类型的垂直分库,报错信息如下:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'shardingDataSource' defined in class path resource [org/apache/shardingsphere/shardingjdbc/spring/boot/SpringBootConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.sql.DataSource]: Factory method 'shardingDataSource' threw exception; nested exception is java.lang.IllegalStateException: Database type inconsistent with 'org.apache.shardingsphere.core.spi.database.DMDatabaseType@1cec219f' and 'org.apache.shardingsphere.core.spi.database.MySQLDatabaseType@2b289ac9'
我同时看了4.0.0-RC2、4.1.1、5.1.0 这三个版本,判断数据库类型的代码在不同的版本中,位置是不一样的,我就不贴类了,报错代码如下:
dataSourceMap 是已加载的多个数据源,把判断出类型的第一个数据源类型存到了 result 里,再用 result 对比后面的数据源,如果不同就会报错。
private DatabaseType createDatabaseType() throws SQLException { DatabaseType result = null; for (DataSource each : dataSourceMap.values()) { DatabaseType databaseType = createDatabaseType(each); Preconditions.checkState(null == result || result == databaseType, String.format("Database type inconsistent with '%s' and '%s'", result, databaseType)); result = databaseType; } return result; }

浙公网安备 33010602011771号