nacos 默认支持的数据库是MySQL. 不支持Postgresql或其他数据库. 如果想使用其他数据有几种方式
import cn.agent.infrastructure.mysql2postgresql.driver.MysqlToPostgresDriver;
import javassist.*;
import java.io.IOException;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.Instrumentation;
import java.util.HashMap;
import java.util.Map;
/**
* Mysql驱动替换
* 在驱动类没有提供配置参数的情况下使用agent替换
*
* @author wxl
*/
public class JdbcDriverAgent {
private static final byte[] EMPTY_BYTE_ARRAY = {};
private static final String DEFAULT_MYSQL_JDBC_DRIVER_NAME = "com.mysql.cj.jdbc.Driver";
private static final String MYSQL_DRIVER_CLASS_NAME_KEY = "driverClassName";
private static final String MTO_DRIVER_NAME = MysqlToPostgresDriver.class.getName();
public static void premain(String agentArgs, Instrumentation inst) {
final ClassFileTransformer transformer = (loader, classFile, classBeingRedefined, protectionDomain, classfileBuffer) -> {
//Lambda
if (classFile == null) {
return EMPTY_BYTE_ARRAY;
}
final String className = toClassName(classFile);
final String mysqlDriverClassName = splitCommaColonStringToKv(agentArgs).getOrDefault(MYSQL_DRIVER_CLASS_NAME_KEY, DEFAULT_MYSQL_JDBC_DRIVER_NAME);
if (mysqlDriverClassName.equals(className)) {
ClassLoader classLoader = loader == null ? ClassLoader.getSystemClassLoader() : loader;
final ClassPool classPool = new ClassPool(true);
if (classLoader == null) {
classPool.appendClassPath(new LoaderClassPath(ClassLoader.getSystemClassLoader()));
} else {
classPool.appendClassPath(new LoaderClassPath(classLoader));
}
try {
CtClass ctClass = classPool.get(MTO_DRIVER_NAME);
ctClass.setName(mysqlDriverClassName);
return ctClass.toBytecode();
} catch (NotFoundException | CannotCompileException | IOException e) {
throw new IllegalStateException(e);
}
}
return EMPTY_BYTE_ARRAY;
};
inst.addTransformer(transformer, true);
}
private static String toClassName(final String classFile) {
return classFile.replace('/', '.');
}
/**
* Split to {@code json} like String({@code "k1:v1,k2:v2"}) to KV map({@code "k1"->"v1", "k2"->"v2"}).
*/
static Map<String, String> splitCommaColonStringToKv(String commaColonString) {
Map<String, String> ret = new HashMap<>(6);
if (commaColonString == null || commaColonString.trim().isEmpty()) {
return ret;
}
final String[] splitKvArray = commaColonString.trim().split("\\s*,\\s*");
for (String kvString : splitKvArray) {
final String[] kv = kvString.trim().split("\\s*:\\s*");
if (kv.length == 0) {
continue;
}
if (kv.length == 1) {
ret.put(kv[0], "");
} else {
ret.put(kv[0], kv[1]);
}
}
return ret;
}
}
import cn.agent.infrastructure.mysql2postgresql.wrapper.ConnectionWrapper;
import org.postgresql.Driver;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
/**
* @author wxl
*/
public class MysqlToPostgresDriver extends Driver {
private static final java.sql.Driver INSTANCE = new MysqlToPostgresDriver();
private static final String MYSQL = "mysql";
private static final String PG = "postgresql";
private static final String DEF_MYSQL_PORT = "3306";
private static final String DEF_PG_PORT = "5432";
static {
try {
DriverManager.registerDriver(MysqlToPostgresDriver.INSTANCE);
} catch (SQLException e) {
throw new IllegalStateException("Could not register MysqlToOracleDriver with DriverManager.", e);
}
}
@Override
public Connection connect(String url, Properties info) throws SQLException {
String replaceURL = replaceURL(url);
return ConnectionWrapper.wrap(super.connect(replaceURL, info));
}
@Override
public boolean acceptsURL(String url) {
String replaceURL = replaceURL(url);
return super.acceptsURL(replaceURL);
}
public String replaceURL(String url) {
if (url.contains(MYSQL)) {
url = url.replaceAll(MYSQL, PG);
}
if (url.contains(DEF_MYSQL_PORT)) {
url = url.replaceAll(DEF_MYSQL_PORT, DEF_PG_PORT);
}
return url;
}
}
JOOQ
@Override
public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
//TODO PG 中 autoGeneratedKeys 与 bigserial 不兼容
// 改成 cn.agent.infrastructure.mysql2postgresql.wrapper.ConnectionWrapper.prepareStatement(java.lang.String, java.lang.String[])
return delegate.prepareStatement(SqlHelper.mysql2postgresql(sql), new String[]{"id"});
// return PreparedStatementWrapper.wrap(delegate.prepareStatement(SqlHelper.mysql2postgresql(sql), autoGeneratedKeys), sql);
}