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

Resource name="jdbc/TestDB" auth="Container"
               type="javax.sql.DataSource"
               removeAbandoned="true"
               removeAbandonedTimeout="30"
               maxActive="80"
               maxIdle="30"
               maxWait="10000"
               username="user"
               password=""
               driverClassName="org.postgresql.Driver"
               url = "jdbc:postgresql://localhost:5432/mydb"
               useUnicode="true"
               characterEncoding="utf-8"
               characterSetResults="utf8"
               validationQuery="/* ping */ SELECT 1"

It seems to be working, but now what I want to do is reuse the same PreparedStatement, so it won't be parsed every time a client makes a request. So, I made the PreparedStatement static for all client connections and when I create it, i invoke statement.setPoolable(true), which, from what I understand, is redundant (a PreparedStatement is already poolable). I hoped that this way, the PreparedStatement won't be tied to a single connection. Still, I get the error:

java.sql.SQLException: org.apache.tomcat.dbcp.dbcp.DelegatingPreparedStatement with address * is closed.

The weird thing is, if i call statement.isClosed() before i make any set, it returns false. Then, I set something and it throws that exception.

The code is:

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,但是随后异常却表明它已关闭。也许这不是重用prepareStatement的方法,但是我该怎么做呢?我读到,如果我在同一查询上调用conn.prepareStatement,则jdbc将从缓存中返回PreparedStatement(不会再次对其进行解析),但是我不确定它是否为真。

最佳答案

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

关于java - PreparedStatement和Axis2,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12949143/

10-12 03:51