HikariCP:Postgres timestamptz列时区在5次查询后在PreparedStatement的结果集中消失

时间:2015-10-27 20:41:20

标签: java postgresql jdbc playframework-2.0 hikaricp

我在play2.4中的光滑映射无法正常工作,我将问题归结为:如果我从具有timestamp with time zone列的表中进行简单选择,则时区会从结果中消失过了一会儿。此消息末尾的示例生成以下输出: 2015-10-27 20:45:13.459+01 2015-10-27 20:45:13.459+01 2015-10-27 20:45:13.459+01 2015-10-27 20:45:13.459+01 2015-10-27 20:45:13.459+01 // from now on, the timezone is never returned (even after 1000 queries) 2015-10-27 20:45:13.459 2015-10-27 20:45:13.459 2015-10-27 20:45:13.459 2015-10-27 20:45:13.459 ...

  • 如果我在不使用HikariCP的情况下直接创建连接,则可以正常工作。
  • 如果我在循环中的每个查询结束时都没有关闭连接(即我泄漏连接),则可以正常工作
  • 如果我在没有创建/关闭新连接的情况下使用相同的连接(即从池中获取一个连接并释放它),则每次都可以使用
  • 如果我每次使用带有相同网址的标准DriverManager.getConnection创建并关闭新连接,它都会有效。
  • 如果我不准备声明,则可以
  • 如果我准备两次声明(即使不使用第二次声明),它也能正常工作
  • 如果我准备第二个与第一个不同的陈述,那么它就不起作用

我尝试了普通和java6版本的hikaricp。 我使用postgres 9.4。我在scala工作,但我在java中创建了示例以扩大受众;)

我开了一个问题,但我有点匆忙,所以如果有人知道该怎么做...... 如果有人能指出我如何使用bonecp或其他任何游戏2.4,我也要感激不尽。

您可以使用仅具有HikariCP和postgres依赖项的项目重现该问题:

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class TestHikari {
    public static void main(String[] args) throws Exception {
        HikariConfig conf = new HikariConfig();
        conf.setJdbcUrl("jdbc:postgresql://localhost/postgres");
        conf.setDriverClassName("org.postgresql.Driver");

        HikariDataSource ds = new HikariDataSource(conf);
        Connection ddlconn = ds.getConnection();
        try { ddlconn.createStatement().execute("DROP TABLE TEST"); } catch(Exception ignored) {}
        ddlconn.createStatement().execute("CREATE TABLE TEST (ts TIMESTAMP with time zone)");
        ddlconn.createStatement().execute("insert into test(ts) values('2015-10-27 20:45:13.459+01')");
        ddlconn.close();

        for (int i = 0; i< 10; i++) {
            Connection conn = ds.getConnection();
            PreparedStatement stmt = conn.prepareStatement("select ts from TEST");
            //if I uncomment the next line, it works!
            //conn.prepareStatement("select ts from TEST");
            ResultSet rs = stmt.executeQuery();
            rs.next();

            System.out.println(rs.getString(1));

            conn.close();
        }
    }
}

1 个答案:

答案 0 :(得分:0)

此问题已在此处得到解答:https://github.com/brettwooldridge/HikariCP/issues/473

  

JDBC驱动程序的日期/时区存在一些问题   切换到服务器端预处理语句。默认会发生这种情况   在5个预处理语句执行之后(请参阅prepareThreshold参数   postgresql JDBC)。

所以这是postgres jdbc驱动程序中的一个错误。现在似乎唯一的解决方法是设置prepareThreshold = 0或切换到没有时区的时间戳。