[Résolu] Configuration d'Hibernate

Bonjour à tous,

j’ai un problème de connection à une base Oracle via JDBC via hibernate. Le problème c’est qu’il bloque sans me donner aucune information.

Je suis sur une machine Windows avec du Java 6, le serveur est un Red Hat avec Oracle 10. Grâce à Maven, j’ai bien mon jar ojdbc1.4, voici les logs d’hibernate :

INFO: autocommit mode: false 20 nov. 2007 17:21:58 org.hibernate.connection.DriverManagerConnectionProvider configure INFO: using driver: oracle.jdbc.OracleDriver at URL: jdbc:oracle:thin:@tmaggen:1521:pmag 20 nov. 2007 17:21:58 org.hibernate.connection.DriverManagerConnectionProvider configure INFO: connection properties: {user=traitement, password=****}

Et puis blocage complet.

A noter que j’arrive à me connecter sans problème sous Oracle SQLDeveloper et sous Perl DBI.

A priori, sans code ni logs plus complets, ca va pas être facile de t’aider… Faudra être un peu plus verbeux…
De plus, en général, tu récupère un timeout de ta base, si vraiment tu arrives pas à te connecter…
Pour un peu plus d’infos, tu peux aller jeter un coup d’oeil dans l’enterprise manager pour voir si y a une connexion qui se fait (auquel cas, hibernate se viande) ou pas (auquel cas, ca serait plus ta connexion à la DB)

Déjà, est-ce que l’url jdbc te semble correct ?

Je vais essayer de creuser un peu plus aujourd’hui.

[EDIT]
Après quelques tests, la connection via JDBC fonctionne :

[codebox]
package com.adeoservices.pmaggenwebadmin;

import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

/**

  • Test de la connection JDBC.

  • @author Loic DREUX
    /
    public class ConnectionTest extends TestCase {
    /
    *

    • Create the test case
    • @param testName
    •        name of the test case
      

    */
    public ConnectionTest(String testName) {
    super(testName);
    }

    /**

    • @return the suite of tests being tested
      */
      public static Test suite() {
      return new TestSuite(ConnectionTest.class);
      }

    /**

    • Test la connection JDBC.
      */
      public void testConnection() {
      Connection connection = null;

      try {
      // Recherche du driver
      Driver oracleDriver = new oracle.jdbc.OracleDriver();
      DriverManager.registerDriver(oracleDriver);

       // Connection
       connection = DriverManager.getConnection(
       		"jdbc:oracle:thin:@tmaggen:1521:pmag", "traitement",
       		"traitement");
      
       assertTrue(isValid(connection));
      

      } catch (SQLException e) {
      assertTrue(e.getMessage(), false);
      } finally {
      if (connection != null) {
      try {
      connection.close();
      } catch (Exception e) {
      e.printStackTrace();
      }
      }
      }
      }

    /**

    • Vérifie que la connection JDBC est valide.
    • @param connection la connection à tester
    • @return true si la connection est valide, false dans le cas contraire
      */
      public static boolean isValid(Connection connection) {
      if (connection == null) {
      return false;
      }
      ResultSet ping = null;
      try {
      if (connection.isClosed()) {
      return false;
      }
      ping = connection.createStatement().executeQuery(“SELECT 1”);
      return ping.next();
      } catch (SQLException sqle) {
      return false;
      } finally {
      if (ping != null) {
      try {
      ping.close();
      } catch (Exception e) {
      e.printStackTrace();
      }
      }
      }
      }
      }
      [/codebox]

En fait je n’ai pas bien configurer Hibernate, je vais donc réorienter mon post : comment configurer hibernate ? Actuellement j’ai une table User :

[codebox]
/*

  • Adeo Services
  • 2007
    */
    package com.adeoservices.pmaggenwebadmin.schema;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

/**

  • Un utilisateur du Portail Web

  • @author Loic DREUX
    /
    @Entity
    @Table(name=“T_UTI”)
    public class User implements Serializable{
    /
    *

    • Le login ldap.
      */
      @Column(name=“COD_UTI”)
      private String codUti;

    /**

    • Retourne le login ldap.
    • @return le login ldap
      */
      @Id
      public String getUti() {
      return this.codUti;
      }
      }
      [/codebox]

et mon fichier de configuration ressemble à ceci :

[codebox]

