Affichage des articles dont le libellé est hibernate. Afficher tous les articles
Affichage des articles dont le libellé est hibernate. Afficher tous les articles

mercredi 26 mai 2010

Transaction explicites sous Spring et JPA dans les applications Batch

Il m'a été difficile d'utiliser une application de traitement batch utilisant Hibernate, JPA. En utilisant des transactions explicite.

J'avais le message "org.hibernate.SessionException: Session is closed!"

Pour démmarrer le contexte transactionnel, j'ai utilisé les lignes suivantes


DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setName("MaTransaction");
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
/** pour démarrer le context transactionnel */
transactionManager.getTransaction(def);


Comment économiser de la mémoire :
- Faire des commit intermédiaires

Comment gagner de la vitesse :
- Faire des insertions et des select dans une table est une opération couteuse (car le recalcul des index prend de plus en plus de temps)

mardi 28 octobre 2008

Generators in Hibernate Annotations

Identity generator in hibernate

@Id 
@GeneratedValue (strategy=GenerationType.IDENTITY)
@Column(name = "REJ_CDN")
int id;



* Tested with Sybase

Increment generator in hibernate

@Id
@GeneratedValue(generator = "autoincrement")
@GenericGenerator(strategy = "increment", name = "autoincrement")
@Column(name = "MYID")
Integer id;


* Tested with Sybase

mardi 21 octobre 2008

No Dialect mapping for JDBC type: -1

org.hibernate.MappingException: No Dialect mapping for JDBC type: -1

Was provoked by :

String query = "SELECT * FROM MYTABLE WHERE MYID=? "
+ "AND MYCRITERIA >= ?";
SQLQuery sqlQuery;
sqlQuery = session.createSQLQuery(query);
sqlQuery.setString(0, code);
sqlQuery.setDate(1, date);
List<string> ports = sqlQuery.list();


The cause was I could not to use the *, I had to specify each field instead.

jeudi 2 octobre 2008

Effectuer une requête simple à l'aide d'Hibernate

Hibernate, même s'il est particulièrement à l'aise sur les problème d'informatique de gestion (Lecture/Modification d'enregistrements), ne peut se substituer à toutes les utilisations qui sont faite lors de SQL.

C'est particulièrement vrai lorsqu'on se sert de fonctions statistique, telle que SUM( ) ou COUNT(*) Dans ces cas une requête simple est préférable. Hibernate offre la possibilité de faire des requêtes simples par la fonction createSQLQuery("SELECT SUM(MACOL) FROM MATABLE").

Dans ce cas, inutile de "voler" la connexion hibernate pour s'en servir à sa place pour se servir des APIS fournies par JAVA, mieux vaut se servir des APIS hibernate.

Voici un exemple :

SQLQuery query = session
.createSQLQuery(
"SELECT count(*) FROM MATABLE WHERE MACOL1=? AND MACOL2=?");
query.addScalar("NOMBRE", Hibernate.FLOAT);
query.setDate(0, dateFinMois);
query.setInteger(1, commande.getId());
Float consommeEnFinDeMois = (Float) query.list().get(0);



L'utilisation de la fonction query.setScalar permet de typer la réponse.
query.setInteger(0,x) permet de fournir des paramètres à la requête.

mardi 8 avril 2008

Problème de synchronisation avec hibernate

Lors de l'appel de saveOrUpdate() or update() j'ai une NonUniqueObjectException.

La session utilise un cache entre la persistance et l'objet instance, ce cache est unique (Il se manifeste par les proxy cglig). L'appel de saveOrUpdate determine premièrement si cet objet existe en base, si oui, il construit son proxy CGLIB, ainsi hibernate sait si cet objet existe ou non en base de données. La comparaison de l'objet proxié et de l'objet que nous tentons d'insérer (Non proxié) provoque une incohérence et retourne l'erreur ci dessus.

L'utilisation de la fonction saveOrUpdate() ne sert pas comme on le croit d'abord, à permettre de procéder à des insert ou des update en aveugle.

La solution de ce problème est soit de connaitre l'état de l'objet avant de faire l'insertion en base. (Ce qui diminue notablement le charme de la fonction saveOrUpdate) soit d'utiliser la fonction merge, qui permet de cloné un objet sur son proxy.

marge prend en argument un objet non proxié et retourne un objet proxié clone exact de l'objet passé en argument.

mardi 11 décembre 2007

Hibernate session en multithread

J'utilise plusieurs threads pour la requête affichage de liste dans une application WEB. Lorsque je lance une requête en servant de la session Hibernate (partagée par les différents threads) j'obtiens le message suivant :
Exception in thread "Thread-41" org.hibernate.HibernateException: Not able to obtain connection
at
org.hibernate.jdbc.ConnectionManager.getConnection(ConnectionManager.java:113)

Le forum http://forums.hibernate.org/viewtopic.php?t=945337 suggère de passer dans un mode transactionnel, mais cela ne fonctionne pas dans mon cas. Il suggère également de laisser spring la possibilité de créer des connexions sur les threads qui en ont le besoin à l'aide de l'option allowCreate

à true ou bien de faire des requête callback.

Réponse :

La session hibernate gèe une seule connection et n'est pas thread safe : on ne peut pas partager une instance de session par plusieurs threads à moins d'utiliser les mécanismes de synchronisation.

C'est la même chose pour une connection JDBC : on ne peut pas avoir un thread qui lit les résultats d'une requête tandis qu'un autre tente de lancer un autre select sur la
même connection.


Tu peux faire rendre ton code thread safe si ton cas d'utilisation le permet en utilisant le mot clef synchronized.

// un seul thread à la fois peut exécuter ce code
synchronized {

// mon code

}

ou

synchronized(maSession) {
// mon code

}