[Hibernate] Insert multi row

Résolu
cptpingu
Messages postés
3834
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
20 octobre 2021
- 4 juin 2009 à 18:34
 SankaWeon - 19 juin 2018 à 13:49
Bonjour.

J'essaie actuellement d'insérer de multiple lignes dans une table, en utilisant Hibernate.
Pour optimiser, je veux éviter de faire un save dans ma boucle. Je me suis donc dis que j'allais construire la requête à la main, et exécuter une requête SQL native.
Malheureusement, ça ne fonctionne pas. Voici un morceau simplifié de mon code qui pose problème:

        SQLQuery query = session.createSQLQuery("INSERT INTO trans2_reviews(raw_id, "
                        + "hotel_id, locale, review_date, transformed_date, translation_status, "
                        + "transformed_text) VALUES(34901, 5166, 'en', '2008-08-16 00:00:00.0', "
                        + "'Thu Jun 04 16:43:44 CEST 2009', 'SOURCE', 'Pouet.')");
        query.executeUpdate();

Et l'erreur:
> Could not execute native bulk manipulation query

J'ai fait beaucoup de recherche, en essayant différente méthodes. Aucune ne fonctionne (en HQL Il n'y a pas INSERT INTO ... VALUES, en critéria, je n'ai rien trouvé de concluant, et les batch insert ne répondent pas à mon besoin). Auriez vous une solution fonctionnelle à ce problème ?

Je vous remercie.

13 réponses

cptpingu
Messages postés
3834
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
20 octobre 2021
125
3 août 2009 à 15:12
J'ai oublié de vous répondre...

J'ai résolu mon problème en réalisant un script shell, qui balance des requêtes SQL. Pour un script de transformation hors code principal, c'est tout à fait acceptable.

Merci à tous.
3
cs_DARKSIDIOUS
Messages postés
15814
Date d'inscription
jeudi 8 août 2002
Statut
Membre
Dernière intervention
4 mars 2013
131
4 juin 2009 à 19:21
Salut,

Quand tu décide d'utiliser un framework, il faut l'utiliser jusqu'au bout, sinon c'est le meilleur moyen pour rendre un compte immaintenable et bourré de bug !

Il est toujours plus facile de debugguer un code qui est homogène plutôt que de debugguer un code qui contient de multiples technologies...
0
cptpingu
Messages postés
3834
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
20 octobre 2021
125
4 juin 2009 à 19:39
Il y a la théorie et la réalité.
Je déteste devoir utiliser ce genre de bidouille, mais il n'est parfois pas possible de faire autrement. Je bosse sur une table absolument gigantesque (plusieurs millions d'entrées) qui doit en remplir une autre qui sera au moins 10 fois plus grande, tout en ayant de fortes contraintes de temps. De plus, ce n'est pas une partie du projet principal, mais un simple script de migration.
J'ai déjà écrit le script, avec du hibernate "propre", mais c'est encore beaucoup trop lent. La dernière optimisation qu'il me reste à faire, est celle d'insérer des lignes par paquets, et non une par une (concaténation de string pour former une seule requêtes, plus rapide que de faire un save dans une boucle). D'où le sujet de ma question.
0
cs_DARKSIDIOUS
Messages postés
15814
Date d'inscription
jeudi 8 août 2002
Statut
Membre
Dernière intervention
4 mars 2013
131
4 juin 2009 à 20:39
A ce moment là utilise du pur JDBC et laisse de côté hibernate.

Fais un prepareStatement avec une Connection JDBC, et exécute tes requêtes d'insertions.

Cependant, je doute que tu obtienne un gain extrêmement important : Hibernate est vraiment très optimisé, et se rapproche des performances de JDBC, après, c'est le connector JDBC qui peut faire la différence : un connector natif pour l'OS utilisé étant toujours plus rapide qu'un connector codé en java !
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
cptpingu
Messages postés
3834
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
20 octobre 2021
125
4 juin 2009 à 21:14
Deux questions:
- Hibernate ne permet donc pas l'insertion de row multiple ?
- Si prends du JDBC, il faudra donc que je fasse un connecteur par OS ?
0
cs_DARKSIDIOUS
Messages postés
15814
Date d'inscription
jeudi 8 août 2002
Statut
Membre
Dernière intervention
4 mars 2013
131
4 juin 2009 à 21:32
Si bien sûr que si, hibernate permet de quasiment tout faire, sinon, il ne serait pas autant utilisé par les entreprises, mais vu que d'après toi même avec hibernate, tu n'es pas satisfait des performances et que tu préfères faire cà avec une requête SQL, je te donne les pistes.

