如何结合适配器与外观模式实现多数据库适配工具?
多数据库适配的可扩展实现方案
核心设计思路
采用抽象工厂模式+策略模式组合实现,配合依赖注入完成数据库类型的动态切换,既能满足当前MySQL、PostgreSQL的支持需求,也能轻松扩展后续新增的数据库类型。
步骤1:定义统一接口层
1.1 数据库操作接口(规范所有数据库行为)
public interface DatabaseOperations { List<String> getAllDatabases(Connection connection) throws SQLException; // 后续可按需添加其他操作接口,比如getTables、executeCustomQuery等 }
1.2 数据库连接器接口(负责连接创建与操作实例获取)
public interface DatabaseConnector { Connection getConnection(DatabaseModel db) throws IOException, SQLException; DatabaseOperations getDatabaseOperations(); }
步骤2:实现各数据库的具体类
2.1 PostgreSQL实现
操作类
public class PostgresDatabaseOperations implements DatabaseOperations { @Override public List<String> getAllDatabases(Connection connection) throws SQLException { List<String> databases = new ArrayList<>(); try (PreparedStatement stmt = connection.prepareStatement( "SELECT datname FROM pg_database WHERE datistemplate = false;")) { ResultSet rs = stmt.executeQuery(); while (rs.next()) { databases.add(rs.getString("datname")); } } return databases; } }
连接器类
public class PostgresConnector implements DatabaseConnector { @Override public Connection getConnection(DatabaseModel db) throws IOException, SQLException { // 实现PostgreSQL连接逻辑 String url = String.format("jdbc:postgresql://%s:%d/", db.getHost(), db.getPort()); return DriverManager.getConnection(url, db.getUsername(), db.getPassword()); } @Override public DatabaseOperations getDatabaseOperations() { return new PostgresDatabaseOperations(); } }
2.2 MySQL实现
操作类
public class MySqlDatabaseOperations implements DatabaseOperations { @Override public List<String> getAllDatabases(Connection connection) throws SQLException { List<String> databases = new ArrayList<>(); try (PreparedStatement stmt = connection.prepareStatement("SHOW DATABASES;")) { ResultSet rs = stmt.executeQuery(); while (rs.next()) { databases.add(rs.getString(1)); } } return databases; } }
连接器类
public class MySqlConnector implements DatabaseConnector { @Override public Connection getConnection(DatabaseModel db) throws IOException, SQLException { // 实现MySQL连接逻辑 String url = String.format("jdbc:mysql://%s:%d/", db.getHost(), db.getPort()); return DriverManager.getConnection(url, db.getUsername(), db.getPassword()); } @Override public DatabaseOperations getDatabaseOperations() { return new MySqlDatabaseOperations(); } }
步骤3:创建工厂类(替代原BaseAdapter的switch逻辑)
用工厂类统一管理连接器创建,避免硬编码switch,扩展新数据库时仅需新增Connector并更新工厂类即可。
public class DatabaseConnectorFactory { public static DatabaseConnector getConnector(String serverType) { return switch (serverType.toLowerCase()) { case "postgres" -> new PostgresConnector(); case "mysql" -> new MySqlConnector(); default -> throw new IllegalArgumentException("不支持的数据库类型: " + serverType); }; } }
步骤4:修改控制器与Service层
Service层接口(原migrationInterface)
public interface MigrationService { List<String> getAllDatabases(DatabaseModel db) throws IOException, SQLException; }
Service实现类
public class MigrationServiceImpl implements MigrationService { @Override public List<String> getAllDatabases(DatabaseModel db) throws IOException, SQLException { DatabaseConnector connector = DatabaseConnectorFactory.getConnector(db.getServerType()); try (Connection connection = connector.getConnection(db)) { return connector.getDatabaseOperations().getAllDatabases(connection); } } }
控制器修改(保留原有接口,简化内部逻辑)
@PostMapping("/allDatabases") public List<String> getDatabases(@RequestBody DatabaseModel db) throws IOException, SQLException { return migrationService.getAllDatabases(db); }
扩展新数据库的方式
- 新增对应数据库的
DatabaseOperations实现类,编写专属SQL逻辑 - 新增对应数据库的
DatabaseConnector实现类,实现连接逻辑并返回操作类实例 - 在
DatabaseConnectorFactory的switch分支中添加新的数据库类型判断
额外优化建议
- 用枚举定义支持的数据库类型,避免字符串硬编码错误
- 结合Spring依赖注入,将各Connector注册为Bean,工厂类直接从容器获取实例,进一步解耦
- 将SQL语句抽离到配置文件,方便维护与修改
内容的提问来源于stack exchange,提问作者Nisha
相关产品推荐
相关产品推荐

