Oracle "TIMESTAMP WITH TIMEZONE"原始 sql 查询的 Java 类型映射问题



我正在使用一个列类型为"TIMESTAMP with TIMEZONE"的Oracle 11.2数据库来存储与时间相关的信息。我无法更改它,因为它已被现有系统使用。

Java应用程序使用ojdbc7(v12.1.0.2)+hibernate作为JPA提供程序。

为了便于理解,我简化了下面的例子!

有一个实体"Product",它将"TIMESTAMP WITH TIMEZONE"列映射到java.util.Calendar

@Entity
@Table(name = "PRODUCT")
public class Product {
@Id
@Column(name = "ID")
private String id;
@Column(name = "START_DATE", columnDefinition = "TIMESTAMP WITH TIME ZONE")
private Calendar startDate;
....
}

如果我通过HQL查询加载它,它可以正常工作。

1.发布

如果我使用原始sql查询:

SELECT * FROM PRODUCT where id='123456';

我得到以下异常:

org.hibernate.MappingException: No Dialect mapping for JDBC type: -101

sql查询要复杂得多,我只是在这里用了一个非常简单的例子。所以我不能简单地将它转换为HQL查询。

2.发布

如果我坚持使用一个新产品,它的开始日期有一个时区,比如AEDT。例如

2014-01-01 12:00:00 AEDT

它被保存在数据库中作为

01-JAN-14 01.00.00.000000000 UTC

如果我再次从Java应用程序中查询它,则Calendar对象的时间以UTC为单位,如上所示,而不是以AEDT为单位。这不仅仅是一个显示问题。

从AEDT到UTC的转换是正确的,但问题是它与时区AEDT一起插入的信息丢失了。

有办法防止这种情况发生吗?为什么会发生这种情况?我今天找了很多,但找不到一个好的提示。

您可以通过以下方式解决第一个问题:

首先,您需要打开Query实现的包装。你说你在使用JPA+Hibernate,所以:

Query jpaQuery = entityManager.createNativeQuery("select, t.int_c, t.str_c, t.timestamp_c from table t");
SQLQuery hibernateQuery = jpaQuery.unwrap(SQLQuery.class);

(org.hubinate.SQLQuery.class是包装类)

其次,您必须为要检索的所有列设置类型:

hibernateQuery.addScalar("int_c", IntegerType.INSTANCE);
hibernateQuery.addScalar("str_c", StringType.INSTANCE);
hibernateQuery.addScalar("timestamp_c", TimestampType.INSTANCE);

第三,只需使用原始JPA查询实例进行查询

List<Object[]> results = jpaQuery.getResultList();

最新更新