没有java.sql.ResultSet,CallableStatement,SQLInput的公共接口

时间:2010-12-19 12:08:10

标签: java jdbc jooq

这是情况

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

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

现在他们的工作方式几乎相同。对于get中的每种数据类型,它们通常都有setjava.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();

上述代码需要为所有这三个代码编写,ResultSetCallableStatementSQLInput。还有很多类似的例子

我的问题是

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

您更喜欢哪种解决方案?为什么?感谢您提供反馈

3 个答案:

答案 0 :(得分: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

答案 1 :(得分:1)

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

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

我认为Spring的人们已经尽可能地使用JDBC了。我可能是错的,但我没有理由沿着你建议的路走下去。

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

  

此界面仅用于自定义   映射,由后面的驱动程序使用   场景,程序员永远不会   直接调用SQLInput方法。

我不确定为什么你认为有必要公开这个界面。

对于ResultSet和CallableStatement(或任何Statement,就此而言),那些最终可以返回一个或多个ResultSet来返回查询结果。我宁愿看到围绕它的抽象。我相信你通过揭露其他人来淹没水域。我不推荐它。

或许它从未被完成的事实是另一个迹象表明它不应该被完成。但欢迎你这样做,看看市场是否会为你赢得胜利。

答案 2 :(得分:0)

  1. 不确定JDBC的扩展名。
  2. 根据设计的其余部分,包装类或访问者模式可能很有用。
  3. 如何扩展每一个并使它们实现具有相同方法签名的相同接口以获取所需数据。