项目需要连接不同版本的数据库,大多数情况下,最新版本的驱动包会兼容老版本的数据库,但仍存在新版的驱动连接老版本数据库出现不兼容的情况。
需要在同一个运行环境中同时加载多个不同版本的驱动对象。
先上代码
public void driverTest() throws Exception {
String userName = "username";
String password = "password";
String url = "jdbc:mysql://localhost:3306/schema";
String className = "com.mysql.jdbc.Driver";
String jarFilePath = "jar:file:/home/xxx/libs/mysql-connector-java-8.0.29.jar!/";
URLClassLoader loader = new URLClassLoader(new URL[]{new URL(jarFilePath)}, null);
Driver driver = (Driver) Class.forName(className, true, loader).newInstance();
Connection connection = null;
Properties info = new Properties();
info.put("user", userName);
info.put("password", password);
connection = driver.connect(url, info);
System.out.println(connection.getMetaData().getDatabaseProductVersion());
System.out.println(connection.getMetaData().getDriverVersion());
}
1. 类加载器
URLClassLoader loader = new URLClassLoader(new URL[]{new URL(jarFilePath)}, null);
jarFilePath指向类所在的jar包,指定类加载器装载驱动类的路径。
注意类加载器的parent需要设为null,否则它会将加载类通过双亲委派机制委派给AppClassLoader,如果AppClassLoader中已经存在同限定名的类(比如pom文件依赖),这里UrlClassLoader中加载的类会被忽略。
jar包路径需要添加前缀"jar:file:“与后缀”!/",不然会报错(mysql场景)。在连接其他数据库时,前缀与后缀需要按情况调整。
2.获取驱动与连接
Driver driver = (Driver) Class.forName(className, true, loader).newInstance();
...
connection = driver.connect(url, info);
Class.forName用于加载指定限定名的类,参数中需要指定类加载器loader。jdbc的驱动类被加载时,会被驱动管理器DriverManager管理,但是通过DriverManager.getConnection()方法获取连接时,无法指定类加载器/驱动对象,这里需要使用driver.connect()。
3. 线程池
public void druidTest() throws Exception {
String userName = "user";
String password = "password";
String url = "jdbc:mysql://localhost:3306/schema";
String className = "com.mysql.cj.jdbc.Driver";
String jarFilePath = "jar:file:/home/xxx/libs/mysql-connector-java-8.0.29.jar!/";
URLClassLoader loader = new URLClassLoader(new URL[]{new URL(jarFilePath)}, null);
DruidDataSource source = DruidDataSourceBuilder.create().build();
source.setUsername(userName);
source.setPassword(password);
source.setUrl(url);
source.setDriverClassName(className);
source.setDriverClassLoader(loader);
source.setInitialSize(10);
source.setMaxActive(10);
source.setMinIdle(3);
System.out.println(source.getConnection());
System.out.println(source.getConnection());
System.out.println(source.getConnection());
System.exit(0);
Connection connection = source.getConnection();
System.out.println(connection.getMetaData().getDatabaseProductVersion());
System.out.println(connection.getMetaData().getDriverVersion());
}
线程池用到的是阿里的druid。
hikari无法指定类加载器。