如何重置 sql 连接池中的会话?

How to reset a session in a sql connection pool?

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

但是当我第二次获得相同的虚拟连接时,会话具有与上一次执行相同的数据。主要是上次执行时创建的temp tables。每次执行后如何重置会话?或者您可以建议任何变通方法来解决问题而不使用 creating temp table if not exists query syntax.

示例代码

   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();
            }
   

    }

context.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 函数中,我有临时 table 创建(名称 t_table)、数据处理和数组输出。当我从 java 中反复调用它时,第一次执行是成功的。但是从第二个执行消息说 t_table 已经存在被抛出。我认为在使用连接池时,池中的连接是会话独立的 IE。来自池的每个新连接都会有一个新会话。 PostgreSQL 解决方案是删除特定的临时文件 table 。但是 tomcat 方面没有其他解决方案 ?

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"