Bonjour,

Une table de ma base de données sous PostGreSQL contient un champ de domaine d_t_interval. Ce domaine correspond au type standard SQL INTERVAL.

Utilisant Hibernate, et Hibernate ne gérant pas par défaut le type INTERVAL (spécial bouh pour cela c'est quand même issu de la norme), j'utilise un Type Utilisateur perso en somme.

Voici le code de ce type :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package i2.application.commun.integration; 
 
import i2.application.commun.exception.TechniqueException; 
 
import java.io.Serializable; 
import java.sql.BatchUpdateException; 
import java.sql.PreparedStatement; 
import java.sql.ResultSet; 
import java.sql.SQLException; 
import java.sql.Types; 
import java.text.DecimalFormat; 
import java.util.regex.Matcher; 
import java.util.regex.Pattern; 
 
import org.hibernate.HibernateException; 
import org.hibernate.usertype.UserType; 
 
/** 
 * Mappe le type Interval pour PostGreSQL en passant le type interval vers des 
 * minutes. Les secondes sont ignorées ! 
 *  
 * @author Alexandre TRANCHANT 
 * @todo convertir en décimal et géré les secondes 
 * @fixme Gérer les retours de types 2 years 3 months 4 days 5 hours 33 minutes 
 */ 
public class IntervalUserType implements UserType { 
 
    private static Pattern intervalPattern = Pattern 
            .compile("([0-9]*):([0-9]{2}):([0-9]{2})"); 
 
    private static DecimalFormat intervalFormat = new DecimalFormat("00"); 
 
    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 { 
        if (arg0 == null && arg1 == null){ 
            return true; 
        }else if (arg0 == null){ 
            return false; 
        }else{ 
            return arg0.equals(arg1); 
        } 
    } 
 
    public int hashCode(Object object) throws HibernateException { 
        return object.hashCode(); 
    } 
 
    public boolean isMutable() { 
        return false; 
    } 
 
    public Object nullSafeGet(ResultSet resultSet, String[] names, Object owner) 
            throws HibernateException, SQLException { 
        String interval = resultSet.getString(names[0]); 
        if (resultSet.wasNull() || interval == null) { 
            return null; 
        } 
        Matcher intervalMatch = intervalPattern.matcher(interval); 
        if (!intervalMatch.matches()) { 
            throw new HibernateException("L'intervalle " + names[0] 
                    + " contenant " + interval 
                    + " doit correspondre au schéma " 
                    + intervalPattern.pattern()); 
        } 
        Long hours = Long.parseLong(intervalMatch.group(1)); 
        Long minutes = Long.parseLong(intervalMatch.group(2)); 
        Long secondes = Long.parseLong(intervalMatch.group(3)); 
        return new Long(hours * 3600 + minutes * 60 + secondes); 
    } 
 
    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, "CAST ('"+ hours +":" 
                        + intervalFormat.format(minutes) + ":" 
                        + intervalFormat.format(secondes)+"' AS INTERVAL)"); 
 
        } 
    } 
 
    public Object replace(Object original, Object target, Object owner) 
            throws HibernateException { 
        return original; 
    } 
 
    public Class returnedClass() { 
        return Long.class; 
    } 
 
    public int[] sqlTypes() { 
        return new int[] { Types.OTHER }; 
    } 
 
}
Je peux très bien lire les données. Cela fonctionne sans difficulté. Par contre il m'est impossible d'écrire une donnée.

Lorsque j'insère j'obtiens un message d'erreur général sans importance me disant que le JDBC a planté. En dessous, je lis la requête à l'origine de l'incident. Quand je regarde le code SQL généré j'obtiens :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
update tj_etat_eta set eta_duree = 350:00:12 where eta_id = 13;
J'ai tout essayé dans ma méthode nullSafeSet.
Que j'utilise la méthode donnée ou des variantes comme celle ci-dessous, rien ne marche :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
 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(); 
              statement.setLongindex, interval); 
 
        } 
    }
De même avec ce type de code...
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 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)+"'"); 
 
        } 
    }
Le problème reste entier, dans le Log de PostGreSQL je lis qu'une erreur est levée. JDBC tente de placer un varchar (ou un Long) dans un d_t_interval... Pourtant quand je copie le code sous ma console postgresql, ca fontionne sans problème.

Vous voyez une piste vous ?