首页 > 解决方案 > 如何在 sql 连接池中重置会话?

问题描述

我有一个使用javax.sql.DataSourcePostgreSQL JDBC 的连接池。这个过程很简单,我从连接池中取出一个虚拟连接,处理它,然后关闭虚拟连接(释放连接到连接池)。一切正常。

但是当我第二次获得相同的虚拟连接时,会话具有与上次执行相同的数据。主要是在上一次执行中创建的临时表。每次执行后如何重置会话?或者,如果不存在查询语法,您能否建议任何解决问题的方法,而不使用创建临时表。

示例代码

   import java.sql.Connection;
   import javax.naming.Context;
   import javax.naming.InitialContext;
   import javax.naming.NamingException;
   import javax.sql.DataSource;
    
    public class Base {
    
 
      public  Connection getConnection() {
        Context ctx = (Context) new InitialContext().lookup("java:/comp/env");
         DataSource ds = (DataSource) ctx.lookup("database");
        Connection con = ds.getConnection();
        return con;
      }

       public Connection closeConnection( Connection con){
         if (con != null || !con.isClosed()) {
                con.close();
            }
   

    }

上下文.xml =>

   <Resource 
          accessToUnderlyingConnectionAllowed="true" 
        auth="Container" 
        closeMethod="close" 
        driverClassName="org.postgresql.Driver" 
        maxTotal="50"
        maxWaitMillis="60000" 
        removeAbandonedOnBorrow="true"
        maxIdle="20" 
        name="Database" 
        password="p*******" 
        type="javax.sql.DataSource" 
        url="jdbc:postgresql://dbUrl/dbName" 
        username="dbUser" 
        validationQuery="select version();"
       validationQueryTimeout="60"
    />

// 用例

con = getconnection()
CallableStatement st = con.prepareCall("{ doSomething()}");
st.execute()
//processing
st.close()
con.close()

在 doSomething() plpgsql 函数中,我创建了一个临时表(名称为 t_table)、数据处理和一个数组输出。当我从 java 中反复调用它时,第一次执行是成功的。但是从第二条执行消息中说 t_table 已经存在被抛出。我以为在使用连接池时,池中的连接是独立于会话的 IE。池中的每个新连接都会有一个新会话。PostgreSQL 解决方案是删除那个特定的临时表。但是从tomcat方面没有其他解决方案吗?

标签: javasqlpostgresqljdbcconnection-pooling

解决方案


discard temporary命令可用于清理会话。您可以将其配置为在连接返回池时运行的验证查询。

使用 Tomcat JDBC 池,这将是这样的:

validationQuery="discard temporary"
testWhileIdle="false"
testOnBorrow="false"
testOnReturn="true"

如果您想进一步清理会话,可以考虑discard all改用,但这需要启用自动提交,不确定这是否适合您。

如果不允许这样的语句,您可以将其包装到一个函数中:

create function session_cleanup()
  returns boolean
as
$$
  discard temporary;
  select true;
$$
language sql;
validationQuery="select session_cleanup()"
testWhileIdle="false"
testOnBorrow="false"
testOnReturn="true"

推荐阅读