- springboot依赖
<!--seata依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
<!--排除低版本seata依赖-->
<exclusions>
<exclusion>
<groupId>io.seata</groupId>
<artifactId>seata-all</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--添加⾼版本seata依赖-->
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-all</artifactId>
<version>1.5.2</version>
</dependency>
-
新建类 MyDbTypeParser
import io.seata.common.loader.LoadLevel; import io.seata.sqlparser.util.DbTypeParser; @LoadLevel(name = "druid", order = 1) public class MyDbTypeParser implements DbTypeParser { public MyDbTypeParser() { } @Override public String parseFromJdbcUrl(String jdbcUrl) { return "mysql"; } }
- 在resource目录下创建配置文件 新建文件夹 /META-INF/services 新建文件io.seata.sqlparser.util.DbTypeParser
io.seata.sqlparser.druid.MyDbTypeParser
- 拷贝seata-all.jar 下io.seata.rm.datasource.sql.struct.cache.MysqlTableMetaCache
修改其中一段内容
package io.seata.rm.datasource.sql.struct.cache; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Statement; import io.seata.common.exception.NotSupportYetException; import io.seata.common.exception.ShouldNeverHappenException; import io.seata.common.loader.LoadLevel; import io.seata.rm.datasource.ColumnUtils; 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 org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * The type Table meta cache. * * @author sharajava */ @LoadLevel(name = JdbcConstants.MYSQL, order = 1) public class MysqlTableMetaCache extends AbstractTableMetaCache { private static final Logger LOGGER = LoggerFactory.getLogger(MysqlTableMetaCache.class); @Override protected String getCacheKey(Connection connection, String tableName, String resourceId) { StringBuilder cacheKey = new StringBuilder(resourceId); cacheKey.append("."); //remove single quote and separate it to catalogName and tableName String[] tableNameWithCatalog = tableName.replace("`", "").split("\\."); String defaultTableName = tableNameWithCatalog.length > 1 ? tableNameWithCatalog[1] : tableNameWithCatalog[0]; DatabaseMetaData databaseMetaData = null; try { databaseMetaData = connection.getMetaData(); } catch (SQLException e) { LOGGER.error("Could not get connection, use default cache key {}", e.getMessage(), e); return cacheKey.append(defaultTableName).toString(); } try { //prevent duplicated cache key if (databaseMetaData.supportsMixedCaseIdentifiers()) { cacheKey.append(defaultTableName); } else { cacheKey.append(defaultTableName.toLowerCase()); } } catch (SQLException e) { LOGGER.error("Could not get supportsMixedCaseIdentifiers in connection metadata, use default cache key {}", e.getMessage(), e); return cacheKey.append(defaultTableName).toString(); } return cacheKey.toString(); } @Override protected TableMeta fetchSchema(Connection connection, String tableName) throws SQLException { String sql = "SELECT * FROM " + ColumnUtils.addEscape(tableName, JdbcConstants.MYSQL) + " LIMIT 1"; try (Statement stmt = connection.createStatement(); ResultSet rs = stmt.executeQuery(sql)) { return resultSetMetaToSchema(rs.getMetaData(), connection.getMetaData()); } catch (SQLException sqlEx) { throw sqlEx; } catch (Exception e) { throw new SQLException(String.format("Failed to fetch schema of %s", tableName), e); } } private TableMeta resultSetMetaToSchema(ResultSetMetaData rsmd, DatabaseMetaData dbmd) throws SQLException { //always "" for mysql String schemaName = rsmd.getSchemaName(1); String catalogName = rsmd.getCatalogName(1); /* * use ResultSetMetaData to get the pure table name * can avoid the problem below * * select * from account_tbl * select * from account_TBL * select * from `account_tbl` * select * from account.account_tbl */ String tableName = rsmd.getTableName(1); TableMeta tm = new TableMeta(); tm.setTableName(tableName); /* * here has two different type to get the data * make sure the table name was right * 1. show full columns from xxx from xxx(normal) * 2. select xxx from xxx where catalog_name like ? and table_name like ?(informationSchema=true) */ try (ResultSet rsColumns = dbmd.getColumns(catalogName, schemaName, tableName, "%"); ResultSet rsIndex = dbmd.getIndexInfo(catalogName, schemaName, tableName, false, true); ResultSet onUpdateColumns = dbmd.getVersionColumns(catalogName, 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")); col.setIsAutoincrement(rsColumns.getString("IS_AUTOINCREMENT")); if (tm.getAllColumns().containsKey(col.getColumnName())) { throw new NotSupportYetException("Not support the table has the same column name with different case yet"); } tm.getAllColumns().put(col.getColumnName(), col); } while (onUpdateColumns.next()) { tm.getAllColumns().get(onUpdateColumns.getString("COLUMN_NAME")).setOnUpdate(true); } while (rsIndex.next()) { String indexName = rsIndex.getString("INDEX_NAME"); 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); //添加内容 || (indexName!=null && indexName.contains("INDEX")) dm的主键索引是INDEX+数字 if ("PRIMARY".equalsIgnoreCase(indexName)|| (indexName!=null && indexName.contains("INDEX"))) { index.setIndextype(IndexType.PRIMARY); } else if (!index.isNonUnique()) { index.setIndextype(IndexType.UNIQUE); } else { index.setIndextype(IndexType.NORMAL); } tm.getAllIndexes().put(indexName, index); } } if (tm.getAllIndexes().isEmpty()) { throw new ShouldNeverHappenException("Could not found any index in the table: " + tableName); } } return tm; } }
- 修改dm8的dm.ini context是dm的关键字需要屏蔽 修改后需要重启数据库
EXCLUDE_RESERVED_WORDS = CONTEXT
也可以在dm_svc.conf配置文件中KEYWORDS配置项进行屏蔽 修改后需要重启数据库
KEY_WORDS=(CONTEXT)
dm_svc.conf DM安装时生产的一个
- seata配置加上
seata.client.rm.sql-parser-type=druid