IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Hibernate Java Discussion :

Type Interval pour Hibernate


Sujet :

Hibernate Java

  1. #1
    Membre Expert
    Avatar de Alexandre T
    Homme Profil pro
    Chef de projets AMO
    Inscrit en
    Mai 2002
    Messages
    1 213
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Chef de projets AMO
    Secteur : Transports

    Informations forums :
    Inscription : Mai 2002
    Messages : 1 213
    Par défaut Type Interval pour Hibernate
    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 ?
    Alexandre Tranchant
    Chef de projet AMO pour le Cerema.
    Retrouvez mes articles sur PHP et Symfony

  2. #2
    Membre Expert
    Avatar de Alexandre T
    Homme Profil pro
    Chef de projets AMO
    Inscrit en
    Mai 2002
    Messages
    1 213
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Chef de projets AMO
    Secteur : Transports

    Informations forums :
    Inscription : Mai 2002
    Messages : 1 213
    Par défaut
    Malgré mes recherches sur Hibernate et sur Interval, je ne trouvais rien. Mais en faisant une recherche sur JDBC et sur Interval, j'ai trouvé une piste. Elle n'est pas très belle car je suis dépendant du type de SGBD. Mais bon, nous n'en utilisons qu'un : PostGreSQL.

    Voici la solution, il fallait utiliser la méthode setObject de la classe PreparedStatement en plaçant en argumant un objet de type org.postgresql.util.PGInterval.

    Ceci me donne donc :
    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
    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; 
                PGInterval monIntervalle = new PGInterval();
                monIntervalle.setString(hours +":" 
                            + intervalFormat.format(minutes) + ":" 
                            + intervalFormat.format(secondes)+"'");
                statement.setObject(index, monIntervalle); 
     
            }
        }
    Code GPL, vous pouvez l'utiliser et l'améliorer. PS : prévenez-moi
    Alexandre Tranchant
    Chef de projet AMO pour le Cerema.
    Retrouvez mes articles sur PHP et Symfony

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    23
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 23
    Par défaut
    La solution proposé par Alexandre ne fonctionne que sur un cas particulier et suppose le format suivant d'une intervalle
    'HH:MM:SS'

    Or ce format oubli les microsecondes & les intervalles supérieures à 99h.

    De plus, selon la DOC :
    http://www.postgresql.org/docs/8.0/s...e.html#AEN4564

    Le format est plus complexe (year,y,Week,w).Parser cela meme avec une expression régulire relève du casse-tête il est toujours possible de basculer dans un format d'interval iso avec la commande & d'utiliser conjointement la classe Period de JodaTime.:

    set interval=(format)
    ou de modifier le .conf de potsgres pour que cela sout le format par défaut.

    La solution que j'ai utilisé , n'est pas le set interval.. fut l'utilisation de
    PeriodFormatter parser =new PeriodFormatterBuilder() pour créer votre propre format suffisant de "x day(s) HH:MM:SS.MMM' , comptabile avec Postgre.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Probleme pour inserer des donnees de type INTERVAL DAY
    Par JUSTIN Loïc dans le forum Oracle
    Réponses: 1
    Dernier message: 01/09/2006, 09h29
  2. Langage de prog. simple type basic pour RS232, vos idées SVP
    Par briconique dans le forum Langages de programmation
    Réponses: 8
    Dernier message: 14/08/2006, 22h45
  3. type "file" pour la balise input
    Par fa_say dans le forum Balisage (X)HTML et validation W3C
    Réponses: 2
    Dernier message: 23/09/2005, 15h13
  4. [CSS] Le type hand pour cursor dans une balise AREA
    Par Invité dans le forum Mise en page CSS
    Réponses: 6
    Dernier message: 13/04/2005, 13h33
  5. informations sur le type interval dans interbase
    Par devalender dans le forum InterBase
    Réponses: 6
    Dernier message: 03/06/2004, 10h29

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo