You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Hibernate中将null转换为自定义@Type(PersistentDateTime)?

解决方案

针对当前环境(Spring 4.1.7 + Hibernate 4.2.5 + Java 7)

核心思路是让查询返回的null匹配PersistentDateTime/PersistentLocalDate对应的JDBC类型,同时显式告知Hibernate字段的类型映射:

1. 调整查询语句,将null转换为对应JDBC类型

  • 对于DateTime(对应PersistentDateTime),JDBC类型为TIMESTAMP,修改查询语句:
    // 用case处理分支,确保返回类型统一为TIMESTAMP
    sb.append(", case when :p_fooId is not null then (select foo.statusDate from Foo foo where foo.id = :p_fooId) else cast(null as timestamp) end as fooStatusDate");
    
  • 对于LocalDate(对应PersistentLocalDate),JDBC类型为DATE,修改为:
    sb.append(", case when :p_fooId is not null then (select foo.localDateField from Foo foo where foo.id = :p_fooId) else cast(null as date) end as fooStatusDate");
    

2. 查询时显式指定字段类型映射

在创建SQLQuery时,通过addScalar指定字段对应的Hibernate类型,确保null能被正确转换为Joda类型:

SQLQuery query = session.createSQLQuery(sb.toString());
query.setParameter("p_fooId", fooId);
// 针对DateTime
query.addScalar("fooStatusDate", new org.jadira.usertype.dateandtime.joda.PersistentDateTime());
// 针对LocalDate则替换为
// query.addScalar("fooStatusDate", new org.jadira.usertype.dateandtime.joda.PersistentLocalDate());
// 映射到DTO或实体
query.setResultTransformer(Transformers.aliasToBean(YourResultDTO.class));

3. 替代方案:使用子查询返回统一类型的null

如果不想用case语句,可以构造一个始终返回null的子查询,确保类型匹配:

// 针对DateTime,从Foo表取一个null的statusDate(利用表结构的类型)
sb.append(", (select foo.statusDate from Foo foo where 1=0) as fooStatusDate");

这个子查询永远返回null,但类型和statusDate一致,Hibernate能直接识别并转换为Joda类型的null。

新版本方案(Hibernate 5.2+ + Java 8+)

放弃Jadira UserType,使用Hibernate原生的日期类型支持:

  1. 使用Java 8日期类型:将实体字段替换为java.time.LocalDateTime/java.time.LocalDate,Hibernate 5.2+原生支持,无需额外Type注解:

    @Column(name = "STATUSDATE", nullable = false)
    private LocalDateTime statusDate;
    
  2. 简化查询语句:直接使用coalesce或直接返回null,Hibernate会自动处理类型映射:

    // 用coalesce处理,子查询无结果时返回null
    sb.append(", coalesce((select foo.statusDate from Foo foo where foo.id = :p_fooId), null) as fooStatusDate");
    
  3. 若仍需使用Joda Time,Hibernate 5+提供hibernate-joda模块,可直接使用内置类型,无需Jadira,查询时同样只需保证返回的null对应JDBC类型即可。

内容的提问来源于stack exchange,提问作者Nikolas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 17:34:55