3

这是这种情况

jOOQ中,非常需要对 JDBC 进行抽象。我希望 jOOQ 客户端代码不知道这样一个事实,即从简单的 ResultSet 检索一些数据,从 SQLInput(对于 UDT)或从 CallableStatements(对于存储过程/函数)检索一些数据。因此,我想对这些 JDBC 类型添加抽象:

java.sql.ResultSet
java.sql.CallableStatement
java.sql.SQLInput
java.sql.SQLOutput

现在它们的工作方式几乎相同。他们通常getset. java.sql.Types例如,他们提供了类似的方法

BigDecimal getBigDecimal(int index);
int getInt(int index);

他们都有类似的方法

boolean wasNull();

问题

不幸的是,这些 JDBC 接口并没有扩展单个通用接口,这让那些想要在这里编写像这个片段这样的通用 JDBC 代码的人的生活更轻松(只是一个支持我的问题的例子):

// As JDBC has no support for BigInteger types directly,
// read a BigDecimal and transform it to a BigInteger
BigDecimal result = null;

if (source instanceof ResultSet) {
    result = ((ResultSet) source).getBigDecimal(index);
}
else if (source instanceof CallableStatement) {
    result = ((CallableStatement) source).getBigDecimal(index);
}
else if (source instanceof SQLInput) {
    result = ((SQLInput) source).readBigDecimal();
}

return result == null ? null : result.toBigInteger();

上面的代码需要为它们三个都编写,ResultSet, CallableStatement, SQLInput。还有很多类似的例子

我的问题是

  • 有谁知道优雅地解决这个问题的 JDBC 扩展库?
  • 还是我应该自己为所有这些类型编写一个简单的包装类(或适配器)?
  • 还是您会接受这个事实并继续复制内部库代码?

您更喜欢哪种解决方案,为什么?感谢您的任何反馈

4

3 回答 3

3
  • 有谁知道优雅地解决这个问题的 JDBC 扩展库?

不,必须有人发明它。


  • 还是我应该自己为所有这些类型编写一个简单的包装类(或适配器)?

我肯定会去的。从一个通用的包装器接口开始。

public interface DataProvider {
    public BigInteger getBigInteger(int columnIndex);
    // ...
}

让所有具体的包装器实现它。

public class ResultSetDataProvider implements DataProvider {
    private ResultSet resultSet;

    public ResultSetDataProvider(ResultSet resultSet) {
        this.resultSet = resultSet;
    }

    public BigInteger getBigInteger(int columnIndex) {
        BigDecimal bigDecimal = resultSet.getBigDecimal(columnIndex);
        return bigDecimal != null ? bigDecimal.toBigInteger() : null;
    }

    // ...
}

并改用它。

try {
    // Acquire ResultSet.
    DataProvider dataProvider = new ResultSetDataProvider(resultSet);
    // Process DataProvider.
} finally {
    // Close ResultSet.
}

  • 还是您会接受这个事实并继续复制内部库代码?

不,我不会。保持你的代码DRY

于 2010-12-19T14:50:00.233 回答
1

就个人而言,我不会使用这样的东西。我没有看到您通过这种抽象使我的生活变得更轻松。

我认为 SQL 抽象没有理由从持久层中泄漏出来。我进行调用、映射到对象并关闭 SQL 抽象。你听起来像你希望他们留下来,这是一个坏主意。

我认为 Spring 的人们已经尽可能简单地使用 JDBC。我可能是错的,但我认为没有理由走你建议的道路。

如果我查看 SQLInput 的 javadocs,我会看到:

此接口仅用于自定义映射,由驱动程序在后台使用,程序员从不直接调用 SQLInput 方法。

我不确定您为什么认为有必要公开此接口。

至于 ResultSet 和 CallableStatement(或任何 Statement,就此而言),它们最终可以返回一个或多个 ResultSet 以返回查询结果。我宁愿看到围绕它的抽象。我相信你暴露其他人是在搅浑水。我不会推荐它。

也许它从未做过的事实是另一个不应该做的迹象。但是欢迎您这样做,看看市场是否将您选为赢家。

于 2010-12-19T16:39:36.497 回答
0
  1. 不确定 JDBC 的扩展。
  2. 根据您的设计的其余部分,包装类或访问者模式可能有用。
  3. 扩展每一个并让它们实现具有相同方法签名的相同接口以获取您想要的数据怎么样?
于 2010-12-19T14:17:59.907 回答