含NOW()条件的查询在psql与JDBC中表现不一致问题
先还原下你的问题场景:
我在psql控制台执行以下查询能正常拿到输出:
select details from history_transactions ,history_operations where history_operations.transaction_id = history_transactions.id and type = 3 and created_at >= NOW() - INTERVAL '5 minutes'但用Java程序调用同一查询时,ResultSet是空的,连
Inside resultset都没打印出来。我的Java代码大致是这样:Connection conn = getConnection(); java.sql.Statement stmt = null; String sql ="select details from history_transactions , history_operations where history_operations.transaction_id=history_transactions.id and type =3 and created_at >= NOW() - INTERVAL '5 minutes'; try{ stmt = conn.createStatement(); rs = stmt.executeQuery(sql); while(rs.next()) { System.out.println("Inside resultset"); } } catch(Exception e) { // 省略异常处理 }
下面是我整理的几个排查方向,你可以逐一试试:
先修掉SQL字符串的语法错误
看你Java代码里的SQL字符串,末尾少了一个闭合的双引号!原代码里String sql ="select ... '5 minutes';这行最后没收尾,这会直接导致SQL语句不合法,大概率执行时抛出了异常,但你的catch块没打印错误信息,所以你没察觉到。先把SQL改成:String sql = "select details from history_transactions , history_operations where history_operations.transaction_id=history_transactions.id and type =3 and created_at >= NOW() - INTERVAL '5 minutes'";检查时区差异
psql控制台和Java程序连接数据库时的时区可能不一样!NOW()取的是数据库服务器的当前时间,但如果Java连接的时区设置和你操作psql时的时区不同,会导致created_at >= NOW() - INTERVAL '5 minutes'的筛选逻辑出现偏差。
你可以在Java的数据库连接URL里显式指定时区,比如:jdbc:postgresql://你的主机:5432/你的数据库?serverTimezone=UTC或者把SQL里的
NOW()换成CURRENT_TIMESTAMP,再或者显式指定时区(比如NOW() AT TIME ZONE 'Asia/Shanghai'),确保和你psql控制台用的时区一致。排查事务隔离和未提交数据的问题
如果你在psql里执行查询前有未提交的事务,而Java程序的连接用了不同的事务隔离级别,可能看不到这些未提交的数据。可以在Java代码里设置自动提交:conn.setAutoCommit(true);或者先在psql里执行
COMMIT提交事务,再用Java程序测试。一定要打印异常信息
你的catch块只写了省略号,强烈建议把异常栈打出来,比如:catch(Exception e) { e.printStackTrace(); }很多时候空ResultSet的背后其实是SQL执行报错,只是你没看到而已。
明确字段的表归属
注意type和created_at这两个字段属于哪张表?如果两张表都有同名字段,必须加上表名前缀(比如history_operations.type = 3、history_transactions.created_at >= ...),不然数据库可能解析到错误的字段,直接导致筛选结果为空。
内容的提问来源于stack exchange,提问作者sweta