<?xml version='1.0' encoding='utf-8'?> oracle.jdbc.OracleDriver jdbc:oracle:thin:@tmaggen:1521:pmag traitement ****
    <property name="dialect">net.sf.hibernate.dialect.OracleDialect</property>
</session-factory>
[/codebox]

J’ai beau lire la documentation, j’ai du mal à comprendre comment indiquer à Hibernate de prendre en compte mon objet User.

j’utilise Nhibernate mais bon vu que c’est un portage j’imagine que la conf est là même.

Il te manque pas l’équivalent du dans ta config du session-factory?

De plus, même si ça n’a rien à voir avec ton problème, je conseil toujours fortement de passer par des fichiers de mapping plutôt que de « poluer » les classes avec des infos de mapping :slight_smile: . Ca favorise beaucoup plus un couplage faible entre domaine et accès aux données.

Effectivement, mon fichier de conf n’était vraiment pas complet, voici la dernière mise à jour qui règle pas mal de problème :

[codebox]

<?xml version='1.0' encoding='utf-8'?> oracle.jdbc.OracleDriver jdbc:oracle:thin:@tmaggen:1521:pmag traitement ****
    <!-- JDBC connection pool (use the built-in) -->
    <property name="connection.pool_size">1</property>
    
    <!-- SQL dialect -->
    <property name="dialect">org.hibernate.dialect.Oracle10gDialect</property>
    
    <!-- Enable Hibernate's automatic session context management -->
    <property name="current_session_context_class">thread</property>

    <!-- Disable the second-level cache  -->
    <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>

    <!-- Echo all executed SQL to stdout -->
    <property name="show_sql">true</property>

    <!-- Drop and re-create the database schema on startup -->
    <property name="hbm2ddl.auto">create</property>
    
    <session-factory>
        <mapping package="com.adeoservices.pmaggenwebadmin.schema"/>
        </--<mapping class="com.adeoservices.pmaggenwebadmin.schema.User"/>-->
    </session-factory>
</session-factory>

<!--<mapping resource="schema.hbm.xml"/>-->
[/codebox]

Maintenant, il me dit qu’il ne trouve pas la classe ‘org/hibernate/annotations/common/reflection/ReflectionManager’, alors que j’ai bien le package org.hibernate.annotation dans mon classes path. D’ailleurs, pour en revenir aux annotations plutôt qu’au mapping externe, il s’agit dans mon cas d’un petit projet externe donc je préfère utiliser des annotations car ça me semble plus facile et rapide à mettre en place plutôt que de maintenir à jour un fichier de mapping XML (il y a certes des outils pour faire ça, mais je n’ai pas le temps de les mettre en place).

Donc bref, je continue à chercher et merci pour votre aide.

Ce n’est pas ce jar là qu’il te faut. C’est celui là : hibernate-commons-annotations.jar (attention à la version que je link, j’ai rien testé avec celle là)

Aux dernières nouvelles, j’ai toutes les librairies, (merci LeGzo, je l’avais raté la hibernate-commons-annotations.jar)

Mais j’utilisais la classe HibernateUtil suivante :

[codebox]
package com.adeoservices.pmaggenwebadmin;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtil {
public static final SessionFactory sessionFactory;

static {
    try {
        // Création de la SessionFactory à partir de hibernate.cfg.xml
        sessionFactory = new Configuration().configure().buildSessionFactory();
    } catch (Throwable ex) {
        // Make sure you log the exception, as it might be swallowed
        System.err.println("Initial SessionFactory creation failed." + ex);
        throw new ExceptionInInitializerError(ex);
    }
}

public static final ThreadLocal session = new ThreadLocal();

public static SessionFactory getSessionFactory() {
    return sessionFactory;
}

}
[/codebox]

ce qui me donne l’erreur suivante

En toute logique après lecture de la documentation http://www.hibernate.org/hib_docs/annotati…/html/ch01.html, je l’ai remplacé par la classe :

