首页 > 解决方案 > 复杂 API 的 Java 尝试

问题描述

我想将一些 JDBC 代码包装到我自己的和不同的类中。因此在这些类中创建资源,返回结果集。如果客户端准备好了,那么该链中所有打开的资源都应该关闭。

我写了以下内容,但我不确定这是否足够正确和最简单的方法。

我为插入数据行构建了一个 SQL 字符串。

从我的数据源(hikari 池),我得到一个数据库连接。然后我创建一个准备好的语句,我执行它并得到一个ResultSet回复​​。

这个结果集我返回给调用者。

连接和准备好的语句必须保持打开状态,直到调用者准备好返回的结果集

public DbResult insert(int cache, String shema, String table, LinkedHashMap<String, Object> data, boolean returnAutoCreate) throws SQLException
{

//building sql-string or take it from my cache
//...

    Connection connection = null;
    PreparedStatement preparedStatement = null;
    ResultSet resultSet = null;
    try
    {

        connection = ds.getConnection();
        preparedStatement = connection.prepareStatement(sqlString);

        int i = 0;
        for (Object value : data.values())
        {
            preparedStatement.setObject(i++, value);
        }

        preparedStatement.executeUpdate();
        resultSet = preparedStatement.getResultSet();

        DbResult dbResult = new DbResult(connection, preparedStatement, resultSet);

        return dbResult;


    }
    catch (Exception e)
    {
        try
        {
            if (resultSet != null) resultSet.close();
        }
        catch (Exception e2)
        {
            e.addSuppressed(e2);
        }

        try
        {
            if (preparedStatement != null) preparedStatement.close();
        }
        catch (Exception e2)
        {
            e.addSuppressed(e2);
        }

        try
        {
            if (connection != null) connection.close();
        }
        catch (Exception e2)
        {
            e.addSuppressed(e2);
        }

        throw e;

    }


}

这是我的 DbResult 类

class DbResult implements AutoCloseable
{

private final ResultSet rs;
private final PreparedStatement ps;
private final Connection conn;

public DbResult(Connection conn, PreparedStatement ps, ResultSet rs)
{
    this.conn = conn;
    this.ps = ps;
    this.rs = rs;
}

@Override
public void close() throws SQLException
{

    try (conn; ps; rs;){}

}

public ResultSet getResultSet()
{
    return rs;
}

}

这里是客户端/调用者代码

DatabaseHelper databaseHelper = new DatabaseHelper(ds, defaultShema);

    try(DbResult result = databaseHelper.insert(1001, defaultShema, "test", new LinkedHashMap<>(), true);)
    {
         //do sth with result
    }

在我的插入方法中,我添加了 try catch,因为如果那里出现问题,我必须关闭资源。

如果没有问题,我将资源添加到我的DbResult对象中,然后使用 - 方法关闭资源close()。在那里,我使用了 try-with,因为如果在该链中一个关闭失败,那么其他的仍然关闭,并且异常被正确转发。

close()在我的调用者处,我还使用了一个 try-with,它在我完成结果后在 DbResult中调用该方法。

但它有很多代码,尤其是我的插入方法中的 try-catch 构造。

我不确定是否有更简单或更好的方法来做到这一点。

我还有一个问题:

我可以缓存结果,所以我不必在DatabaseHelper课堂之外处理该资源的关闭。

存在一个CachedRowSet. 但我不确定,这有多贵。这是否也复制了元信息?

我猜正常ResultSet首先检索数据,如果我访问它们:元数据,行数据:逐行?

将数据缓存到 Hashmap 的 ArrayList 中是个好主意吗?

Arraylist -> Rows
HashMap -> 列名 -> 值

因此,如果我这样做,我可以立即关闭所有资源。
-> 我不必关心在我的 DatabaseClass 之外关闭
-> 池更快地恢复连接

但是,也许我检索了我不需要的数据(例如,元数据)。

此外,将我的数据副本构建到 ArrayList->Hashmap 构造中的成本很高。

那么你对此有什么想法?最佳做法是什么?

标签: javasqljdbctry-catchtry-with

解决方案


推荐阅读