2009-12-22 10 views
8

W PostgreSQL używam PersistentDuration do mapowania między interwałem typu sql & czas trwania, ale to nie działa.Jak odwzorować interwał typu w trybie hibernacji?

Inny użytkownik znalazł ten sam problem & pochodzą z własnej klasy:

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

    } 
} 

Ale to nie działa w rzeczywistym formacie ponieważ załóżmy wzór przedział jest tylko „hh: mm: ss” . To nie jest przypadek: patrz

tu kilka prawdziwych przykładach I trzeba przeanalizować z bazy danych:

 
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

masz czyste rozwiązanie?

Odpowiedz

0

Zgodnie z linkiem powinieneś mieć dzień, a następnie godziny: minuty: sekundy. Zmieniając kod na coś podobnego, zakładając, że nie musisz mieć więcej niż 23 godziny i 59 minut w interwale.

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

Nie mogę przetestować tego kodu, ponieważ nie mam zainstalowanego PostGreSql. Aby uzyskać kolejną dyskusję na ten sam temat, zobacz poniższy link, chociaż musisz zmodyfikować dostarczony kod, aby obsłużyć sekundy. To jednak nie powinno stanowić większego problemu.

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

+0

Nie jest to obowiązkowe, aby mieć day.And nie tylko dzień keywork (rok, miesiąc, tydzień, .. patrz link powyżej) Tutaj prawdziwych przykład z bazy danych: -1 dzień 00: 29:42 -00: 29: 42 -1 tydzień 00:29:42 1 tydzień 2 dni 00:29:42 1 miesiąc 1 tydzień 2 dni 00:29:42 -1 rok 00:29:42 1 dekada 00:29:42 – adam

3

to roztwór roboczy w JPA, hibernacji (z uwagi).

To początek klasy podmiotu (na stole, który ma kolumnę Interval):

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

Jest to kolumna przedział:

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

I to jest klasa 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; 
    } 

} 
0

PostgreSQL ma funkcję date_part/extract, której można użyć do zwrócenia różnych pola, epoki będące jednym z nich. Podczas wyodrębniania epoki z przedziału, otrzymujesz liczbę sekund zawartych w przedziale, a stamtąd możesz przekonwertować, jak chcesz. Straciłem doświadczenie z Hibernate, ale możesz to zrobić w następujący sposób:

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

Dlaczego nie zmienić tego na liczbowy i nie odwzorować na długi?

SELECT EXTRACT(epoch FROM my_interval) 
Powiązane problemy