2009-12-22 17 views
8

En PostgreSQL, estoy usando PersistentDuration para la asignación entre el intervalo de tipo sql & duración, pero no funciona.Cómo asignar el tipo Intervalo en Hibernate?

Otro usuario encontrado el mismo problema & venido con su propia clase:

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)+"'"); 

    } 
} 

Pero no funciona con el formato real porque supongamos que el patrón de intervalo es sólo "hh: mm: ss" . Ese no es el caso: ver

Aquí algunos pocos ejemplos reales que necesito para analizar la base de datos:

 
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

tiene una solución limpia?

Respuesta

0

Según el enlace, debe tener un día seguido de horas: minutos: segundos. Cambiando el código a algo así como lo siguiente suponiendo que nunca necesita tener más de 23 horas y 59 minutos en el intervalo.

statement.setString(index, "'0 "+ hours +":" 
+ intervalFormat.format(minutes) + ":" 
+ intervalFormat.format(secondes)+"'"); 

No puedo probar este código ya que no tengo instalado PostGreSql. Para otra discusión sobre este mismo problema, consulte el siguiente enlace, aunque deberá modificar el código provisto para manejar los segundos. Sin embargo, eso no debería ser un gran problema.

https://forum.hibernate.org/viewtopic.php?p=2348558&sid=95488ce561e7efec8a2950f76ae4741c

+0

No es obligatorio tener un day.And no sólo el día keywork (año, mes, semana, .. ver el siguiente enlace) Aquí algunos ejemplos reales de la base de datos: -1 día 00: 29:42 -00: 29: 42 -1 semana 00:29:42 1 semana 2 días 00:29:42 1 mes 1 semana 2 días 00:29:42 -1 año 00:29:42 1 década 00:29:42 – adam

3

Esta es una solución de trabajo para JPA, Hibernate (con anotaciones).

Este es el comienzo de la clase de entidad (para la tabla que tiene la columna Intervalo):

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

Ésta es la columna de intervalo:

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

Y esta es la clase de intervalo:

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; 
    } 

} 
0

PostgreSQL tiene una función date_part/extract que puede usar para devolver diferentes campos, época es uno de ellos. Cuando extrae la época de un intervalo, recibe la cantidad de segundos que contiene el intervalo y, a partir de allí, puede convertir como lo desee. Perdí mi experiencia con Hibernate, pero puedes hacerlo de esta manera:

SELECT 
    average_interval_between_airings 
    , date_part('epoch', average_interval_between_airings)/60 as minutes 
    , date_part('epoch', average_interval_between_airings) as seconds 
FROM shows; 
1

¿Por qué no simplemente convertirlo en un numérico y asignarlo a Long?

SELECT EXTRACT(epoch FROM my_interval) 
Cuestiones relacionadas