如何在jpa本机查询中转换joda DateTime

时间:2013-10-02 00:27:26

标签: hibernate jpa jodatime spring-data-jpa

我有一个使用hibernate

保留DateTime属性的实体
@Type(type = "org.jadira.usertype.dateandtime.joda.PersistentDateTime")
@Column(name = "EFF_DT")
protected DateTime effDt;

这一切都适用于常规spring-data-jpa生成的查询。

我正在尝试添加自定义原生查询

 @Query(value = "SELECT COUNT(*) FROM wsa_circuit_state_history ch WHERE ch.eff_dt between ?1 and ?2", nativeQuery = true)
    Integer countEffDateBetween(DateTime start, DateTime end);

我得到的错误是在尝试调用时

 java.sql.SQLException: ORA-00932: inconsistent datatypes: expected DATE got BINARY

这是我在将自定义类型映射添加到我的实体之前使用常规spring-data finder获得的相同错误

 @Type(type = "org.jadira.usertype.dateandtime.joda.PersistentDateTime")

如何使spring-data-jpa / hibernate使用自定义类型映射参数进行本机查询?

3 个答案:

答案 0 :(得分:1)

我也得到了同样的要求。我通过将自定义类型注册到hibernate配置来解决它。

对于本机查询,TypeDef不足以让hibernate找到用户类型。它需要Type解析器才能找到它的类型。

@Query(value = "SELECT COUNT(*) FROM wsa_circuit_state_history ch WHERE ch.eff_dt between ?1 and ?2", nativeQuery = true)
    Integer countEffDateBetween(DateTime start, DateTime end);

在这种情况下,hibernate会尝试从类型解析器中猜出类型(org.joda.time.DateTime)。

Type type = session.getFactory().getTypeResolver().heuristicType(typename);

因为没有DateTime的解析器。然后它获得默认类型(可序列化类型)。并且DateTime的值被转换为它的类型,它被序列化并持久存储在DB中,由于大二进制值而失败

要解决此问题,您需要将DateTime类型注册为Hibernate Configuration

configuration.registerTypeOverride(new org.jadira.usertype.dateandtime.joda.PersistentDateTime(), new String[]{"org.joda.time.DateTime"});

答案 1 :(得分:0)

只需将您的属性设置为java.util.Date,就像这样

@Type(type = "org.jadira.usertype.dateandtime.joda.PersistentDateTime")
@Column(name = "EFF_DT")
@Temporal( TemporalType.TIMESTAMP )
protected Date effDt;

然后转换你的getter / setter

public DateTime getEffDt() {
    return null == effDt ? null : new DateTime( effDt );
}

public void setEffDt( final DateTime effDt ) {
    this.effDt = null == effDt ? null : effDt.toDate();
}

本机:

@Query(value = "SELECT COUNT(*) FROM wsa_circuit_state_history ch WHERE ch.eff_dt between ?1 and ?2", nativeQuery = true)
Integer countEffDateBetween(Date start, Date end);

答案 2 :(得分:0)

在类似的情况下,我使用自定义CompositeUserType编写了一个将Joda DateTime存储在两个字段中的日期时间字段和时区字段。

当实体被保存时,它将时间值以UTC和时区存储为原始值,在检索时它反过来(即它将存储在数据库中的时间转换回原始时区)。

如上所述,尽管像“dateTime BETWEEN?1 AND?2”这样的查询具有直观意义,但当然在复合类型方面没有任何意义,因为您需要牢记时区。这就是我将所有值存储在UTC中的原因,因此我总是可以比较数据库中的任何两个日期/时间值。

不幸的是,这意味着我传递的所有日期/时间查询参数都必须转换为UTC。