项目中使用了Postgres-XC作为关系型数据库,而应用则是部署在IBM WAS中,在WAS控制台的配置了基于postgresql-9.3-1103.jdbc4.jar的数据源,但发现一个问题,某个读取包含timestamp类型字段的查询在创建连接后前几次执行不会报错,但后续的执行就会报错。
Caused by: org.postgresql.util.PSQLException: Unsupported binary encoding of timestamp.
at org.postgresql.jdbc2.TimestampUtils.toTimestampBin(TimestampUtils.java:727)
at org.postgresql.jdbc2.AbstractJdbc2ResultSet.getTimestamp(AbstractJdbc2ResultSet.java:517)
at org.postgresql.jdbc2.AbstractJdbc2ResultSet.getTimestamp(AbstractJdbc2ResultSet.java:2629)
at com.ibm.ws.rsadapter.jdbc.WSJdbcResultSet.getTimestamp(WSJdbcResultSet.java:2672)
at org.hibernate.type.descriptor.sql.TimestampTypeDescriptor$2.doExtract(TimestampTypeDescriptor.java:62)
at org.hibernate.type.descriptor.sql.BasicExtractor.extract(BasicExtractor.java:64)
at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:254)
at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:250)
at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:230)
at org.hibernate.type.AbstractStandardBasicType.hydrate(AbstractStandardBasicType.java:331)
at org.hibernate.persister.entity.AbstractEntityPersister.hydrate(AbstractEntityPersister.java:2283)
at org.hibernate.loader.Loader.loadFromResultSet(Loader.java:1527)
at org.hibernate.loader.Loader.instanceNotYetLoaded(Loader.java:1455)
at org.hibernate.loader.Loader.getRow(Loader.java:1355)
at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:611)
at org.hibernate.loader.Loader.doQuery(Loader.java:829)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:274)
at org.hibernate.loader.Loader.doList(Loader.java:2542)
... 82 more
查看postgresql jdbc源码可以看到报错的那段代码。
/**
* Returns the SQL Timestamp object matching the given bytes with
* {@link Oid#TIMESTAMP} or {@link Oid#TIMESTAMPTZ}.
*
* @param tz The timezone used when received data is {@link Oid#TIMESTAMP},
* ignored if data already contains {@link Oid#TIMESTAMPTZ}.
* @param bytes The binary encoded timestamp value.
* @param timestamptz True if the binary is in GMT.
* @return The parsed timestamp object.
* @throws PSQLException If binary format could not be parsed.
*/
public Timestamp toTimestampBin(TimeZone tz, byte[] bytes, boolean timestamptz)
throws PSQLException {
if (bytes.length != 8) {
throw new PSQLException(GT.tr("Unsupported binary encoding of {0}.",
"timestamp"), PSQLState.BAD_DATETIME_FORMAT);
}
可以看到得到的是以二进制编码的时间值,在jdbc代码中将其转化为Java中的Timestamp类型,而报错的原因是二进制编码的时间值存在问题。是WAS的问题?还是hibernate的问题?还是postgresql-jdbc的问题?还是postgres-xc的问题?
查看网络资料,发现postgresql-jdbc有两种传输数据的方式,一种是字符串,一种是二进制。使用二进制传输可以减少网络传输所需的字节数,进而提高效率。同时,在postgresql-jdbc中有相对应的配置,所以,如果二进制传输出错,是否可以尝试一下传统的字符串传输呢?