Voir ceci par exemple pour faire des insertions multiples "optimisées" en hibernate :
http://www.javabeat.net/tips/81-batch-insert-in-hibernate.html
0
cptpingu
Messages postés
3834
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
20 octobre 2021
125
4 juin 2009 à 22:24
J'ai fait beaucoup de recherche sur le net, et j'ai déjà lu ce lien.
Il ne réponds pas à mon besoin du tout, bien au contraire. Il sert à optimiser l'espace mémoire en flushant les requêtes. Je cherche justement à regrouper les requêtes, pour en faire le moins possibles. Néanmoins, je te remercie pour cette indication.
Si hibernate est capable de faire une insertion multi row, c'est à dire si celui ci est capable de générer une requête du type:
INSERT INTO table(a,b, c) VALUES(0,1,2,),(0,1,2,),(0,1,2,)(regroupement des values pour ne faire qu'une requête), alors je suis super intéressé.
Hibernate est un très bon produit, et je ne doute pas de ses performances, mais ma question initiale ne dit pas que celui ci ne convient pas, mais que je n'arrive pas à réaliser ce que je viens de décrire avec ce framework.
0
Bonjour cptpingu, je ressort une vielle question mais la réponse à ta question m'intéresse beaucoup aujourd'hui, je suis sur un même problème et je ne trouve toujours rien aujourd’hui pour y répondre. As-tu trouvé une réponse à ton problème d'insert avec hibernate ou du tout ? merci
0
cs_DARKSIDIOUS
Messages postés
15814
Date d'inscription
jeudi 8 août 2002
Statut
Membre
Dernière intervention
4 mars 2013
131
5 juin 2009 à 08:01
http://docs.jboss.org/hibernate/stable/core/reference/en/html/batch-direct.html

Voir surtout la fin :
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();

String hqlInsert = "insert into DelinquentAccount (id, name) select c.id, c.name from Customer c where ...";
int createdEntities = s.createQuery( hqlInsert )
.executeUpdate();
tx.commit();
session.close();

Est-ce que cela correspond à ton problème ?
0
kirua12
Messages postés
1155
Date d'inscription
samedi 17 janvier 2004
Statut
Membre
Dernière intervention
29 avril 2011
8
5 juin 2009 à 11:04
Salut,

hibernate a une vision objet et non table (c'est l'intérêt des framework de persistence). Donc lors de l'insertion, en version de base, c'est objet par objet.
Après l'optimisation dans ce cas, c'est le mode batch. On envoie n requêtes en 1 seule fois. Tu veux faire 1 requête avec n valeurs. Est ce vraiment différent ? As tu mesurer les performances ? c'est une simple question, j'ai toujours joué avec le mode batch et les perfs sont très bonnes (sauf dans le cas d'héritage entre tables où il faut bidouiller un peu) : par ex : qq centaines de milliers de lignes insérées en 2s. (oracle 10g)
0
hakker
Messages postés
23
Date d'inscription
vendredi 15 février 2008
Statut
Membre
Dernière intervention
20 février 2010

3 août 2009 à 14:32
hi dsl pour l'interruption. je vous demander est ce que on peu vraiment faire insertion ds la base sans faire un réquete on creer un objet et on y stock les nouvelles info désirer et puis avec un save. voila le pour mieux me comprenez:
public class MailDAO {
protected Session session;

public MailDAO(){this.session=this.session = HibernateUtil.getSessionFactory().getCurrentSession();}

public MailDAO(Session session){this.session=session;}

public void insert(BoiteMail mail) throws RollbackException, HeuristicMixedException{
Transaction tx;
try{
tx=(Transaction) session.beginTransaction();
session.save(mail);
tx.commit();
System.out.println("Done");

}
catch (Exception ex){ex.printStackTrace();}
finally{session.flush();
session.close();}
}
}

bon l'exécution marche sava mé ma table est vide c'est à dire y a pa d'insertion!
et dsl encore une fois pour le dérangement mercii d'avance.
nice working with u all guz!!
0
hakker
Messages postés
23
Date d'inscription
vendredi 15 février 2008
Statut
Membre
Dernière intervention
20 février 2010

3 août 2009 à 23:50
salut tout le monde vous pouvez m'aider?

nice working with u all guz!!
0
kirua12
Messages postés
1155
Date d'inscription
samedi 17 janvier 2004
Statut
Membre
Dernière intervention
29 avril 2011
8
4 août 2009 à 09:43
Pour hakker : pose ta question dans ton propre topic et donne le maximum de détail
0
hakker
Messages postés
23
Date d'inscription
vendredi 15 février 2008
Statut
Membre
Dernière intervention
20 février 2010

4 août 2009 à 10:39
salut dsl kiura12 parce que j'ai pas donné ma question car j'ai déja écrir mon pb dans la page précedente mais c'est pa grave je vais le récrire.

hi dsl pour l'interruption. je vous demander est ce que on peu vraiment faire insertion dans la base sans faire une réquete.just on creer un objet et on y stock les nouvelles info désirer et puis avec un save. voila le pour mieux comprendre:
// ce code fais une insertion d 'un objet Mail dans la base BoiteMail.//

public class MailDAO {
protected Session session;

public MailDAO(){this.session=this.session = HibernateUtil.getSessionFactory().getCurrentSession();}

public MailDAO(Session session){this.session=session;}

public void insert(BoiteMail mail) throws RollbackException, HeuristicMixedException{
Transaction tx;
try{
tx=(Transaction) session.beginTransaction();
session.save(mail);
tx.commit();
System.out.println("Done");

}
catch (Exception ex){ex.printStackTrace();}
finally{session.flush();
session.close();}
}
}

bon l'exécution marche sava mé ma table est vide c'est à dire y a pa d'insertion!
et désolée encore une fois pour le dérangement mercii d'avance.

nice working with u all guz!!
0