Java - 用于重复sql任务的设计模式

时间:2015-09-08 16:43:05

标签: java mysql sql design-patterns interface

我有不同的方法,它们从数据库中查询不同的数据,但每种方法的主要结构都是相同的。为了减少代码,我想缩小它,但我不知道如何。我已经尝试过接口但是返回语句不能从内部类调用。 (它应该是类型安全的!)

结构:

public <special type> getXYdata(some parameters) {
    try (Connection connection = mDataSource.getConnection();
                 Statement statement = connection.createStatement();
                 ResultSet results = statement.executeQuery(... special query ...)
    ) {
        // Handle ResultsSet and return object of a special type.
    } catch (SQLTimeoutException e) {
        throw new ContentManagerException("Query took to long or connection timed out", e);
    } catch (SQLException e) {
        throw new ContentManagerException("Query or parsing its results failed", e);
    }
}

点子:

private interface QHandler<T> {
    String getQuery();
    T handleResultSet(ResultSet set) throws SQLException;
}

然后:

private void executeQuery(QHandler handler) throws ContentManagerException {
    try (Connection connection = mDataSource.getConnection();
        Statement statement = connection.createStatement();
        ResultSet results = statement.executeQuery(handler.getQuery())
    ) {
        handler.handleResultSet(results);
    } catch (SQLTimeoutException e) {
        throw new ContentManagerException("Query took to long or connection timed out", e);
    } catch (SQLException e) {
        throw new ContentManagerException("Query or parsing its results failed", e);
    }
}

但是如果我在我的一个数据方法中调用这个私有方法,我就无法从handleResultSet()方法返回一个对象,因为return语句会影响这个接口方法。是否有一个选项,告诉execiteQuery()方法处理程序有哪种返回类型?

注意:它必须是类型安全的,如果可能的话不能进行投射!

2 个答案:

答案 0 :(得分:2)

您的方法不应使用原始QHandler类型,并且应该是通用的:

private <T> T executeQuery(QHandler<T> handler) throws ContentManagerException {
    try (Connection connection = mDataSource.getConnection();
        Statement statement = connection.createStatement();
        ResultSet results = statement.executeQuery(handler.getQuery())
    ) {
        return handler.handleResultSet(results);
    } catch (SQLTimeoutException e) {
        throw new ContentManagerException("Query took to long or connection timed out", e);
    } catch (SQLException e) {
        throw new ContentManagerException("Query or parsing its results failed", e);
    }
}

请注意,您正在尝试重新发明Spring的JdbcTemplate。您可以考虑使用它而不是重新发明它。

答案 1 :(得分:0)

也许您对替代解决方案持开放态度。如果你使用的是Java 8,你可以这样做:

Interface MyHandler {
  <T> T handle(Connection c);
}

class MyHelperClass {
  public <T> T withConnection(MyHandler handler) {
    try {
      Connection connection = mDataSource.getConnection();
      return handler.handle(connection);
    } catch (...) {
      ...
    } finally {
      ...
    }
  }
}

用法:

Result r = myHelperObject.withConnection(con -> {
  ResultSet results = connection.createStatement().executeQuery(query)
  return new Result(..)
});

这样您就可以使用lambda表达式,因此您不需要为处理程序接口实现各种新类。