mirror of
https://gitee.com/dromara/dbswitch.git
synced 2025-09-23 12:44:15 +00:00
支持名称大小写转换
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
package com.gitee.dbswitch.data.entity;
|
||||
|
||||
import com.gitee.dbswitch.common.type.CaseConvertEnum;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -24,6 +25,8 @@ public class TargetDataSourceProperties {
|
||||
private Long maxLifeTime = TimeUnit.MINUTES.toMillis(30);
|
||||
|
||||
private String targetSchema = "";
|
||||
private CaseConvertEnum tableNameCase = CaseConvertEnum.NONE;
|
||||
private CaseConvertEnum columnNameCase = CaseConvertEnum.NONE;
|
||||
private Boolean targetDrop = Boolean.TRUE;
|
||||
private Boolean onlyCreate = Boolean.FALSE;
|
||||
private Boolean createTableAutoIncrement = Boolean.FALSE;
|
||||
|
@@ -18,6 +18,7 @@ import com.gitee.dbswitch.calculate.TaskParamEntity;
|
||||
import com.gitee.dbswitch.common.consts.Constants;
|
||||
import com.gitee.dbswitch.common.entity.CloseableDataSource;
|
||||
import com.gitee.dbswitch.common.entity.ResultSetWrapper;
|
||||
import com.gitee.dbswitch.common.type.CaseConvertEnum;
|
||||
import com.gitee.dbswitch.common.type.ProductTypeEnum;
|
||||
import com.gitee.dbswitch.common.util.DatabaseAwareUtils;
|
||||
import com.gitee.dbswitch.common.util.ExamineUtils;
|
||||
@@ -118,11 +119,26 @@ public class MigrationHandler implements Supplier<Long> {
|
||||
fetchSize = sourceProperties.getFetchSize();
|
||||
}
|
||||
|
||||
this.sourceProductType = DatabaseAwareUtils.getProductTypeByDataSource(sourceDataSource);
|
||||
this.targetProductType = DatabaseAwareUtils.getProductTypeByDataSource(targetDataSource);
|
||||
|
||||
if (this.targetProductType.isLikeHive()) {
|
||||
// !! hive does not support upper table name and column name
|
||||
properties.getTarget().setTableNameCase(CaseConvertEnum.LOWER);
|
||||
properties.getTarget().setColumnNameCase(CaseConvertEnum.LOWER);
|
||||
}
|
||||
|
||||
this.targetExistTables = targetExistTables;
|
||||
// 获取映射转换后新的表名
|
||||
this.targetSchemaName = properties.getTarget().getTargetSchema();
|
||||
this.targetTableName = PatterNameUtils.getFinalName(td.getTableName(),
|
||||
sourceProperties.getRegexTableMapper());
|
||||
this.targetTableName = properties.getTarget()
|
||||
.getTableNameCase()
|
||||
.convert(
|
||||
PatterNameUtils.getFinalName(
|
||||
td.getTableName(),
|
||||
sourceProperties.getRegexTableMapper()
|
||||
)
|
||||
);
|
||||
|
||||
if (StringUtils.isEmpty(this.targetTableName)) {
|
||||
throw new RuntimeException("表名的映射规则配置有误,不能将[" + this.sourceTableName + "]映射为空");
|
||||
@@ -141,10 +157,7 @@ public class MigrationHandler implements Supplier<Long> {
|
||||
public Long get() {
|
||||
log.info("Begin Migrate table for {}", tableNameMapString);
|
||||
|
||||
this.sourceProductType = DatabaseAwareUtils.getProductTypeByDataSource(sourceDataSource);
|
||||
this.targetProductType = DatabaseAwareUtils.getProductTypeByDataSource(targetDataSource);
|
||||
this.sourceMetaDataService = new DefaultMetadataService(sourceDataSource,
|
||||
sourceProductType);
|
||||
this.sourceMetaDataService = new DefaultMetadataService(sourceDataSource, sourceProductType);
|
||||
|
||||
// 读取源表的表及字段元数据
|
||||
this.sourceTableRemarks = sourceMetaDataService
|
||||
@@ -157,9 +170,12 @@ public class MigrationHandler implements Supplier<Long> {
|
||||
// 根据表的列名映射转换准备目标端表的字段信息
|
||||
this.targetColumnDescriptions = sourceColumnDescriptions.stream()
|
||||
.map(column -> {
|
||||
String newName = PatterNameUtils.getFinalName(
|
||||
column.getFieldName(),
|
||||
sourceProperties.getRegexColumnMapper());
|
||||
String newName = properties.getTarget().getColumnNameCase()
|
||||
.convert(
|
||||
PatterNameUtils.getFinalName(
|
||||
column.getFieldName(),
|
||||
sourceProperties.getRegexColumnMapper())
|
||||
);
|
||||
ColumnDescription description = column.copy();
|
||||
description.setFieldName(newName);
|
||||
description.setLabelName(newName);
|
||||
@@ -167,7 +183,12 @@ public class MigrationHandler implements Supplier<Long> {
|
||||
}).collect(Collectors.toList());
|
||||
this.targetPrimaryKeys = sourcePrimaryKeys.stream()
|
||||
.map(name ->
|
||||
PatterNameUtils.getFinalName(name, sourceProperties.getRegexColumnMapper())
|
||||
properties.getTarget().getColumnNameCase()
|
||||
.convert(
|
||||
PatterNameUtils.getFinalName(
|
||||
name,
|
||||
sourceProperties.getRegexColumnMapper())
|
||||
)
|
||||
).collect(Collectors.toList());
|
||||
|
||||
// 打印表名与字段名的映射关系
|
||||
|
@@ -12,29 +12,20 @@ package com.gitee.dbswitch.data.util;
|
||||
import cn.hutool.core.util.ClassLoaderUtil;
|
||||
import com.gitee.dbswitch.common.entity.CloseableDataSource;
|
||||
import com.gitee.dbswitch.common.entity.InvisibleDataSource;
|
||||
import com.gitee.dbswitch.common.entity.JarClassLoader;
|
||||
import com.gitee.dbswitch.common.util.ExamineUtils;
|
||||
import com.gitee.dbswitch.data.domain.WrapCommonDataSource;
|
||||
import com.gitee.dbswitch.data.domain.WrapHikariDataSource;
|
||||
import com.gitee.dbswitch.data.entity.SourceDataSourceProperties;
|
||||
import com.gitee.dbswitch.data.entity.TargetDataSourceProperties;
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.sql.Connection;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Properties;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import javax.sql.DataSource;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -58,7 +49,8 @@ public final class DataSourceUtils {
|
||||
* @param properties 数据库连接描述符
|
||||
* @return HikariDataSource连接池
|
||||
*/
|
||||
public static CloseableDataSource createSourceDataSource(SourceDataSourceProperties properties) {
|
||||
public static CloseableDataSource createSourceDataSource(
|
||||
SourceDataSourceProperties properties) {
|
||||
Properties parameters = new Properties();
|
||||
HikariDataSource ds = new HikariDataSource();
|
||||
ds.setPoolName("The_Source_DB_Connection");
|
||||
@@ -102,7 +94,8 @@ public final class DataSourceUtils {
|
||||
* @param properties 数据库连接描述符
|
||||
* @return HikariDataSource连接池
|
||||
*/
|
||||
public static CloseableDataSource createTargetDataSource(TargetDataSourceProperties properties) {
|
||||
public static CloseableDataSource createTargetDataSource(
|
||||
TargetDataSourceProperties properties) {
|
||||
HikariDataSource ds = new HikariDataSource();
|
||||
ds.setPoolName("The_Target_DB_Connection");
|
||||
ds.setJdbcUrl(properties.getUrl());
|
||||
@@ -151,10 +144,15 @@ public final class DataSourceUtils {
|
||||
return new WrapHikariDataSource(ds, urlClassLoader);
|
||||
}
|
||||
|
||||
public static CloseableDataSource createCommonDataSource(String jdbcUrl,
|
||||
String driverClass, String driverPath,
|
||||
String username, String password) {
|
||||
URLClassLoader urlClassLoader = createURLClassLoader(driverPath, driverClass);
|
||||
public static CloseableDataSource createCommonDataSource(
|
||||
String jdbcUrl,
|
||||
String driverClass,
|
||||
String driverPath,
|
||||
String username,
|
||||
String password) {
|
||||
URLClassLoader urlClassLoader = createURLClassLoader(
|
||||
driverPath,
|
||||
driverClass);
|
||||
InvisibleDataSource dataSource = createInvisibleDataSource(
|
||||
urlClassLoader,
|
||||
jdbcUrl,
|
||||
@@ -166,65 +164,46 @@ public final class DataSourceUtils {
|
||||
return new WrapCommonDataSource(dataSource, urlClassLoader);
|
||||
}
|
||||
|
||||
private static InvisibleDataSource createInvisibleDataSource(ClassLoader cl,
|
||||
String jdbcUrl, String driverClass, String username,
|
||||
String password, Properties properties) {
|
||||
return new InvisibleDataSource(cl, jdbcUrl, driverClass, username, password, properties);
|
||||
private static InvisibleDataSource createInvisibleDataSource(
|
||||
ClassLoader cl,
|
||||
String jdbcUrl,
|
||||
String driverClass,
|
||||
String username,
|
||||
String password,
|
||||
Properties properties) {
|
||||
return new InvisibleDataSource(
|
||||
cl,
|
||||
jdbcUrl,
|
||||
driverClass,
|
||||
username,
|
||||
password,
|
||||
properties);
|
||||
}
|
||||
|
||||
private static URLClassLoader createURLClassLoader(String driverPath, String driverClass) {
|
||||
if (StringUtils.isBlank(driverPath)) {
|
||||
throw new RuntimeException("Invalid driver path,can not be empty!");
|
||||
}
|
||||
if (StringUtils.isBlank(driverClass)) {
|
||||
throw new RuntimeException("Invalid driver class,can not be empty!");
|
||||
}
|
||||
List<Path> filePaths = findJarFilesFromDirectory(driverPath);
|
||||
if (filePaths.isEmpty()) {
|
||||
throw new RuntimeException("No jar file found from path:" + driverPath + "!");
|
||||
}
|
||||
URL[] urls = filePaths.stream().map(path -> convertPath2URL(path)).toArray(URL[]::new);
|
||||
private static URLClassLoader createURLClassLoader(
|
||||
String driverPath, String driverClass) {
|
||||
ExamineUtils.checkArgument(
|
||||
StringUtils.isNoneBlank(driverPath),
|
||||
"Invalid driver path,can not be empty!");
|
||||
ExamineUtils.checkArgument(
|
||||
StringUtils.isNoneBlank(driverClass),
|
||||
"Invalid driver class,can not be empty!");
|
||||
ClassLoader parent = driverClass.contains("postgresql")
|
||||
? ClassLoaderUtil.getContextClassLoader()
|
||||
: ClassLoaderUtil.getSystemClassLoader().getParent();
|
||||
URLClassLoader loader = new URLClassLoader(urls, parent);
|
||||
URLClassLoader loader = new JarClassLoader(driverPath, parent);
|
||||
try {
|
||||
Class<?> clazz = loader.loadClass(driverClass);
|
||||
clazz.newInstance();
|
||||
clazz.getConstructor().newInstance();
|
||||
return loader;
|
||||
} catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) {
|
||||
} catch (Exception e) {
|
||||
log.error("Could not load class : {} from driver path: {}", driverClass, driverPath, e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static URL convertPath2URL(Path path) {
|
||||
try {
|
||||
return path.toUri().toURL();
|
||||
} catch (MalformedURLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static List<Path> findJarFilesFromDirectory(String path) {
|
||||
File file = new File(path);
|
||||
if (!file.exists()) {
|
||||
throw new RuntimeException("Path:" + path + " is not exists!");
|
||||
}
|
||||
Predicate<Path> fileFilter = f -> {
|
||||
String fileName = f.toFile().getName();
|
||||
return fileName.endsWith(".jar") || fileName.endsWith(".JAR");
|
||||
};
|
||||
try (Stream<Path> paths = Files.walk(Paths.get(path))) {
|
||||
return paths.filter(Files::isRegularFile)
|
||||
.filter(fileFilter)
|
||||
.collect(Collectors.toList());
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static String executeStringReturnedSql(DataSource dataSource, String sql) {
|
||||
private static String executeStringReturnedSql(
|
||||
DataSource dataSource, String sql) {
|
||||
try (Connection connection = dataSource.getConnection()) {
|
||||
try (Statement statement = connection.createStatement()) {
|
||||
try (ResultSet resultSet = statement.executeQuery(sql)) {
|
||||
|
@@ -5,7 +5,7 @@ dbswitch:
|
||||
## support multiple source database connection
|
||||
- url: jdbc:mysql://172.17.2.10:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true&tinyInt1isBit=false&rewriteBatchedStatements=true&useCompression=true
|
||||
driver-class-name: 'com.mysql.jdbc.Driver'
|
||||
driver-path: D:/Workspace/dbswitch/drivers/mysql/mysql-5
|
||||
driver-path: D:\Workspace\IdeaProjects\dbswitch\drivers\mysql\mysql-5
|
||||
username: 'test'
|
||||
password: '123456'
|
||||
# source database configuration parameters
|
||||
@@ -31,12 +31,14 @@ dbswitch:
|
||||
## Best support for Oracle/PostgreSQL/Greenplum/DM etc.
|
||||
url: jdbc:postgresql://172.17.2.10:5432/test
|
||||
driver-class-name: org.postgresql.Driver
|
||||
driver-path: D:/Workspace/dbswitch/drivers/postgresql/postgresql-11.4
|
||||
username: 'test'
|
||||
driver-path: D:\Workspace\IdeaProjects\dbswitch\drivers\postgresql\postgresql-11.4
|
||||
username: 'postgres'
|
||||
password: '123456'
|
||||
# target database configuration parameters
|
||||
## schema name for create/insert table data
|
||||
target-schema: public
|
||||
table-name-case: UPPER
|
||||
column-name-case: UPPER
|
||||
## whether drop-create table when target table exist
|
||||
target-drop: true
|
||||
## whether create table support auto increment for primary key field
|
||||
|
Reference in New Issue
Block a user