[codebox] <?xml version='1.0' encoding='utf-8'?> oracle.jdbc.OracleDriver jdbc:oracle:thin:@tmaggen:1521:pmag traitement traitement
    <!-- JDBC connection pool (use the built-in) -->
    <property name="connection.pool_size">1</property>
    
    <!-- SQL dialect -->
    <property name="dialect">org.hibernate.dialect.Oracle10gDialect</property>
    
    <!-- Enable Hibernate's automatic session context management -->
    <property name="current_session_context_class">thread</property>

    <!-- Disable the second-level cache  -->
    <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>

    <!-- Echo all executed SQL to stdout -->
    <property name="show_sql">true</property>

    <!-- Drop and re-create the database schema on startup -->
    <property name="hbm2ddl.auto">create</property>
    
    <mapping class="com.adeoservices.pmaggenwebadmin.schema.User" />
</session-factory> 
[/codebox]

Tiens j’ai pas trop le temps de regarder en détail mais déjà mes propriétés dans mon fichier de config n’ont pas les mêmes valeurs :

take a look :

[codebox]


org.postgresql.Driver
jdbc:postgresql://localhost:5432/helloworld
postgres
postgres

	<property name="hibernate.hbm2ddl.auto">create</property>

	<property name="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</property>
	<!-- Use the C3P0 connection pool provider -->
	<property name="hibernate.c3p0.min_size">5</property>
	<property name="hibernate.c3p0.max_size">20</property>
	<property name="hibernate.c3p0.timeout">300</property>
	<property name="hibernate.c3p0.max_statements">50</property>
	<property name="hibernate.c3p0.idle_test_period">3000</property>
	<!-- Show and print nice SQL on stdout -->
	<property name="show_sql">false</property>
	<property name="format_sql">true</property>
	<!-- List of XML mapping files -->
	<mapping resource="model/Message.hbm.xml" />
</session-factory>

[/codebox]

Les machins c3p0 c’est pour avoir un pool de connexions hors contexte JEE peut être pas à utiliser dans ton cas.

euh l’avantage des mapper O/R n’est pas de mapper la base, mais bien de mapper les objets. Utiliser des technos objet et des mappers O/R pour continuer à réfléchir à partir d’un MCD… bah autant ne pas utiliser les technos objet, parce qu’un SGBD, ça sait pas faire d’héritage et de polymorphisme.

Hibernate est vraiment un excellent outil pour mettre en place une architecture en couche, mais ce n’est qu’un élément parmi tant d’autre. Je ne dis pas que c’est ton cas ZGoblin, mais je me méfie toujours des gens qui utilisent Hibernate ou Nhibernate comme « simple » driver d’accès aux données dans une archiecture pilotée par la base. Le fait que les objets doivent persister est une incidence technique, et la technique ne doit ni conditionner ni piloter le projet. Les mappers O/R nous sauvent la vie et nous évitant d’avoir à écrire nous même le mapping des objets au même titre qu’un Struts nous évite à avoir à écrire notre propre framework MVC.

Je veux bien te croire quand tu dis que Hibernate est un super outil qui fait bien plus que du simple accès au base. Mais moi c’est justement ce que je recherche, pourvoir éditer 2/3 tables sans me prendre la tête, et là c’est le drame, on t’insultes à chaque exécution avec des stacktrace de 3 pages :slight_smile: alors que moi je voulais juste ajouter et supprimer un utilisateur tous les 36 du mois.

Si ton besoin est juste d’éditer 2 3 tables sans te prendre la tête, alors hibernate n’est pas je pense la meilleure réponse :crying: C’est sortir l’artillerie lourde.

il y a finalement 4 grands patterns d’architecture d’accès aux données:

  • Table data Gateway (les datasets de .NET)
  • Row data Gateway (j’ai pas d’exemple ^^ )
  • Active Record (ActiveRecord en .NET)
  • Data Mapper (hibernate)

Dans ton cas, j’aurai tendance à dire que la réponse est ActiveRecord, mais n’étant pas un expert Java, je ne sais pas ce qu’il existe à ce niveau là.

Bon je sais tout ceci ne répond à tes questions d’origine, mais bon, c’est plus fort que moi je me sens toujours obligé de partir en live :slight_smile:

C’est la mise en place qui est douloureuse, apres c’est la fete du slip :slight_smile:

Oui mais tu dois savoir ce que c’est, au début on te demande un petit truc rapide qui permet d’éditer 2, 3 tables et voyant que ça marche bien on t’en demande un peu plus, puis encore un peu plus, et au final, tu es bien content d’avoir sortie l’artillerie lourde dès le début afin de ne pas remettre tout en cause et de pouvoir supporter les évolutions.

A tout hasard, est-ce que ça t’intéresse un projet eclipse de type HelloWorld pour éditer 2, 3 tables avec toutes les bonnes librairies et la config déjà faite? Parce que j’ai ça sous la main et si ça peut te permettre de te bootstrapper :slight_smile:

J’ai aussi le même en Hibernate/JPA de mémoire.

[quote=« LeGzo, post:14, topic: 46535 »]A tout hasard, est-ce que ça t’intéresse un projet eclipse de type HelloWorld pour éditer 2, 3 tables avec toutes les bonnes librairies et la config déjà faite? Parce que j’ai ça sous la main et si ça peut te permettre de te bootstrapper :slight_smile:

J’ai aussi le même en Hibernate/JPA de mémoire.[/quote]

Ca me sauverait la vie :crying:

Euh oui mais encore faut-il que l’artillerie lourde en question soit correctement déployée :slight_smile: Hibernate mal utilisé peut devenir une véritable horreur à maintenir quand le système grossi.
De plus, supporter les évolutions, c’est bien, mais je ne suis pas sur qu’Hibernate soit la baguette magique permettant de tout prévoir. Ce n’est qu’un outil technique, aussi bon soit-il, il ne va pas couvrir les évolutions fonctionnelles.

De plus, un de mes grands credo est « la base n’est pas le besoin ». Je ne pense pas ici que l’utilisateur a demandé à la base à éditer 2 3 tables? Il a du demander la possibilité d’entrer et modifier des utilisateurs. Les tables sont une incidence de la solution technique retenue. Gérer les évolutions sur le besoin de base ne passera peut être pas du tout par hibernate.

[quote=« BodySplash, post:16, topic: 46535 »]Euh oui mais encore faut-il que l’artillerie lourde en question soit correctement déployée :slight_smile: Hibernate mal utilisé peut devenir une véritable horreur à maintenir quand le système grossi.
De plus, supporter les évolutions, c’est bien, mais je ne suis pas sur qu’Hibernate soit la baguette magique permettant de tout prévoir. Ce n’est qu’un outil technique, aussi bon soit-il, il ne va pas couvrir les évolutions fonctionnelles.

De plus, un de mes grands credo est « la base n’est pas le besoin ». Je ne pense pas ici que l’utilisateur a demandé à la base à éditer 2 3 tables? Il a du demander la possibilité d’entrer et modifier des utilisateurs. Les tables sont une incidence de la solution technique retenue. Gérer les évolutions sur le besoin de base ne passera peut être pas du tout par hibernate.[/quote]

J’ai du mal à te suivre dans toutes tes explications :crying:.

Même si je suis d’accord dans l’ensemble, il faut voir le théorique et la pratique. Car lorsque je suis arrivé sur ce projet, la base de données était déjà faite (avec un beau MCD merise :cry:), je ne devais m’occuper que du développement, donc forcément, les choix techniques ont déjà été pris des mois auparavant et il faut faire avec, ce qui me va bien car la base de données à été bien conçu. Et je continue de penser que Hibernate correspond très bien à mon cas. Il peut faire beaucoup plus ? Ca tombe bien, qui peut le plus, peu le moins donc.

En plus, je ne suis pas encore à l’aise avec Hibernate, il y a aussi un aspect auto-formation que je n’avais pas évoqué, le fait d’utiliser Hibernate tranquillement va me permettre de me faire la main, de comprendre les principes et de pouvoir par la suite utiliser pleinement avec de l’objet et tout :stuck_out_tongue:

Pour conclure, ce matin, j’ai réussi à faire passer mon test unitaire de connection Hibernate, voici le code en question :

try { Configuration configuration = new AnnotationConfiguration(); configuration.configure(); sessionFactory = configuration.buildSessionFactory(); } catch (Throwable ex) { throw new ExceptionInInitializerError(ex); }

Il manqué le configuration.configure(); qui n’était dans l’exemple de la documentation, donc mon fichier de conf n’était pas pris en compte. Tout bête mais fallait le voir pour quelqu’un qui n’est pas encore à l’aise avec l’API d’hibernate.

[quote=« ZGoblin, post:17, topic: 46535 »]J’ai du mal à te suivre dans toutes tes explications :crying:.

Même si je suis d’accord dans l’ensemble, il faut voir le théorique et la pratique. Car lorsque je suis arrivé sur ce projet, la base de données était déjà faite (avec un beau MCD merise :cry:), je ne devais m’occuper que du développement, donc forcément, les choix techniques ont déjà été pris des mois auparavant et il faut faire avec, ce qui me va bien car la base de données à été bien conçu. Et je continue de penser que Hibernate correspond très bien à mon cas. Il peut faire beaucoup plus ? Ca tombe bien, qui peut le plus, peu le moins donc.

En plus, je ne suis pas encore à l’aise avec Hibernate, il y a aussi un aspect auto-formation que je n’avais pas évoqué, le fait d’utiliser Hibernate tranquillement va me permettre de me faire la main, de comprendre les principes et de pouvoir par la suite utiliser pleinement avec de l’objet et tout :P[/quote]

Bon on déborde un peu, faut voir si on continue PM/nouveau thread ou ailleurs :slight_smile:

Je ne parle pas de théorie, ce que je dis, je le met en pratique tous les jours. Tu arrives sur un projet qui a déjà une base? Et alors, il ne faut pas se laisser limiter par d’anciens choix, sinon les applications n’évoluent jamais. C’est limite plus intéressant justement de reprendre un projet en cours et essayer de « l’objectiser ».

Introduire hibernate dans ce projet est peut être une bonne chose, mais il faut que ce soit justifier architecturalement parlant. Les data mapper servent à quoi? A palier plus ou moins bien le gouffre qu’il existe entre la philo objet et le relationnel. Bah oui, un SGBD ne gère pas l’héritage, ne gère pas le comportement (bah une classe c’est gérer les données ET le comportement), ne gère qu’un seul type d’association.
Si ton objectif et d’essayer de penser objet et ensuite faire persister ces objets en base, alors hibernate va te sauver la vie niveau gain de temps.
Apprendre hibernate juste comme ça, pour connaitre, sans être sûr de la direction que tu veux faire prendre au projet où à l’architecture, c’est dangereux.

Bref tout ce que je dis, je ne le sors pas de nul part. Non seulement je met tout ça en pratique, mais je m’appuie aussi sur le principe de domain driven design.

Il y a aussi le coté relationnel et client/prestataire qu’il faut prendre en compte. Je ne suis pas chef de projet et je suis sur ce projet en tant que développeur. Les personnes qui travaillent avec moi travaillent encore “à l’ancienne”, ils n’ont pas l’habitude d’utiliser de l’objet, le logging, un IDE, les tests unitaires, des repository de sources, des scripts de compilation et de distributions, … Je ne peux pas arriver avec mes grands sabots et dire à tous : “Maintenant, c’est comme ça qu’il faut travailler pour bien faire les chose”, il faut être assez diplomate et montrer les avantages de tous ces outils, et même une fois qu’ils ont vues et compris tous les avantages, je ne peux pas les obliger à utiliser ces méthodes de travails car il n’ont pour la plupart pas le temps ni les connaissances, bref il faut faire la transition en douceur.

Et puis je ne vois pas l’interrêt de passer le model en tout objet pour le plaisir, il y a de l’existant qui tourne sur ce projet et il n’est pas question de remettre ça en cause.

Maintenant, c’est vrai que sur un nouveau projet où je serais totalement libre des mes choix techniques, j’utiliserai à 100% de l’objet, avec surement du Java et de l’hibernate.

Pour en revenir au sujet, c’est à dire la bibliothèque Hibernate, j’ai un soucis, mon script de test fonctionne parfaitement, mais losque j’essaye de récupérer des objets dans mon interface Swing, ca bloque sur cette partie :

22 nov. 2007 10:32:35 org.hibernate.connection.DriverManagerConnectionProvider configure INFO: using driver: oracle.jdbc.OracleDriver at URL: jdbc:oracle:thin:@tmaggen1:1521:pmag 22 nov. 2007 10:32:35 org.hibernate.connection.DriverManagerConnectionProvider configure INFO: connection properties: {user=bu015, password=****}

N’y aurait-il pas un problème de thread ?

Le code en question :

Session session = HibernateUtil.getSessionFactory().getCurrentSession(); session.beginTransaction(); List<User> result = session.createQuery("from User").list(); session.getTransaction().commit();

à noter que j’utilise ce code à l’aide d’un SwingWorker pour ne pas bloquer l’interface.