PreparedStatement和Axis2

时间:2012-10-18 07:18:31

标签: java tomcat jdbc prepared-statement axis2

我正在将Axis2与Apache Tomcat一起使用。我需要Web服务的客户端才能查询数据库,所以我在互联网上发现,通过将以下资源添加到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" 

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

java.sql.SQLException:org.apache.tomcat.dbcp.dbcp.DelegatingPreparedStatement with address *已关闭。

奇怪的是,如果我在创建任何集合之前调用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);          
    }

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(它不会被再次解析),但我不确定它是否属实。

1 个答案:

答案 0 :(得分:0)

有一个名为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的参考