seata适配人大金仓(kingbase8)数据库

一、seata源码环境准备

  • seata文档地址
  • 源码下载地址
  • 本文下载的源码版本是:1.4.1.1

二、seata源码环境编译

使用idea开发工具,打开你下载好的seata源码,并下载好相关jar包依赖。
编译好的源码环境如下:

三、seata适配kingbase8

注意:
如果想适配dm达梦数据库,由于undo_log表会出现context关键字问题,所以这里得改下这个字段,改成context_即可。

io.seata.core.constants.ClientTableColumnsName.java

String UNDO_LOG_CONTEXT = "context_";

注意,改了之后,对应的sql语句,也记得修改下。

3.1 seata-core的修改

增加io.seata.core.store.db.sql.lock.KingbaseLockStoreSql.java
注意:KingbaseLockStoreSql.java,继承OracleLockStoreSql.java

加入到配置文件中:META-INF/services/io.seata.core.store.db.sql.lock.LockStoreSql

增加io.seata.core.store.db.sql.log.KingBaseLogStoreSqls.java
注意:KingBaseLogStoreSqls.java,继承OracleLogStoreSqls.java

加入到配置文件中:META-INF/services/io.seata.core.store.db.sql.log.LogStoreSqls

io.seata.core.constants.DBType.java 增加 kingbase

修改io.seata.core.store.db.AbstractDataSourceProvider.java,getValidationQuery()方法
支持kingbase的类型

3.2 seata-sqlparser-core修改

修改io.seata.sqlparser.util.JdbcConstants.java , 增加kingbase常量

3.3 seata-sqlparser-druid修改

io.seata.sqlparser.druid–>增加kingbase包以及内部的java,模仿oracle的即可。
注意:需要修改的地方有:
(1)常量JdbcConstants.KINGBASE
(2)构造方法

加入到配置文件中:META-INF/services/io.seata.sqlparser.druid.SQLOperateRecognizerHolder

3.4 seata-rm-datasource的修改

增加io.seata.rm.datasource.exec.kingbase.KingbaseInsertExecutor.java
注意:KingbaseInsertExecutor.java,模仿OracleInsertExecutor.java

代码如下:

