我有一个使用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使用自定义类型映射参数进行本机查询?
答案 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。