如果我使用一个语句选择属性然后使用多个 sql 查询的 1 个准备好的语句,我是不是需要使用连接池

Posted

技术标签:

【中文标题】如果我使用一个语句选择属性然后使用多个 sql 查询的 1 个准备好的语句,我是不是需要使用连接池【英文标题】:Do I need to use connection pooling if I use one statement to select attributes and then 1 prepared statement with multiple sql queries如果我使用一个语句选择属性然后使用多个 sql 查询的 1 个准备好的语句,我是否需要使用连接池 【发布时间】:2012-12-17 20:16:41 【问题描述】:

我正在使用 jdbc 驱动程序查询 postgres 数据库,这将是一个相当基本的独立 Java 应用程序,用于查询本地安装/托管服务器。

我想用格式字符串记录我传递的 sql,以检查我是否只是传递问号或实际的列名,但结果 jdbc 不支持这种日志记录以确保线程安全。我构建了我准备好的陈述,使其在不同的条件下有所不同。

所以我使用语句来选择我需要的所有内容,然后使用结果集进行检索,同时根据这些结果集创建准备好的对象。在我使用两个不同的准备好的语句并且收到死锁之前,我的准备好的语句可以在两个 sql 更新之间变化。因此我需要连接池吗?我宁愿不要,因为这个独立的应用程序不应该占用太多时间,因为我已经投入了太多时间来尝试调试和解决服务器问题。我的代码如下:

    public static void handleEntries(Long level,
        PreparedStatement w_ustmt, String base_url, String name5,
        String name4, String name3, String name2, String name1, String name0) throws SQLException 
    String wiki_url_entry = "";
    try 
        if (level.equals((long) 5)) 
            // wiki_url = wiki_url + name5;
            w_ustmt.setString(1, base_url + name5);
            w_ustmt.addBatch();
            System.out.println(w_ustmt.toString());
         else if (level.equals((long) 4)) 
            // wiki_url = wiki_url + name4;
            w_ustmt.setString(1, base_url + name4);
            w_ustmt.addBatch();
            System.out.println(w_ustmt.toString());
         else if (level.equals((long) 3)) 
            //for some reason all the results are coming from this loop
            // wiki_url = wiki_url + name3;
            w_ustmt.setString(1, base_url + name3);
            w_ustmt.addBatch();
            System.out.println(w_ustmt.toString());
         else if (level.equals((long) 2)) 
            // wiki_url = wiki_url + name2;
            w_ustmt.setString(1, base_url + name2);
            w_ustmt.addBatch();
            System.out.println(w_ustmt.toString());
         else if (level.equals((long) 1)) 
            // wiki_url = wiki_url + name1;
            w_ustmt.setString(1, base_url + name1);
            w_ustmt.addBatch();
            System.out.println(w_ustmt.toString());
         else 
            // wiki_url = wiki_url + name0;
            w_ustmt.setString(1, base_url + name0);
            w_ustmt.addBatch();
            System.out.println(w_ustmt.toString());
        

     catch (SQLException ex) 
        Logger lgr = Logger.getLogger(Shapefile_Repair.class.getName());
        lgr.log(Level.SEVERE, ex.getMessage());
        while (ex != null)
            System.out.println(ex.getNextException());
        
        //System.out.println("SQLState: A " + ex.getSQLState());
        //System.out.println("VendorError A: " + ex.getErrorCode());
    


/* this function will handle all the urls which have same entries */ 
public static void handleDups(String wiki_url,
        String base_url, String name5, String name4,
        String name3, String name2, String name1, String name0,
        PreparedStatement w_ustmt) 
    String wiki_url_entry = "";
    try 
        if (wiki_url.toString().equals(base_url + name5)) 
            wiki_url_entry = wiki_url + "(" + name0 + "." + name1  + "." + name2 + "." + name3 + "." +
            name4 + ")";
            // rewriting here, yet it is only printing ?, ?
            w_ustmt.setString(1, wiki_url_entry);
         else if (wiki_url.toString().equals(base_url + name4)) 
            wiki_url_entry = wiki_url + "(" + name0 + "." + name1 + "." + name2 + "." + name3 +
            ")";
            w_ustmt.setString(1, wiki_url_entry);
         else if (wiki_url.toString().equals(base_url + name3)) 
            wiki_url_entry = wiki_url + "(" + name0 + "." + name1  + "." + name2
            + ")";
            w_ustmt.setString(1, wiki_url_entry);
         else if (wiki_url.toString().equals(base_url + name2)) 
            wiki_url_entry = wiki_url + "(" + name0 + "." + name1 + ")";
            w_ustmt.setString(1, wiki_url_entry);
         else if (wiki_url.toString().equals(base_url + name1)) 
            wiki_url_entry = wiki_url + "(" + name0 + ")";
            w_ustmt.setString(1, wiki_url_entry);
        
        w_ustmt.addBatch();
        System.out.println("B");
     catch (SQLException ex) 
        Logger lgr = Logger.getLogger(Shapefile_Repair.class.getName());
        lgr.log(Level.SEVERE, ex.getMessage());
        System.out.println("SQLState: B " + ex.getSQLState());
        System.out.println("VendorError B :" + ex.getErrorCode());
    


/* main method */
@SuppressWarnings("resource")
public static void main(String[] args) throws InstantiationException,
        IllegalAccessException, SQLException 
    // TODO Auto-generated method stub
    Connection conn = null;
    // use the log4jdbc4 wrapper for the connection object
    // conn = new net.sf.log4jdbc.ConnectionSpy(conn);
    Statement stmt = null;
    ResultSet rs = null;
    try 
        // conn = makeConnection(args[0], args[1], args[2], args[3], "");
        String host = args[0];
        String port = args[1];
        String database = args[2];
        String user = args[3];
        String password = args[4];
        String sql_query = "SELECT \"NAME_0\", \"NAME_1\", \"NAME_2\", \"NAME_3\", \"NAME_4\", \"NAME_5\", \"WIKI_URL\", \"LEVEL_DEPT\" FROM"
                + " AdminBoundaries WHERE \"WIKI_URL\" IN(SELECT \"WIKI_URL\" FROM AdminBoundaries"
                + " GROUP By \"WIKI_URL\" HAVING (count (\"WIKI_URL\") > 1)) ORDER BY \"WIKI_URL\";";
        Class.forName("org.postgresql.Driver").newInstance();

        String url = "jdbc:postgresql://" + host + ":" + port + "/"
                + database;
        conn = DriverManager.getConnection(url, user, password);
        // if(conn.equals(null))
        // System.err.println("Connection complete");
        // 
        DatabaseMetaData meta;          
        try 
            if (conn.isClosed()) 
                System.out.println("closed");
            
            System.out.println(conn.getWarnings());
            meta = conn.getMetaData();
            boolean updateable = meta.supportsResultSetConcurrency(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);
            /*if(updateable) System.out.println("yes");
            System.out.println("Does database support batch processes?:"
                    + meta.supportsBatchUpdates());
            ResultSet columns = meta.getColumns(null, null,
                    "adminboundaries", "%");
            while (columns.next()) 
                System.out.println(columns.getString(4));
            */
            // after checking the table, adminboundaries was in fact
            // evident, so the issue now is changing the sql queries to
            // lower case
            /*
             * ResultSet tables = meta.getTables(null, null, "%", null);
             * while (tables.next())
             * System.out.println(tables.getString(3)); 
             */
         finally 
            System.out.println(conn.getTransactionIsolation());
            System.out.println(sql_query);
            stmt = conn.createStatement(ResultSet.CLOSE_CURSORS_AT_COMMIT,
                    ResultSet.CONCUR_UPDATABLE,
                    ResultSet.TYPE_SCROLL_INSENSITIVE);
            System.out.println(stmt.getFetchSize());
            stmt.setMaxRows(900);
            System.out.println(conn.getTypeMap());
            // stmt.addBatch(sql_query);
            rs = stmt.executeQuery(sql_query);
            // batch_counter is for the row count of the SQL statements
            // executed
            // int batch_counter = pstmt.executeUpdate();
            // update dup_sql's arguments being set as it will vary
            // String wiki_sql =
            // "UPDATE AdminBoundaries SET \"WIKI_URL\" = ?";
            PreparedStatement w_ustmt = conn
                    .prepareStatement("UPDATE AdminBoundaries SET WIKI_URL = ?");
            // int counter = 0;
            // for (counter = 0; counter < 1000; counter++) 
            conn.setAutoCommit(false);
            // stmt.addBatch(sql_query);
            // stmt.setQueryTimeout(30);
            System.out.println(rs.getFetchSize());
            SQLWarning resultsetWarning = rs.getWarnings();
            System.out.println(resultsetWarning);
            // consider changing tables/columns to lower case as sources say
            // to do
            while (rs.next()) 
                String base_url = "http://127.0.0.1/mediawiki/index.php/";
                String name0 = rs.getString("NAME_0");
                String name1 = rs.getString("NAME_1");
                String name2 = rs.getString("NAME_2");
                String name3 = rs.getString("NAME_3");
                String name4 = rs.getString("NAME_4");
                String name5 = rs.getString("NAME_5");
                String wiki_url = rs.getString("WIKI_URL");
                Long level = rs.getLong("LEVEL_DEPT");
                /*for (int i = 1; i < rs.getMetaData().getColumnCount() + 1; i++) 
                    while (rs.next()) 
                        System.out.println(i + " " + rs.getMetaData().getColumnName(i));
                    
                */
                // use 127.0.0.1, not ncsirad-pc b/c wiki_urls are coming
                // back 127.0.0.1

                // TO DO: rethink this if statement to include in function
                // and execute
                // both functions without conditionals above. So it will run
                // through first
                // then run through second.

                if (wiki_url.toString().equals(base_url)) 
                    // Savepoint savepoint1 =
                    // conn.setSavepoint("wiki_entry");
                    // w_ustmt.setQueryTimeout(30);
                    // System.out.println("Getting into duplicates loop");
                    handleEntries(level, w_ustmt, base_url, name5, name4,
                            name3, name2, name1, name0);
                    // add to batch
                    // w_ustmt.addBatch(wiki_sql);
                    // int counts2[] = w_ustmt.executeBatch();
                    // make sure to try the below
                    // w_ustmt.executeUpdate();
                    // conn.rollback(savepoint1);
                 else 
                    handleDups(wiki_url, base_url, name5, name4, name3,
                            name2, name1, name0, w_ustmt);
                    w_ustmt.setQueryTimeout(30);
                    // dup_pstmt.addBatch(dup_sql);
                    // int count3[] = dup_pstmt.executeBatch();
                

            
            // may not need executeUpdate
            int counts[] = w_ustmt.executeBatch();
            System.out.println("here is " + counts);
            conn.commit();
            conn.setAutoCommit(true);
            // counter = 0;
            // 
        
        System.out.println("finished queries");
        rs.close();

     catch (ClassNotFoundException e) 
        e.printStackTrace();
        // System.exit(1);
     catch (SQLException ex) 
        Logger lgr = Logger.getLogger(Shapefile_Repair.class.getName());
        lgr.log(Level.SEVERE, ex.getMessage());
        System.out.println("SQLState C: " + ex.getSQLState() + " " + lgr);
        System.out.println("VendorError C: " + ex.getErrorCode());
        if (ex != null) 
            System.out.println(ex.getNextException());
        
     finally 
        try 
            if (rs != null) 
                rs.close();
            
            if (stmt != null) 
                stmt.close();
            
            if (conn != null) 
                conn.close();
            
         catch (SQLException e) 
        
    
     conn.close();

The errors/SQL returned from printing was long with the first couple print statements indicating the # of allowable rows so I shortened it: 
UPDATE adminboundaries SET WIKI_URL = 'http://127.0.0.1/mediawiki/index.php/null'
UPDATE adminboundaries SET WIKI_URL = 'http://127.0.0.1/mediawiki/index.php/null'
UPDATE adminboundaries SET WIKI_URL = 'http://127.0.0.1/mediawiki/index.php/null'
UPDATE adminboundaries SET WIKI_URL = 'http://127.0.0.1/mediawiki/index.php/null'
UPDATE adminboundaries SET WIKI_URL = 'http://127.0.0.1/mediawiki/index.php/null'
UPDATE adminboundaries SET WIKI_URL = 'http://127.0.0.1/mediawiki/index.php/?uilly (France.Picardie.Aisne.Laon.Craonne)'
UPDATE adminboundaries SET WIKI_URL = 'http://127.0.0.1/mediawiki/index.php/?uilly (France.Champagne-Ardenne.Marne.Épernay.Dormans)'
UPDATE adminboundaries SET WIKI_URL = 'http://127.0.0.1/mediawiki/index.php/01 (Vietnam.Ðông Nam B?.H? Chí Minh city.Qu?n 3)'
UPDATE adminboundaries SET WIKI_URL = 'http://127.0.0.1/mediawiki/index.php/01 (Vietnam.Ðông Nam B?.H? Chí Minh city.Qu?n 10)'
UPDATE adminboundaries SET WIKI_URL = 'http://127.0.0.1/mediawiki/index.php/01 (Vietnam.Ðông Nam B?.H? Chí Minh city.Qu?n 6)'
UPDATE adminboundaries SET WIKI_URL = 'http://127.0.0.1/mediawiki/index.php/01 (Vietnam.Ðông Nam B?.H? Chí Minh city.Phú Nhu?n)'
UPDATE adminboundaries SET WIKI_URL = 'http://127.0.0.1/mediawiki/index.php/01 (Vietnam.Ðông Nam B?.H? Chí Minh city.Qu?n 4)'
Dec 18, 2012 4:31:05 PM Shapefile_Repair main 
SEVERE: Batch entry 0 UPDATE    adminboundaries SET        

WIKI_URL='http://127.0.0.1/mediawiki/index.php/null' was aborted.  
Call getNextException to see the cause.
SQLState C: 42703 java.util.logging.Logger@37504d
VendorError C: 0
org.postgresql.util.PSQLException: ERROR: column "wiki_url" of relation   

"adminboundaries" does not exist
Position: 28

【问题讨论】:

使用连接池不会修复代码中的错误。看来您无论如何都在使用相同的连接来做所有事情。但这很难说,因为您没有提供任何代码,只是对您遇到的错误进行了模糊的描述。 这是一个内部项目,但我会更改一些名称分配,并且我已经调试了一段时间,所以我不妨发布它。在任何情况下,我都会根据 LEVEL_DEPT 列的值填充一个列,作为对另一列 NAME_# 值的引用。然后我会处理重复的 wiki_url 条目。 是的,您确实需要显示运行的实际 SQL,以及任何错误消息的准确文本,以及 您的 PostgreSQL 版本。我看不出连接池与您在代码中显示的内容有何关系,但我也无法想象您如何在仅使用单个连接时设法陷入死锁。代码看起来过于复杂,我怀疑这一切都可以通过几个更智能的 UPDATE 语句或 CTE 来完成,但是如果没有看到您运行的最终 SQL,就很难说。 好吧,实际运行的 SQL 正是我在代码中放入的内容。这就是我设置preparedstatements的方式。我的 PostgreSQL 版本是 9.2,这不能通过简单的更新语句来解决,因为您不能对表列名执行动态比较。所以不,它不能通过“几个更智能的 UPDATE 语句”来完成,而且我有一个很大的数据集,所以我需要使用准备好的语句和批量更新。 我也从来没有说过我现在有死锁,我说我以前有过。 【参考方案1】:

异常cleary说wiki_url在表adminboundaries中不存在。

org.postgresql.util.PSQLException: ERROR: column "wiki_url" of relation "adminboundaries" does not exist

我认为它来自update 查询正在执行

conn.prepareStatement("UPDATE adminboundaries SET WIKI_URL = ?");

因为 postgresql 区分大小写 将您的查询更改为

conn.prepareStatement("UPDATE AdminBoundaries SET WIKI_URL = ?"); 假设您的表名是 AdminBoundaries

【讨论】:

我忘了说我实际上已经尝试过了,我已经尝试过改变大小写。我已经相应地更新了我的代码。该错误实际上与比较列中长值的第一个循环有关,但我不确定如何解决。

以上是关于如果我使用一个语句选择属性然后使用多个 sql 查询的 1 个准备好的语句,我是不是需要使用连接池的主要内容,如果未能解决你的问题,请参考以下文章

数据库用sql语句查询是有数据的,然后前台就是查不到

一个SQL查询不会写

SQL多个条件查询语句

Asp.net(C#) 获取 执行sql server 语句/存储过程后的 多个返回值?

使用一条语句对多个属性和表进行 Oracle SQL 特权授权

仅使用在 TOAD 中执行来运行多个 sql 语句