/**  Copyright 1999-2019 Seata.io Group.**  Licensed under the Apache License, Version 2.0 (the "License");*  you may not use this file except in compliance with the License.*  You may obtain a copy of the License at**       http://www.apache.org/licenses/LICENSE-2.0**  Unless required by applicable law or agreed to in writing, software*  distributed under the License is distributed on an "AS IS" BASIS,*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.*  See the License for the specific language governing permissions and*  limitations under the License.*/
package io.seata.rm.datasource.exec.kingbase;import io.seata.common.exception.NotSupportYetException;
import io.seata.common.loader.LoadLevel;
import io.seata.common.loader.Scope;
import io.seata.rm.datasource.StatementProxy;
import io.seata.rm.datasource.exec.BaseInsertExecutor;
import io.seata.rm.datasource.exec.StatementCallback;
import io.seata.sqlparser.SQLRecognizer;
import io.seata.sqlparser.struct.Null;
import io.seata.sqlparser.struct.Sequenceable;
import io.seata.sqlparser.struct.SqlMethodExpr;
import io.seata.sqlparser.struct.SqlSequenceExpr;
import io.seata.sqlparser.util.JdbcConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.sql.SQLException;
import java.util.Collections;
import java.util.List;
import java.util.Map;/*** @author llsydn*/
@LoadLevel(name = JdbcConstants.KINGBASE, scope = Scope.PROTOTYPE)
public class KingbaseInsertExecutor extends BaseInsertExecutor implements Sequenceable {private static final Logger LOGGER = LoggerFactory.getLogger(KingbaseInsertExecutor.class);/*** Instantiates a new Abstract dml base executor.** @param statementProxy    the statement proxy* @param statementCallback the statement callback* @param sqlRecognizer     the sql recognizer*/public KingbaseInsertExecutor(StatementProxy statementProxy, StatementCallback statementCallback,SQLRecognizer sqlRecognizer) {super(statementProxy, statementCallback, sqlRecognizer);}@Overridepublic Map<String,List<Object>> getPkValues() throws SQLException {Map<String,List<Object>> pkValuesMap = null;Boolean isContainsPk = containsPK();//when there is only one pk in the tableif (isContainsPk) {pkValuesMap = getPkValuesByColumn();}else if (containsColumns()) {String columnName = getTableMeta().getPrimaryKeyOnlyName().get(0);pkValuesMap = Collections.singletonMap(columnName, getGeneratedKeys());}else {pkValuesMap = getPkValuesByColumn();}return pkValuesMap;}@Overridepublic Map<String,List<Object>> getPkValuesByColumn() throws SQLException {Map<String,List<Object>> pkValuesMap  = parsePkValuesFromStatement();String pkKey = pkValuesMap.keySet().iterator().next();List<Object> pkValues = pkValuesMap.get(pkKey);if (!pkValues.isEmpty() && pkValues.get(0) instanceof SqlSequenceExpr) {pkValuesMap.put(pkKey,getPkValuesBySequence((SqlSequenceExpr) pkValues.get(0)));} else if (pkValues.size() == 1 && pkValues.get(0) instanceof SqlMethodExpr) {pkValuesMap.put(pkKey,getGeneratedKeys());} else if (pkValues.size() == 1 && pkValues.get(0) instanceof Null) {throw new NotSupportYetException("oracle not support null");}return pkValuesMap;}@Overridepublic String getSequenceSql(SqlSequenceExpr expr) {return "SELECT " + expr.getSequence() + ".currval FROM DUAL";}
}

加入到配置文件:META-INF/services/io.seata.rm.datasource.exec.InsertExecutor

增加io.seata.rm.datasource.sql.struct.cache.KingbaseTableMetaCache.java
注意:KingbaseTableMetaCache.java,模仿OracleTableMetaCache.java

代码如下:

/**  Copyright 1999-2019 Seata.io Group.**  Licensed under the Apache License, Version 2.0 (the "License");*  you may not use this file except in compliance with the License.*  You may obtain a copy of the License at**       http://www.apache.org/licenses/LICENSE-2.0**  Unless required by applicable law or agreed to in writing, software*  distributed under the License is distributed on an "AS IS" BASIS,*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.*  See the License for the specific language governing permissions and*  limitations under the License.*/
package io.seata.rm.datasource.sql.struct.cache;import io.seata.common.exception.ShouldNeverHappenException;
import io.seata.common.loader.LoadLevel;
import io.seata.common.util.StringUtils;
import io.seata.rm.datasource.sql.struct.ColumnMeta;
import io.seata.rm.datasource.sql.struct.IndexMeta;
import io.seata.rm.datasource.sql.struct.IndexType;
import io.seata.rm.datasource.sql.struct.TableMeta;
import io.seata.sqlparser.util.JdbcConstants;import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;/*** The type Table meta cache.** @author llsydn*/
@LoadLevel(name = JdbcConstants.KINGBASE)
public class KingbaseTableMetaCache extends AbstractTableMetaCache {@Overrideprotected String getCacheKey(Connection connection, String tableName, String resourceId) {StringBuilder cacheKey = new StringBuilder(resourceId);cacheKey.append(".");//separate it to schemaName and tableNameString[] tableNameWithSchema = tableName.split("\\.");String defaultTableName = tableNameWithSchema.length > 1 ? tableNameWithSchema[1] : tableNameWithSchema[0];//oracle does not implement supportsMixedCaseIdentifiers in DatabaseMetadataif (defaultTableName.contains("\"")) {cacheKey.append(defaultTableName.replace("\"", ""));} else {// oracle default store in upper casecacheKey.append(defaultTableName.toUpperCase());}return cacheKey.toString();}@Overrideprotected TableMeta fetchSchema(Connection connection, String tableName) throws SQLException {try {return resultSetMetaToSchema(connection.getMetaData(), tableName);} catch (SQLException sqlEx) {throw sqlEx;} catch (Exception e) {throw new SQLException(String.format("Failed to fetch schema of %s", tableName), e);}}private TableMeta resultSetMetaToSchema(DatabaseMetaData dbmd, String tableName) throws SQLException {TableMeta tm = new TableMeta();tm.setTableName(tableName);String[] schemaTable = tableName.split("\\.");String schemaName = schemaTable.length > 1 ? schemaTable[0] : dbmd.getUserName();tableName = schemaTable.length > 1 ? schemaTable[1] : tableName;if (schemaName.contains("\"")) {schemaName = schemaName.replace("\"", "");} else {schemaName = schemaName.toUpperCase();}schemaName="PUBLIC";if (tableName.contains("\"")) {tableName = tableName.replace("\"", "");} else {tableName = tableName.toUpperCase();}try (ResultSet rsColumns = dbmd.getColumns("", schemaName, tableName, "%");ResultSet rsIndex = dbmd.getIndexInfo(null, schemaName, tableName, false, true);ResultSet rsPrimary = dbmd.getPrimaryKeys(null, schemaName, tableName)) {while (rsColumns.next()) {ColumnMeta col = new ColumnMeta();col.setTableCat(rsColumns.getString("TABLE_CAT"));col.setTableSchemaName(rsColumns.getString("TABLE_SCHEM"));col.setTableName(rsColumns.getString("TABLE_NAME"));col.setColumnName(rsColumns.getString("COLUMN_NAME"));col.setDataType(rsColumns.getInt("DATA_TYPE"));col.setDataTypeName(rsColumns.getString("TYPE_NAME"));col.setColumnSize(rsColumns.getInt("COLUMN_SIZE"));col.setDecimalDigits(rsColumns.getInt("DECIMAL_DIGITS"));col.setNumPrecRadix(rsColumns.getInt("NUM_PREC_RADIX"));col.setNullAble(rsColumns.getInt("NULLABLE"));col.setRemarks(rsColumns.getString("REMARKS"));col.setColumnDef(rsColumns.getString("COLUMN_DEF"));col.setSqlDataType(rsColumns.getInt("SQL_DATA_TYPE"));col.setSqlDatetimeSub(rsColumns.getInt("SQL_DATETIME_SUB"));col.setCharOctetLength(rsColumns.getInt("CHAR_OCTET_LENGTH"));col.setOrdinalPosition(rsColumns.getInt("ORDINAL_POSITION"));col.setIsNullAble(rsColumns.getString("IS_NULLABLE"));tm.getAllColumns().put(col.getColumnName(), col);}while (rsIndex.next()) {String indexName = rsIndex.getString("INDEX_NAME");if (StringUtils.isNullOrEmpty(indexName)) {continue;}String colName = rsIndex.getString("COLUMN_NAME");ColumnMeta col = tm.getAllColumns().get(colName);if (tm.getAllIndexes().containsKey(indexName)) {IndexMeta index = tm.getAllIndexes().get(indexName);index.getValues().add(col);} else {IndexMeta index = new IndexMeta();index.setIndexName(indexName);index.setNonUnique(rsIndex.getBoolean("NON_UNIQUE"));index.setIndexQualifier(rsIndex.getString("INDEX_QUALIFIER"));index.setIndexName(rsIndex.getString("INDEX_NAME"));index.setType(rsIndex.getShort("TYPE"));index.setOrdinalPosition(rsIndex.getShort("ORDINAL_POSITION"));index.setAscOrDesc(rsIndex.getString("ASC_OR_DESC"));index.setCardinality(rsIndex.getInt("CARDINALITY"));index.getValues().add(col);if (!index.isNonUnique()) {index.setIndextype(IndexType.UNIQUE);} else {index.setIndextype(IndexType.NORMAL);}tm.getAllIndexes().put(indexName, index);}}while (rsPrimary.next()) {String pkIndexName = rsPrimary.getString("PK_NAME");if (tm.getAllIndexes().containsKey(pkIndexName)) {IndexMeta index = tm.getAllIndexes().get(pkIndexName);index.setIndextype(IndexType.PRIMARY);}else {String colName = rsPrimary.getString("COLUMN_NAME");ColumnMeta col = tm.getAllColumns().get(colName);IndexMeta index = new IndexMeta();index.getValues().add(col);index.setIndextype(IndexType.PRIMARY);tm.getAllIndexes().put(pkIndexName, index);}}if (tm.getAllIndexes().isEmpty()) {throw new ShouldNeverHappenException(String.format("Could not found any index in the table: %s", tableName));}}return tm;}
}

加入到配置文件中:META-INF/services/io.seata.rm.datasource.sql.struct.TableMetaCache

io.seata.rm.datasource.undo–>增加kingbase包以及内部的java,模仿oracle的即可。
注意:需要修改的地方有:
(1)常量JdbcConstants.KINGBASE
(2)构造方法

加入到配置文件中:META-INF/services/io.seata.rm.datasource.undo.KeywordChecker

加入到配置文件中:META-INF/services/io.seata.rm.datasource.undo.UndoLogManager

加入到配置文件中:META-INF/services/io.seata.rm.datasource.undo.UndoExecutorHolder

四、seata修改ip有效性校验

seata在启动时,会对 “-h ip” 进行有效性校验,并且 “127.0.0.1 and 0.0.0.0” 也是校验不通过的
在docker容器、需要注册到外网ip、需要注册到域名,那都是校验失败的
所以这里对源码进行修改,seata启动时,不校验ip的有效性。

修改io.seata.server.Server.java,main()方法

五、修改后seata源码打包

右键:pom.xml,选择Run Maven --> New Goal --> -Dmaven.test.skip=true -Dcheckstyle.skip=true clean install -U

打包成功后,是放在seata-distribution下面,直接就是和在官网下载的seata服务一样的文件

这里要注意:要将kingbase8的驱动jar包,手动拷贝放入到lib下面。

至此:seata的适配kingbase8,并重新打包源码,已完成

