postgresql - 如何在 Hibernate 中映射 PostgreSQL Interval 列类型?

标签 postgresql hibernate intervals custom-type column-types

在 PostgreSQL 下,我使用 PersistentDuration 来映射 sql 类型间隔和持续时间,但它不起作用。

另一位用户发现了同样的问题并带来了他自己的类(class):

public void nullSafeSet(PreparedStatement statement, Object value, int index) 
        throws HibernateException, SQLException { 
    if (value == null) { 
        statement.setNull(index, Types.OTHER); 
    } else { 
        Long interval = ((Long) value).longValue(); 
        Long hours = interval / 3600; 
        Long minutes = (interval - (hours * 3600)) / 60; 
        Long secondes = interval - (hours * 3600) - minutes * 60; 
            statement.setString(index, "'"+ hours +":" 
                    + intervalFormat.format(minutes) + ":" 
                    + intervalFormat.format(secondes)+"'"); 

    } 
}

但它不适用于真正的格式,因为它假设间隔模式只是 “hh:mm:ss”。事实并非如此:请参阅

这里有一些我需要从数据库中解析出来的真实例子:

1 day 00:29:42
00:29:42
1 week 00:29:42
1 week 2 days  00:29:42
1 month 1 week 2 days  00:29:42
1 year 00:29:42
1 decade 00:29:42

http://www.postgresql.org/docs/current/interactive/datatype-datetime.html

你有干净的解决方案吗?

最佳答案

这是一个适用于 JPA、Hibernate(带有注释)的工作解决方案。

这是实体类的开头(对于具有 Interval 列的表):

@Entity
@Table(name="table_with_interval_col")
@TypeDef(name="interval", typeClass = Interval.class)
public class TableWithIntervalCol implements Serializable {

这是间隔列:

@Column(name = "interval_col",  nullable = false)
@Type(type = "interval")    
private Integer intervalCol;

这是 Interval 类:

package foo.bar.hibernate.type;

import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Date;

import org.hibernate.HibernateException;
import org.hibernate.usertype.UserType;
import org.postgresql.util.PGInterval;


/**
 * Postgres Interval type
 * 
 * @author bpgergo
 * 
 */
public class Interval implements UserType {
    private static final int[] SQL_TYPES = { Types.OTHER };

    @Override
    public int[] sqlTypes() {
        return SQL_TYPES;
    }

    @SuppressWarnings("rawtypes")
    @Override
    public Class returnedClass() {
        return Integer.class;
    }

    @Override
    public boolean equals(Object x, Object y) throws HibernateException {
        return x.equals(y);
    }

    @Override
    public int hashCode(Object x) throws HibernateException {
        return x.hashCode();
    }

    @Override
    public Object nullSafeGet(ResultSet rs, String[] names, Object owner)
            throws HibernateException, SQLException {
        String interval = rs.getString(names[0]);
        if (rs.wasNull() || interval == null) {
            return null;
        }
        PGInterval pgInterval = new PGInterval(interval);
        Date epoch = new Date(0l);
        pgInterval.add(epoch);
        return Integer.valueOf((int)epoch.getTime() / 1000);
    }

    public static String getInterval(int value){
        return new PGInterval(0, 0, 0, 0, 0, value).getValue();
    }


    @Override
    public void nullSafeSet(PreparedStatement st, Object value, int index)
            throws HibernateException, SQLException {
        if (value == null) {
            st.setNull(index, Types.VARCHAR);
        } else {
            //this http://postgresql.1045698.n5.nabble.com/Inserting-Information-in-PostgreSQL-interval-td2175203.html#a2175205
            st.setObject(index, getInterval(((Integer) value).intValue()), Types.OTHER);
        }
    }

    @Override
    public Object deepCopy(Object value) throws HibernateException {
        return value;
    }

    @Override
    public boolean isMutable() {
        return false;
    }

    @Override
    public Serializable disassemble(Object value) throws HibernateException {
        return (Serializable) value;
    }

    @Override
    public Object assemble(Serializable cached, Object owner)
            throws HibernateException {
        return cached;
    }

    @Override
    public Object replace(Object original, Object target, Object owner)
            throws HibernateException {
        return original;
    }

}

关于postgresql - 如何在 Hibernate 中映射 PostgreSQL Interval 列类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1945615/

相关文章:

postgresql - 转储无法在 hstore 列的数组上重新创建索引

java - 仅存在于子类中的属性的别名(Hibernate Criteria)

r - 如何操作(聚合)R 中的数据?

datetime - Informix 日期时间 : How to subtract 15 Minutes

java - 从 SelectQuery(或等效项)中提取查询部分?

mysql - 从与自身外键相关的 SQL 表中选择最顶层的父级

postgresql - 在 postgresql 函数中抛出异常

java - Hibernate Session 更新未反射(reflect)在数据库中

java - Spring 计划作业中的 Hibernate Lazy init 异常

MySQL DATE_ADD 间隔