0

我将 Axis2 与 Apache Tomcat 一起使用。我需要 web 服务的客户端能够查询数据库,所以我在互联网上发现,通过将以下资源添加到 Tomcat 的上下文中,它将自动创建一个连接池:

资源名称="jdbc/TestDB" auth="容器"
               类型="javax.sql.DataSource"
               removeAbandoned="true"
               removeAbandonedTimeout="30"
               最大活动=“80”   
               最大空闲=“30”
               maxWait="10000"
               用户名="用户"
               密码=""
               driverClassName="org.postgresql.Driver"
               url = "jdbc:postgresql://localhost:5432/mydb"
               使用Unicode="真"
               字符编码="utf-8"
               characterSetResults="utf8"
               验证查询="/* ping */ SELECT 1"

它似乎正在工作,但现在我想做的是重用相同的 PreparedStatement,因此每次客户端发出请求时都不会对其进行解析。因此,我为所有客户端连接设置了 PreparedStatement 静态,当我创建它时,我调用 statement.setPoolable(true),据我了解,这是多余的(PreparedStatement 已经是可池化的)。我希望这样,PreparedStatement 不会被绑定到单个连接。不过,我得到了错误:

java.sql.SQLException: org.apache.tomcat.dbcp.dbcp.DelegatingPreparedStatement 地址 * 已关闭。

奇怪的是,如果我在进行任何设置之前调用 statement.isClosed(),它会返回 false。然后,我设置了一些东西,它抛出了那个异常。

代码是:

try {
        Connection conn;

        Context envCtx = (Context) new InitialContext().lookup("java:comp/env");

        DataSource ds = (DataSource) envCtx.lookup("jdbc/TestDB");
        conn = ds.getConnection();    

        if(statement == null){
        //statement is static, so it won't be null at the second call                
            statement = conn.prepareStatement(query);
            statement.setPoolable(true);        
        }
        if(statement.isClosed()){
            statement = conn.prepareStatement(query);
            //it never gets here
        }
        else{
            Logger.getLogger(HelloAxisWorld.class.getName()).log(Level.INFO, "STATEMENT IS NOT CLOSED", new Object());  
            //it always gets here
        }

        statement.setString(1, par1); //here, the second call throws an exception
        ResultSet rs = statement.executeQuery();
        while (rs.next()) {
            cur_value = rs.getInt("cur_value");
        }         
        rs.close();

        conn.close();

    }catch (Exception ex) {            
        Logger.getLogger(HelloAxisWorld.class.getName()).log(Level.SEVERE, null, ex);          
    }

我不明白为什么 statement.isClosed 返回 false,但是异常说它已关闭。也许这不是重用preparedStatement的方法,但是我该怎么做呢?我读到,如果我在同一个查询上调用 conn.prepareStatement,jdbc 将从缓存中返回 PreparedStatement(它不会再次被解析),但我不确定它是否属实。

4

1 回答 1

0

有一个名为 c3p0 的项目专门用于处理您遇到的一种情况。该网站在这里https://sourceforge.net/projects/c3p0/和这里http://www.mchange.com/projects/c3p0/它处理数据源 JNDI 绑定、连接池和语句池。还有一个关于 stackoverflow 的参考,关于某人使用这个库和 servlets what-is-a-good-strategy-for-caching-prepared-statements-in-tomcat

于 2012-10-18T07:31:17.137 回答