Hibernate识别数据库特有字段实例详解
发布时间 - 2026-01-11 01:36:44 点击率:次Hibernate识别数据库特有字段实例详解

前言:
Hibernate已经为绝大多数常用的数据库数据类型提供了内置支持,但对于某些数据库的专属字段支持就不够好了。 这些特殊数据类型往往提供了比常规数据类型更好的数据表达能力,更符合我们的业务场景。比如PostgreSQL的Interval类型,可以非常方便的保存一个时间段的数据。 本文以添加Interval类型支持为例,说明为Hibernate添加特有数据类型支持的方法。
Hibernate提供了丰富的数据类型支持,但对于部分数据库专有的数据类型,提供的支持就很有限了。比如PostgreSQL的Interval类型,对于保存一个"时间段"数据就非常方便。
在开发中,我们期望将Interval类型映射为Java 8 的Duration类型。但是Hibernate默认对Duration类型的映射是直接映射到数据库的BigInt类型,直接保存纳秒值。显然对于不直接支持Interval类型的数据库来说,是比较合适的,但是我们仍然期望直接映射到数据库的Interval类型。
为此,我们需要调整Hibernate对于两种数据类型(Java世界的Duration和Db世界的Interval)的映射关系。
幸运的是,Hibernate提供了非常方便的方法可以实现数据类型的映射。
为此,我们需要一个实现org.hibernate.usertype.UserType接口的类,来实现两个世界的数据转换/映射工作。
Hibernate的自定义类型(UserType)
UserType是Hibernate提供的一个自定义数据类型的接口。所有自定义数据均需实现此接口,或者从org.hibernate.usertype中定义的接口中选择一个合适的接口。
鉴于我们的场景比较简单,直接实现UserType即可满足需求。此接口提供了如下一组方法需要自己实现:
assemble(Serializable cached, Object owner)
从序列化中重新构建(Java)对象。
deepCopy(Object value)
返回深度副本。
disassemble(Object value)
转换对象的序列化数据。
equals(Object x, Object y)
返回两个映射的数据是否相等。
hashCode(Object x)
获取对象的散列。
isMutable()
返回对象是否是可变类型。
nullSafeGet(ResultSet rs, String[] names, Object owner)
从数据库类型的数据,返回对应的Java对象。核心实现方法
nullSafeSet(PreparedStatement st, Object value, int index)
从Java对象,返回对应的数据库类型的数据。核心实现方法
replace(Object original, Object target, Object owner)
合并期间,将实体中的目标值(target)替换为原始值(original)。
returnedClass()
nullSafeGet返回的类。
sqlTypes()
返回对应的数据库类型。
实例
package framework.postgresql;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.usertype.UserType;
import org.postgresql.util.PGInterval;
import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.time.Duration;
/**
* PostgreSql Inteval字段与java.time.Duration映射
* 目前只支持到最多1个月(30天)的间隔
* <p>
* 使用方法:
* 在实体类上增加
* \@TypeDef(name="interval", typeClass = IntervalType.class)
* 在字段定义上增加:
* \@Type(type = "interval")
* <p>
* http://stackoverflow.com/questions/1945615/how-to-map-the-type-interval-in-hibernate/6139581#6139581
*
* @version 1.0
* @since 1.0
*/
public class IntervalType implements UserType {
public Object assemble(Serializable cached, Object owner) throws HibernateException {
return cached;
}
public Object deepCopy(Object value) throws HibernateException {
return value;
}
public Serializable disassemble(Object value) throws HibernateException {
return (Serializable) value;
}
public boolean equals(Object arg0, Object arg1) throws HibernateException {
return arg0 != null && arg1 != null && arg0.equals(arg1) || arg0 == null && arg1 == null;
}
public int hashCode(Object object) throws HibernateException {
return object.hashCode();
}
@Override
public Object nullSafeGet(ResultSet resultSet, String[] names, SharedSessionContractImplementor sessionImplementor, Object o) throws HibernateException, SQLException {
String interval = resultSet.getString(names[0]);
if (resultSet.wasNull() || interval == null) {
return null;
}
PGInterval pgInterval = new PGInterval(interval);
return getDuration(pgInterval);
}
@Override
public void nullSafeSet(PreparedStatement st, Object value, int index, SharedSessionContractImplementor sessionImplementor) throws HibernateException, SQLException {
if (value == null) {
st.setNull(index, Types.OTHER);
} else {
//this http://postgresql.1045698.n5.nabble.com/Inserting-Information-in-PostgreSQL-interval-td2175203.html#a2175205
Duration duration = (Duration) value;
st.setObject(index, getInterval(duration), Types.OTHER);
}
}
public static Duration getDuration(PGInterval pgInterval) {
return Duration.ofSeconds(pgInterval.getDays() * 24 * 3600 +
pgInterval.getHours() * 3600 +
pgInterval.getMinutes() * 60 +
(int) pgInterval.getSeconds());
}
private static PGInterval getInterval(Duration value) {
long seconds = value.getSeconds();
int days = (int) (seconds / (24 * 3600));
seconds -= days * 24 * 3600;
int hours = (int) (seconds / 3600);
seconds -= hours * 3600;
int minutes = (int) (seconds / 60);
seconds -= minutes * 60;
seconds = Math.abs(seconds);
return new PGInterval(0, 0, days, hours, minutes, seconds);
}
public boolean isMutable() {
return false;
}
public Object replace(Object original, Object target, Object owner) throws HibernateException {
return original;
}
public Class returnedClass() {
return Duration.class;
}
public int[] sqlTypes() {
return new int[]{Types.OTHER};
}
}
使用自定义类型
至此,我们已经定义好了自己的数据类型。但Hibernate还不知道怎么使用它。为此,我们需要通过在Entity上使用使用TypeDef注解,并在属性上使用Type注解。
比如:
...
@Entity
@TypeDef(name = "interval", typeClass = IntervalType.class)
public class PaperStatis implements Serializable {
...
@Column(name = "avg_duration")
@Type(type = "interval")
public Duration getAvgDuration() {
return this.avgDuration;
}
...
}
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
# Hibernate识别数据库特有字段
# Hibernate
# 数据库字段
# Hibernate迫切连接和普通连接的区别实例详解
# hibernate通过session实现增删改查操作实例解析
# 在已有spring的基础上集成hibernate的实例讲解
# hibernate属性级别注解实例代码
# Hibernate 修改数据的实例详解
# JSP开发之hibernate之单向多对一关联的实例
# hibernate4快速入门实例详解
# Hibernate初体验及简单错误排除代码详解
# 自定义
# 自己的
# 的是
# 序列化
# 好了
# 最多
# 就不
# 两种
# 很有
# 并在
# 希望能
# 为例
# 可以实现
# 谢谢大家
# 来实现
# 不知道怎么
# 个月
# 不直接
# 比较合适
# 更符合
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
Laravel事件监听器怎么写_Laravel Event和Listener使用教程
制作网站软件推荐手机版,如何制作属于自己的手机网站app应用?
如何用AI一键生成爆款短视频文案?小红书AI文案写作指令【教程】
Laravel的契約(Contracts)是什么_深入理解Laravel Contracts与依赖倒置
如何快速生成可下载的建站源码工具?
如何制作一个表白网站视频,关于勇敢表白的小标题?
最好的网站制作公司,网购哪个网站口碑最好,推荐几个?谢谢?
如何制作新型网站程序文件,新型止水鱼鳞网要拆除吗?
Android自定义控件实现温度旋转按钮效果
桂林网站制作公司有哪些,桂林马拉松怎么报名?
简历在线制作网站免费版,如何创建个人简历?
如何在IIS中新建站点并配置端口与IP地址?
php json中文编码为null的解决办法
Laravel如何实现用户注册和登录?(Auth脚手架指南)
laravel怎么在请求结束后执行任务(Terminable Middleware)_laravel Terminable Middleware请求结束任务执行方法
Laravel如何实现登录错误次数限制_Laravel自带LoginThrottles限流配置【方法】
🚀拖拽式CMS建站能否实现高效与个性化并存?
谷歌浏览器如何更改浏览器主题 Google Chrome主题设置教程
如何在阿里云域名上完成建站全流程?
Android okhttputils现在进度显示实例代码
HTML5空格和margin有啥区别_空格与外边距的使用场景【说明】
如何快速搭建高效服务器建站系统?
Gemini怎么用新功能实时问答_Gemini实时问答使用【步骤】
php后缀怎么变mp4格式错误_修改扩展名提示格式不对怎么办【技巧】
如何在橙子建站中快速调整背景颜色?
如何续费美橙建站之星域名及服务?
Laravel如何集成Inertia.js与Vue/React?(安装配置)
高防服务器如何保障网站安全无虞?
Laravel如何记录日志_Laravel Logging系统配置与自定义日志通道
Laravel辅助函数有哪些_Laravel Helpers常用助手函数大全
如何在宝塔面板中修改默认建站目录?
Laravel怎么清理缓存_Laravel optimize clear命令详解
Java类加载基本过程详细介绍
Laravel怎么集成Vue.js_Laravel Mix配置Vue开发环境
微博html5版本怎么弄发语音微博_语音录制入口及时长限制操作【教程】
ChatGPT 4.0官网入口地址 ChatGPT在线体验官网
微信小程序 require机制详解及实例代码
Laravel如何生成API文档?(Swagger/OpenAPI教程)
Python自然语言搜索引擎项目教程_倒排索引查询优化案例
javascript中的数组方法有哪些_如何利用数组方法简化数据处理
北京企业网站设计制作公司,北京铁路集团官方网站?
Laravel如何实现图片防盗链功能_Laravel中间件验证Referer来源请求【方案】
如何在云指建站中生成FTP站点?
北京专业网站制作设计师招聘,北京白云观官方网站?
如何在云虚拟主机上快速搭建个人网站?
阿里云高弹*务器配置方案|支持分布式架构与多节点部署
HTML 中如何正确使用模板变量为元素的 name 属性赋值
高性能网站服务器部署指南:稳定运行与安全配置优化方案
如何快速使用云服务器搭建个人网站?
Win11怎么恢复误删照片_Win11数据恢复工具使用【推荐】