  • seata配合nacos使用,需要修改的配置如下:

store.db.url = jdbc:kingbase8://xxx.xxx.x.xx:54321/db1
store.db.driverClassName = com.kingbase8.Driver
store.db.dbType = kingbase
store.db.user = root
store.db.password = 123456

六、项目中使用seata

  • 在项目中需要引入seata相关得依赖
<dependency><groupId>io.seata</groupId><artifactId>seata-all</artifactId><version>1.4.1.1</version>
</dependency><dependency><groupId>io.seata</groupId><artifactId>seata-spring-boot-starter</artifactId><version>1.4.1.1</version>
</dependency>

配置文件:

seata:enabled: trueapplication-id: ${spring.application.name}tx-service-group: llsydn_tx_groupenable-auto-data-source-proxy: trueregistry:type: nacosnacos:application: seata-servernamespace: ${nacos.namespace}server-addr: ${nacos.address}group : DEFAULT_GROUPuserName: ${nacos.username}password: ${nacos.password}config:type: nacosnacos:namespace: ${nacos.namespace}serverAddr: ${nacos.address}group: SEATA_GROUPcluster: defaultuserName: ${nacos.username}password: ${nacos.password}
  • kingbase8的jar包依赖
  • 修改的源码地址,联系qq:1091391667

seata适配人大金仓(kingbase8)数据库相关推荐

