我有以下代码:
private final ResultSet resultSet;
public returnResult() {
if(mycondition){
resultSet = return Empty;
}else
resultSet = statement.executeQuery();
}
不打分贝就返回空结果集的正确方法是什么?
答案 0 :(得分:0)
这实际上很复杂。您需要一个'dummy'空的ResultSet类,但这过去几乎是不可能的。
如果接口的作者在某些版本升级中添加了新方法,则意味着这是一个向后不兼容的更改:版本更新之前编写的该接口的所有实现现在不再可编译,因为它们没有实现新添加的方法。
通常,java 不会破坏向后兼容性。
因此,用java核心定义的接口(在java.something
包中)将永远不会增加新方法,因此您可以将其模拟掉,为其中的每个方法QED编写一个合适的虚拟实现。 / p>
不幸的是,JDBC是不具备的少数几个领域之一-想法是,一定数量的开发人员(数据库供应商)将在{中编写接口的实现。 {1}}程序包,因此,假设所有数据库开发人员都参与其中,则这些接口可以开发新方法。
他们做到了。
但是,我相信,但我找不到对此的任何引用,JDBC团队停止了这样做,而是依赖于或多或少可插入的方法,例如PreparedStatement的java.sql
。
在这种背景下,您可以选择以下方法:
.setObject(idx, value, targetSqlType)
只要ResultSet有大量方法,它将是页面和页面。不幸的是。
代理是一种机制,通过它可以编写接口的动态实现:无需为接口中的每个方法都提供一个方法,只需提供一个方法即可:它被赋予方法名称(作为字符串) )和参数(作为对象数组)。这样,您可以为需要知道实际结果的所有方法编写一个大的switch-on-strings块,例如ResultSet的public class DummyResultSet implements java.sql.ResultSet {
// an impl of every method here that returns a value
// that fits the notion that it has no rows
}
(不执行任何操作)或first()
(执行什么都没有)或close()
(返回next()
),对于其他任何流入的内容,您只需false
。
这也方便地意味着,如果ResultSet接口增加了更多的方法,则基于代理的虚拟impl可能会对这些新方法(特别是:引发SQLException)做正确的事情:
throw SQLException
好吧,总是会运行一个实际的查询,保证没有结果:
private static final InvocationHandler dummyResultSetHandler =
(proxy, method, args) -> {
switch (method.getName()) {
case "next":
case "absolute":
return false;
case "afterLast":
case "beforeFirst":
case "close":
return null;
// you need way more of these, go through the entire list
// of methods ResultSet has.
default:
throw new SQLException("No results");
};
private static final ResultSet EMPTY_SET =
java.lang.reflect.Proxy.newProxyInstance(
ResultSet.class.getClassLoader(),
new Class[] { ResultSet.class },
dummyResultSetHandler);
将在大多数数据库引擎中完成这项工作:为您保证空结果集。
但是,不幸的是,这将导致数据库引擎快速往返。
那么不幸的是你不走运。但是,您可以尝试做的是对代码进行某种程度的重构。例如,您可以返回其他内容,例如结果列表或迭代器,因为“空迭代器”和“空列表”很容易实现。
通常,JDBC API有点低,可以直接使用。当然,您可以做到这一点,但是在JDBC之上构建的抽象仍然可以为您提供SQL的所有强大功能,这些功能要好得多,并且在这里也有帮助:JDBI和JOOQ是您可能要研究的库。 >
答案 1 :(得分:0)
您可以将jOOQ的MockResultSet
用于此目的,或者从中汲取灵感。
if (mycondition) {
// Result is the jOOQ representation of the JDBC ResultSet. You might not have to
// create it with column information attached to it but your client code may expect
// a ResultSet with N columns and corresponding data types, even if there's no data
Result<?> result = DSL.using(DEFAULT).newResult(
DSL.field("COL1", SQLDataType.INTEGER),
DSL.field("COL2", SQLDataType.VARCHAR(10))
);
resultSet = new MockResultSet(result);
}
else
resultSet = statement.executeQuery();
请注意,尽管jOOQ在某些用例中具有双重许可,但在此情况下,可以完全由ASL 2.0许可的jOOQ开源版来完成。
免责声明:我为jOOQ背后的公司工作。
答案 2 :(得分:-1)
在不触及数据库的情况下无法获得空的ResultSet
。仅当execute查询不返回任何数据时,您才能获得空的ResultSet
。为了避免根据您的情况命中数据库,您可以执行以下操作:
public ResultSet returnResult() {
ResultSet resultSet = null;
if(!mycondition) {
//...
resultSet = statement.executeQuery();
}
return resultSet;
}
请注意,如果不满足您的条件,则将获得ResultSet
(空或具有一个或多个记录),并且如果满足您的条件,则函数将返回null
。