简体   繁体   English

Java JDBC将ResultSet存储在ArrayList中

[英]Java JDBC storing ResultSet in ArrayList

I am trying to work myself into using SQLite databases in Java. 我正在尝试自己在Java中使用SQLite数据库。

(I am also using the sqlite-jdbc-3.20.0 library , but I think this problem isn't influenced by that.) (我也在使用sqlite-jdbc-3.20.0库 ,但我认为这个问题不受此影响。)

I have created some functions I want to use later on to simplify my workflow. 我创建了一些函数,以后将使用它们简化我的工作流程。 For that I created the class DBInterface.java , from which I created an object in my Main.java class. 为此,我创建了类DBInterface.java ,从它在Main.java类中创建了一个对象。

Simplified content of DBInterface.java : DBInterface.java的简化内容:

/**
 * Executes a sql String and returns it's results as ResultSet[].
 *
 * @param sql as String holidng the SQL statement to execute
 * @return ResultSet[] containing the results of the query, or empty ResultSet[] if no results
 */
public ArrayList<ResultSet> excecute(String sql)
{
    if(!isConnected()) return null;
    try
    {
        return getResultSets(statement.execute(sql));
    }
    catch (SQLException e)
    {
        Main.log(tag, "An SQLException has occured for statement '"+sql+"':");
        Main.log(tag, e);
    }
    return null;
}

/**
 * Returns an array containing all resultSets of the last executed statement.
 *
 * @param isResultSet as boolean defining if the statement resulted in an result set
 * @return
 */
private ArrayList<ResultSet> getResultSets(boolean isResultSet)
{
    ArrayList<ResultSet> results = new ArrayList<>();

    try
    {
        int count = 0;
        while(true) {
            if(isResultSet)
            {
                ResultSet set = statement.getResultSet();
                results.add(set);
                /*
                while(set.next())
                {
                    //Here the information can still be retrieved
                    Main.log(tag, ""+set.getString("name")+", row:"+set.getRow());
                }
                */

            }
            else
            {
                if(statement.getUpdateCount() == -1)
                {
                    break;
                }

                Main.log(tag, "Result '"+count+"' is just a count: '"+statement.getUpdateCount()+"'");
            }

            count ++;
            isResultSet = statement.getMoreResults();
        }
    }
    catch(SQLException e)
    {
        Main.log(tag, "An SQLException has occured while processing a request:");
        Main.log(tag, e);
    }

    return results;
}

Simplified content of Main.java : Main.java的简化内容:

public static void main(String[] args)
{
    [...]

    dbInterface.excecute("DROP TABLE IF EXISTS Users");
    dbInterface.excecute("CREATE TABLE IF NOT EXISTS Users (id INTEGER, name STRING(20));");
    dbInterface.excecute("INSERT INTO Users (id, name) VALUES (1, \"Hans\");");
    dbInterface.excecute("INSERT INTO Users (id, name) VALUES (2, \"Peter\");");

    ArrayList<ResultSet> results = dbInterface.excecute("SELECT * FROM Users;");

    log(tag, ""+results.size());
    for(int i = 0; i < results.size(); i++)
    {
        ResultSet set = results.get(i);
        try
        {
            ///*
            while(set.next())
            {
                //TODO Here the information can no longer be retrieved... :(
                Main.log(tag, ""+set.getString("name")+", row:"+set.getRow());
            }
            //*/
        }
        catch (Exception e)
        {
            Main.log(tag, e);
        }
    }
}

Since from how I understand it is possible in some cases that an SQL query creates multiple ResultSet's, I've though that I will simply add all ResultSet objects to an ArrayList, so I can see when I'm processing the results somewhere else how many ResultSet's exist. 根据我的理解,在某些情况下,SQL查询可能会创建多个ResultSet,因此我只是将所有ResultSet对象简单地添加到ArrayList中,这样我就可以知道何时在其他地方处理结果了。 ResultSet存在。 Stranegly though, this doesn't work. 不过,这毫无用处。 By uncommenting the block in getResultSets() in DBInterface.java I can confirm that the result set does contain the information. 通过取消注释DBInterface.javagetResultSets()中的块,我可以确认结果集确实包含该信息。

However, doing the same thing in Main.java from the ArrayList, for some reason I can no longer access the information. 但是,由于某些原因,我无法从ArrayList在Main.java中执行相同的操作。 I have tested to change the functions to instead return the ResultSet object directly, which did work, however it does not fulfill my goal, since I want to return all possible ResultSet objetcs, not just one. 我已经测试过更改功能,而是直接返回ResultSet对象,该方法确实起作用,但是它不能实现我的目标,因为我想返回所有可能的ResultSet objetcs,而不仅仅是一个。

You can write a method to convert ResultSet to list, map or class and store the results of ResultSet in your object 您可以编写一种将ResultSet转换为列表,映射或类并将ResultSet的结果存储在对象中的方法

Something like this 像这样

public List resultSetToArrayList(ResultSet rs) throws SQLException {
    ResultSetMetaData md = rs.getMetaData();
    int columns = md.getColumnCount();
    List<Map<String, Object>> list = new ArrayList<>();
    while (rs.next()) {
        Map<String, Object> row = new HashMap<>(columns);
        for (int i = 1; i <= columns; ++i) {
            row.put(md.getColumnName(i), rs.getObject(i));
        }
        list.add(row);
    }

    return list;
}

Remember to close ResultSet, Statement and Connection when you don't use it 切记在不使用时关闭ResultSet,Statement和Connection

Closing ResultSet explicitly gives chance to garbage collector to recollect memory as early as possible because ResultSet object may occupy lot of memory depending on query. 关闭ResultSet显式地使垃圾回收器有机会尽早重新收集内存,因为ResultSet对象可能会占用大量内存,具体取决于查询。

Granted, this is much simpler using Spring, but it's good to know how to use plain old JDBC. 当然,使用Spring会容易得多,但是最好知道如何使用普通的旧JDBC。

Rather than returning a List object, create a Java class to hold the result objects and return those in your list. 创建一个Java类来保存结果对象并返回列表中的对象,而不是返回List对象。

You can do this in a method that is specifically designed to return these objects. 您可以使用专门用于返回这些对象的方法来执行此操作。

For example, if you created a User class, you could do something like this: 例如,如果创建了User类,则可以执行以下操作:

private static String SQL = "SELECT * FROM Users";
...

private List<User> getUsers()
{
    List<User> results = new ArrayList<>();

    try
    {
        PreparedStatement statement = connection.prepareStatement(SQL);
        ResultSet rs = statement.executeQuery(SQL);
        while(rs.next()) {
          User aUser = new User();
           aUser.setUserid(rs.getString("USER_ID"));
           aUser.setUserName(rs.getString("USERNAME"));
           ...
         results.add(aUser);
        }
    }
    catch(SQLException e) {
     // log any exceptions ...
    }
    finally() {
     // always close your JDBC resources - google it
     // example
     try{
        if (statement != null) {
           statement.close();
           statement=null;
        }
      }
      catch(SQLException e) {
        // couldn't close statement
      }
      ...
    }

    return results;
}

If you are not using a JDBC DataSource , then you have to manage your DB connections yourself - which can be tedious and is (was) a common source of application errors. 如果您没有使用JDBC DataSource ,那么您必须自己管理数据库连接-这可能很繁琐,并且是应用程序错误的常见来源。 Almost all modern Java applications use DataSource implementations (and pooling DataSources are very common) rather than simple JDBC connections. 几乎所有现代Java应用程序都使用DataSource实现(并且池化DataSource非常普遍)而不是简单的JDBC连接。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM