如果我使用一个语句选择属性然后使用多个 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 个准备好的语句,我是不是需要使用连接池的主要内容,如果未能解决你的问题,请参考以下文章
Asp.net(C#) 获取 执行sql server 语句/存储过程后的 多个返回值?