diff --git a/src/main/java/neatlogic/framework/datawarehouse/service/DatabaseService.java b/src/main/java/neatlogic/framework/datawarehouse/service/DatabaseService.java deleted file mode 100644 index 0a91a6d66d2f94aa41edd01c83af0163830d8d3a..0000000000000000000000000000000000000000 --- a/src/main/java/neatlogic/framework/datawarehouse/service/DatabaseService.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2025 深圳极向量科技有限公司 All Rights Reserved. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package neatlogic.framework.datawarehouse.service; - -import java.sql.Connection; -import java.sql.SQLException; - -public interface DatabaseService { - - Connection getConnectionByDatabaseId(Long databaseId) throws SQLException, InstantiationException, IllegalAccessException, ClassNotFoundException; -} diff --git a/src/main/java/neatlogic/framework/datawarehouse/service/DatabaseServiceImpl.java b/src/main/java/neatlogic/framework/datawarehouse/utils/DriverHolder.java similarity index 33% rename from src/main/java/neatlogic/framework/datawarehouse/service/DatabaseServiceImpl.java rename to src/main/java/neatlogic/framework/datawarehouse/utils/DriverHolder.java index d171a6c6c8e4c76aade599e76acd75af2d0fff0f..70cf4534e394f8679899d238c512a90711ec47a7 100644 --- a/src/main/java/neatlogic/framework/datawarehouse/service/DatabaseServiceImpl.java +++ b/src/main/java/neatlogic/framework/datawarehouse/utils/DriverHolder.java @@ -15,102 +15,89 @@ * along with this program. If not, see . */ -package neatlogic.framework.datawarehouse.service; +package neatlogic.framework.datawarehouse.utils; -import com.alibaba.fastjson.JSONObject; import neatlogic.framework.common.util.FileUtil; -import neatlogic.framework.datawarehouse.dao.mapper.DatabaseMapper; import neatlogic.framework.datawarehouse.dto.DatabaseVo; import neatlogic.framework.datawarehouse.exceptions.DatabaseConnectionFailedException; -import neatlogic.framework.datawarehouse.exceptions.DatabaseNotFoundException; -import neatlogic.framework.exception.file.FileNotFoundException; -import neatlogic.framework.file.dao.mapper.FileMapper; import neatlogic.framework.file.dto.FileVo; import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.collections4.MapUtils; -import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Service; -import javax.annotation.Resource; import java.io.File; +import java.io.IOException; import java.io.InputStream; 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.Driver; +import java.sql.DriverManager; import java.sql.SQLException; import java.util.List; -import java.util.Properties; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; -@Service -public class DatabaseServiceImpl implements DatabaseService { +public class DriverHolder { + private static final Logger logger = LoggerFactory.getLogger(DriverHolder.class); + private static final Map LOADER_MAP = new ConcurrentHashMap<>(); + private static final Map DRIVER_MAP = new ConcurrentHashMap<>(); - static Logger logger = LoggerFactory.getLogger(DatabaseServiceImpl.class); + public static synchronized Driver borrowDriver(DatabaseVo databaseVo) throws ClassNotFoundException, InstantiationException, IllegalAccessException { + Long id = databaseVo.getId(); + Driver driver = DRIVER_MAP.get(id); + if (driver != null) return driver; - @Resource - private DatabaseMapper databaseMapper; - - @Resource - private FileMapper fileMapper; - - - @Override - public Connection getConnectionByDatabaseId(Long databaseId) throws SQLException, InstantiationException, IllegalAccessException, ClassNotFoundException { - DatabaseVo dataBaseVo = databaseMapper.getDataBaseById(databaseId); - if (dataBaseVo == null) { - throw new DatabaseNotFoundException(databaseId); - } - List fileIdList = dataBaseVo.getFileIdList(); - if (CollectionUtils.isNotEmpty(fileIdList)) { - URL[] urls = new URL[fileIdList.size()]; - for (int i = 0; i < fileIdList.size(); i++) { - Long fileId = fileIdList.get(i); - FileVo fileVo = fileMapper.getFileById(fileId); - if (fileVo == null) { - throw new FileNotFoundException(fileId); - } - try (InputStream is = FileUtil.getData(fileVo.getPath())) { - String fileName = fileVo.getName(); - String suffix = ".jar"; - String prefix = fileName.substring(0, fileName.length() - suffix.length()); - File file = new File(prefix + "-" + fileVo.getId() + suffix); - if (!file.exists()) { + // 只在第一次创建 + List fileList = databaseVo.getFileList(); + if (CollectionUtils.isNotEmpty(fileList)) { + URL[] urls = new URL[fileList.size()]; + for (int i = 0; i < fileList.size(); i++) { + FileVo fileVo = fileList.get(i); + String fileName = fileVo.getName(); + String suffix = ".jar"; + String prefix = fileName.substring(0, fileName.length() - suffix.length()); + File file = new File(prefix + "-" + fileVo.getId() + suffix); + if (!file.exists()) { + try (InputStream is = FileUtil.getData(fileVo.getPath())) { Path path = Paths.get(file.toURI()); Files.copy(is, path); + urls[i] = file.toURI().toURL(); + } catch (Exception e) { + logger.error(e.getMessage(), e); + throw new RuntimeException(e); } - urls[i] = file.toURI().toURL(); - }catch (Exception e) { - logger.error(e.getMessage(), e); - throw new RuntimeException(e); - } - } - JSONObject config = dataBaseVo.getConfig(); - if (MapUtils.isNotEmpty(config)) { - String user = config.getString("user"); - String password = config.getString("password"); - String url = config.getString("url"); - String driverClassName = config.getString("driverClassName"); - Properties props = new Properties(); - if (StringUtils.isNoneBlank(user)) { - props.put("user", user); } - if (StringUtils.isNotBlank(password)) { - props.put("password", password); - } - URLClassLoader loader = new URLClassLoader(urls, null); - Class clazz = loader.loadClass(driverClassName); - Driver driver = ((Driver) clazz.newInstance()); - return driver.connect(url, props); - } else { - throw new DatabaseConnectionFailedException(DatabaseConnectionFailedException.Type.CONFIG_IS_EMPTY, dataBaseVo.getName()); } + URLClassLoader loader = new URLClassLoader(urls, DriverHolder.class.getClassLoader()); + Class clazz = loader.loadClass(databaseVo.getConfig().getString("driverClassName")); + driver = (Driver) clazz.newInstance(); + LOADER_MAP.put(id, loader); + DRIVER_MAP.put(id, driver); + return driver; } else { - throw new DatabaseConnectionFailedException(DatabaseConnectionFailedException.Type.FILE_ID_LIST_IS_EMPTY, dataBaseVo.getName()); + throw new DatabaseConnectionFailedException(DatabaseConnectionFailedException.Type.FILE_ID_LIST_IS_EMPTY, databaseVo.getName()); + } + } + + public static synchronized void destroyDriver(Long id) throws SQLException, IOException { + Driver driver = DRIVER_MAP.remove(id); + if (driver != null) { + try { + DriverManager.deregisterDriver(driver); + } catch (Exception e) { + logger.error(e.getMessage(), e); + } + } + URLClassLoader classLoader = LOADER_MAP.remove(id); + if (classLoader != null) { + try { + classLoader.close(); + } catch (Exception e) { + logger.error(e.getMessage(), e); + } } } } diff --git a/src/main/java/neatlogic/module/framework/datawarehouse/handler/JDBCDataSourceHandler.java b/src/main/java/neatlogic/module/framework/datawarehouse/handler/JDBCDataSourceHandler.java index 72baee90da03a815214df12a8a68a07d73d9e631..bccd76af6d3b8cf7cf2a752a91da349a888b38dd 100644 --- a/src/main/java/neatlogic/module/framework/datawarehouse/handler/JDBCDataSourceHandler.java +++ b/src/main/java/neatlogic/module/framework/datawarehouse/handler/JDBCDataSourceHandler.java @@ -17,12 +17,19 @@ package neatlogic.module.framework.datawarehouse.handler; +import com.alibaba.fastjson.JSONObject; import neatlogic.framework.datawarehouse.core.DataSourceServiceHandlerBase; import neatlogic.framework.datawarehouse.dao.mapper.DataWarehouseDataSourceMapper; +import neatlogic.framework.datawarehouse.dao.mapper.DatabaseMapper; import neatlogic.framework.datawarehouse.dto.*; +import neatlogic.framework.datawarehouse.exceptions.DatabaseConnectionFailedException; +import neatlogic.framework.datawarehouse.exceptions.DatabaseNotFoundException; import neatlogic.framework.datawarehouse.exceptions.ReportDataSourceSyncException; -import neatlogic.framework.datawarehouse.service.DatabaseService; +import neatlogic.framework.datawarehouse.utils.DriverHolder; +import neatlogic.framework.file.dao.mapper.FileMapper; +import neatlogic.framework.file.dto.FileVo; import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.MapUtils; import org.apache.commons.lang3.StringUtils; import org.dom4j.DocumentException; import org.slf4j.Logger; @@ -30,12 +37,8 @@ import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import javax.annotation.Resource; -import java.net.URLClassLoader; import java.sql.*; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; @Component public class JDBCDataSourceHandler extends DataSourceServiceHandlerBase { @@ -43,8 +46,12 @@ public class JDBCDataSourceHandler extends DataSourceServiceHandlerBase { int FETCH_SIZE = 1000; @Resource private DataWarehouseDataSourceMapper dataSourceMapper; + + @Resource + private DatabaseMapper databaseMapper; + @Resource - private DatabaseService databaseService; + private FileMapper fileMapper; @Override public String getHandler() { @@ -157,11 +164,7 @@ public class JDBCDataSourceHandler extends DataSourceServiceHandlerBase { queryStatement.close(); } if (conn != null) { - ClassLoader classLoader = conn.getClass().getClassLoader(); conn.close(); - if (classLoader instanceof URLClassLoader) { - ((URLClassLoader) classLoader).close(); - } } } catch (Exception e) { logger.error(e.getMessage(), e); @@ -170,6 +173,33 @@ public class JDBCDataSourceHandler extends DataSourceServiceHandlerBase { } private Connection getConnection(DataSourceVo dataSourceVo) throws SQLException, InstantiationException, IllegalAccessException, ClassNotFoundException { - return databaseService.getConnectionByDatabaseId(dataSourceVo.getDatabaseId()); + DatabaseVo databaseVo = databaseMapper.getDataBaseById(dataSourceVo.getDatabaseId()); + if (databaseVo == null) { + throw new DatabaseNotFoundException(dataSourceVo.getDatabaseId()); + } + List fileIdList = databaseVo.getFileIdList(); + if (CollectionUtils.isNotEmpty(fileIdList)) { + List fileList = fileMapper.getFileListByIdList(fileIdList); + databaseVo.setFileList(fileList); + } else { + throw new DatabaseConnectionFailedException(DatabaseConnectionFailedException.Type.FILE_ID_LIST_IS_EMPTY, databaseVo.getName()); + } + Driver driver = DriverHolder.borrowDriver(databaseVo); + JSONObject config = databaseVo.getConfig(); + if (MapUtils.isNotEmpty(config)) { + String user = config.getString("user"); + String password = config.getString("password"); + String url = config.getString("url"); + Properties props = new Properties(); + if (StringUtils.isNoneBlank(user)) { + props.put("user", user); + } + if (StringUtils.isNotBlank(password)) { + props.put("password", password); + } + return driver.connect(url, props); + } else { + throw new DatabaseConnectionFailedException(DatabaseConnectionFailedException.Type.CONFIG_IS_EMPTY, databaseVo.getName()); + } } }