  1. Kettle连接人大金仓KingbaseES数据库

    Kettle连接人大金仓KingbaseES数据库 1.驱动下载.在人大金仓官网–>通用型数据库–>接口驱动–> JDBC 驱动程序 X86(第一个驱动包)下载出来,直达链接(点此直 ...

  2. 如何查询当前表空间下所有实例_详解人大金仓MPP数据库并行查询技术

    什么是MPP数据库? 人大金仓MPP数据库的 并行查询技术原理是什么? 如何实现并行查询?性能如何? 且听以下详细分解~ 01 什么是人大金仓MPP数据库? KingbaseAnalyticsDB(简 ...

  3. 金仓数据库字段_技术干货 | 超实用!详解人大金仓MPP数据库并行查询技术

    什么是MPP数据库? 人大金仓MPP数据库的 并行查询技术原理是什么? 如何实现并行查询?性能如何? 且听以下详细分解~ 01 什么是人大金仓MPP数据库? KingbaseAnalyticsDB(简 ...

  4. 人大金仓国产化数据库适配

    最近公司接到需求,项目要进行国产化适配,数据库是人大金仓中间件是TongWeb浏览器是uos,项目所用到的技术是LayuiAdmin.ssm.mybatis-plus.springboot等,数据源切 ...

  5. BDTC 2017数据库:犹他大学、东方国信、蚂蚁金服、微软、人大金仓畅谈数据库发展与实践...

    [CSDN现场报道]12月7-9日,由中国计算机学会主办,CCF 大数据专家委员会承办,中国科学院计算技术研究所.中科天玑数据科技股份有限公司.CSDN协办的2017中国大数据技术大会(BDTC 20 ...

  6. CentOS7环境下 人大金仓kes86数据库安装过程

    安装前确认 操作系统:主机名.IP地址.发型版本.内核版本 [root@localhost ~]# hostname localhost.localdomain [root@localhost ~]# ...

  7. 普元 EOS Platform 7.6适配人大金仓v8

    先说下普元7.6,普元7.6最大支持编译JDK1.7.然后在它默认的数据源里,最大支持人大金仓V7. 实际使用中,可以使用JDK1.8,也可以连接人大金仓V8. 人大金仓V8记得朝人大金仓要jar包( ...

  8. DBeaver连接人大金仓kingbase数据库配置

    1.打开DBeaver软件,点击"数据库",选择"驱动管理器". 2.点击"新建"进行人大金仓驱动管理器配置. 3.填写驱动配置信息,配置完 ...

  9. XXL-JOB适配人大金仓数据库kingbase

    一:背景 XXL-JOB版本是2.2.1-SNAPSHOT 二:配置连接池 2.1 首先找到xxl-job-admin目录下的pom.xml文件,把原本mysql-connector-java连接包注 ...

最新文章

  1. mysql隐藏密码_MySQL在Linux系统中隐藏命令行中的密码的方法
  2. 硕士生两年发14篇论文!获浙大最高层次奖学金!
  3. Prismatic 机器学习不一定得用大框架
  4. SQL Server 2005 Service Broker 初探
  5. easyexcel 无模板写入_给位,问个问题,用easyExcel无模板导出数据时,怎么在指定单元格添加计算公式呢?...
  6. HashMap(摘)
  7. 在雅加达EE TCK中使用Arquillian的可能方法
  8. 工作406- Error:Node Sass version 5.0.0 is incompatible with ^4.0.0 问题解决
  9. 十三、MySQL存储过程相关知识总结 + 案例讲解(强化)
  10. css-背景图片和渐变
  11. oracle没有注册mdsdora,oracle rac一个节点服务注册不上,必须重启监听才能注册上,各位大神帮忙看一下...
  12. 青蛙吃蚊子小游戏源码
  13. Spring MVC 基础笔记
  14. vscode运行html的插件_vscode前端常用插件推荐,搭建JQuery、Vue等开发环境
  15. C#调用系统的复制、移动、删除文件对话框
  16. C++中常量指针,指针常量(const 和*)的使用方法和理解方法
  17. Vue 服务端渲染(SSR)、Nuxt.js - 从入门到实践
  18. 利用sklearn实现adaboost,以单一分类树为例
  19. MongoDB高可用集群搭建(主从、分片、路由、安全验证)
  20. 水星怎么设置网速最快_水星路由器怎么设置网速 - 卡饭网

热门文章

  1. Python可以用来做什么?
  2. Linux下给python3安装库
  3. python查找中间值
  4. 常用的Linux快捷键 [译]
  5. AW codec驱动跨平台移植
  6. 如何从零开始搭建一个网站
  7. python爬取京东手机参数_python爬虫——分页爬取京东商城商品信息(手机为例)...
  8. 数据分析的五大用处,你都知道吗?
  9. 【Javascript】javascript 中的指针
  10. 玩转console.log 如何在console.log里面插入图片