我正在使用Oracle 11.2数据库,列类型为“TIMESTAMP WITH TIMEZONE”来存储时间相关信息。我无法更改它,因为它被现有系统使用。
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这样的时区的开始日期的新产品。 E.g。
2014-01-01 12:00:00 AEDT
它以
的形式保存在数据库中01-JAN-14 01.00.00.000000000 UTC
如果我再次从Java应用程序查询它,则Calendar对象具有UTC所示的时间,如上所示,而不是AEDT中的时间。这不仅仅是一个显示问题。
从AEDT到UTC的转换是正确的,但问题是因为插入了时区AEDT而丢失了信息。
有没有办法防止这种情况发生?为什么会发生这种情况?我今天搜索了很多,但找不到好的提示。
答案 0 :(得分:0)
您可以通过以下方式解决第一个问题:
首先,您需要解开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.hibernate.SQLQuery.class是包装的类)
第二,您必须为要检索的所有列设置类型:
hibernateQuery.addScalar("int_c", IntegerType.INSTANCE);
hibernateQuery.addScalar("str_c", StringType.INSTANCE);
hibernateQuery.addScalar("timestamp_c", TimestampType.INSTANCE);
第三,只需使用原始的JPA Query实例进行查询
List<Object[]> results = jpaQuery.getResultList();