如何在多个含重复代码的Java方法中实现代码复用?附数据库查询代码
解决Java多方法间数据库代码复用的实用方案
针对你在多个包含重复数据库查询逻辑的Java方法里实现代码复用的需求,我整理了几个适配不同场景的方案,你可以根据项目的Java版本和架构来选择:
方案1:利用Java 9+接口私有方法(最推荐)
从Java 9开始,接口支持私有方法,刚好适合把你接口里重复的数据库连接、资源初始化这类逻辑抽出来,既保证复用性,又不会对外暴露这些内部逻辑。
比如修改你的MapReduceDAO接口:
public interface MapReduceDAO { String host = "mysql"; int port = 3306; String user = "root"; String password = "root"; String dbName = "customers"; default String customersMysqlUrl(String name) { return getDocker().containers().container(name).port(port).inFormat("$HOST:$EXTERNAL_PORT"); } default void checkTableHasData(Duration atMost, String tableName) throws Exception { // 直接调用私有复用方法获取查询实例 try (MysqlQuery mysqlQuery = createMysqlQuery()) { // 这里写你的表数据检查逻辑 // 比如:mysqlQuery.query("SELECT COUNT(*) FROM " + tableName)... } } // 新增私有方法,封装重复的JDBC连接逻辑 private MysqlQuery createMysqlQuery() throws Exception { String jdbcUrl = "jdbc:mysql://" + customersMysqlUrl(host) + "/" + dbName; return new MysqlQuery(jdbcUrl, user, password); } }
这样不管后续再新增多少个数据库操作的默认方法,都可以复用createMysqlQuery()的逻辑,不用重复写连接代码。
方案2:抽象类封装通用逻辑(兼容Java 8及以下)
如果你的项目还在使用Java 8,接口不支持私有方法,那可以把通用的常量和复用逻辑放到抽象类里,让DAO实现类继承它:
// 抽象基类,封装所有DAO通用的数据库配置和方法 public abstract class BaseDBDAO { protected String host = "mysql"; protected int port = 3306; protected String user = "root"; protected String password = "root"; protected String dbName = "customers"; protected String customersMysqlUrl(String name) { return getDocker().containers().container(name).port(port).inFormat("$HOST:$EXTERNAL_PORT"); } protected MysqlQuery createMysqlQuery() throws Exception { String jdbcUrl = "jdbc:mysql://" + customersMysqlUrl(host) + "/" + dbName; return new MysqlQuery(jdbcUrl, user, password); } // 定义抽象方法,保持原有业务契约 public abstract void checkTableHasData(Duration atMost, String tableName) throws Exception; } // 你的DAO实现类继承抽象类并实现业务逻辑 public class MapReduceDAOImpl extends BaseDBDAO implements MapReduceDAO { @Override public void checkTableHasData(Duration atMost, String tableName) throws Exception { try (MysqlQuery mysqlQuery = createMysqlQuery()) { // 具体的表数据检查逻辑 } } }
这种方式既兼容低版本Java,又能让所有DAO类复用通用逻辑,避免代码冗余。
方案3:独立工具类抽离通用操作
如果不想改动现有接口或类的继承结构,也可以把通用的数据库操作封装到一个静态工具类里,供所有需要的地方调用:
// 数据库工具类,封装无状态的通用操作 public class DBCommonUtils { private static final String host = "mysql"; private static final int port = 3306; private static final String user = "root"; private static final String password = "root"; private static final String dbName = "customers"; public static String getCustomersMysqlUrl(String name) { return getDocker().containers().container(name).port(port).inFormat("$HOST:$EXTERNAL_PORT"); } public static MysqlQuery createMysqlQuery() throws Exception { String jdbcUrl = "jdbc:mysql://" + getCustomersMysqlUrl(host) + "/" + dbName; return new MysqlQuery(jdbcUrl, user, password); } } // 在你的接口里直接调用工具类方法 public interface MapReduceDAO { default void checkTableHasData(Duration atMost, String tableName) throws Exception { try (MysqlQuery mysqlQuery = DBCommonUtils.createMysqlQuery()) { // 具体逻辑 } } }
工具类适合那种无状态、通用型极强的逻辑,调用起来简单直接,不过要注意如果涉及到共享资源,要保证线程安全。
总结
- 如果你用的是Java 9+,优先选接口私有方法,最贴合你现有接口的结构;
- 低版本Java选抽象类,兼顾兼容性和复用性;
- 通用逻辑跨多个模块的话,选工具类更灵活。
内容的提问来源于stack exchange,提问作者Saffik
相关产品推荐
相关产品推荐

