Java - 重复 sql 任务的设计模式
Java - Design Pattern for repeating sql tasks
我有不同的方法,从数据库中查询不同的数据,但是每个方法的主要结构都是一样的。为了减少代码,我想缩小它,但我不知道该怎么做。我尝试过接口,但无法从内部 class 调用 return 语句。 (它应该是类型安全的!)
结构:
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);
}
}
但是如果我在我的一个数据方法中调用这个私有方法,我不能 return 来自 handleResultSet()
方法的对象,因为 return 语句会影响这个接口方法.是否有一个选项可以告诉 execiteQuery()
方法处理程序具有哪种 return 类型?
注意:它必须是类型安全的,如果可能的话不要转换!
您的方法不应使用原始 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。您可能会考虑使用它而不是重新发明它。
也许您愿意接受其他解决方案。如果你使用的是 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 表达式,因此您不需要为您的处理程序接口实现各种新的 类。
我有不同的方法,从数据库中查询不同的数据,但是每个方法的主要结构都是一样的。为了减少代码,我想缩小它,但我不知道该怎么做。我尝试过接口,但无法从内部 class 调用 return 语句。 (它应该是类型安全的!)
结构:
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);
}
}
但是如果我在我的一个数据方法中调用这个私有方法,我不能 return 来自 handleResultSet()
方法的对象,因为 return 语句会影响这个接口方法.是否有一个选项可以告诉 execiteQuery()
方法处理程序具有哪种 return 类型?
注意:它必须是类型安全的,如果可能的话不要转换!
您的方法不应使用原始 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。您可能会考虑使用它而不是重新发明它。
也许您愿意接受其他解决方案。如果你使用的是 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 表达式,因此您不需要为您的处理程序接口实现各种新的 类。