[Hibernate] Insert multi row [Résolu]

cptpingu 3794 Messages postés dimanche 12 décembre 2004Date d'inscription 10 juin 2018 Dernière intervention - 4 juin 2009 à 18:34 - Dernière réponse :  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.
Afficher la suite 

Votre réponse

14 réponses

Meilleure réponse
cptpingu 3794 Messages postés dimanche 12 décembre 2004Date d'inscription 10 juin 2018 Dernière intervention - 3 août 2009 à 15:12
3
Merci
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.

Merci cptpingu 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 84 internautes ce mois-ci

Commenter la réponse de cptpingu
cs_DARKSIDIOUS 15838 Messages postés jeudi 8 août 2002Date d'inscription 4 mars 2013 Dernière intervention - 4 juin 2009 à 19:21
0
Merci
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...
Commenter la réponse de cs_DARKSIDIOUS
cptpingu 3794 Messages postés dimanche 12 décembre 2004Date d'inscription 10 juin 2018 Dernière intervention - 4 juin 2009 à 19:39
0
Merci
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.
Commenter la réponse de cptpingu
cs_DARKSIDIOUS 15838 Messages postés jeudi 8 août 2002Date d'inscription 4 mars 2013 Dernière intervention - 4 juin 2009 à 20:39
0
Merci
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 !
Commenter la réponse de cs_DARKSIDIOUS
cptpingu 3794 Messages postés dimanche 12 décembre 2004Date d'inscription 10 juin 2018 Dernière intervention - 4 juin 2009 à 21:14
0
Merci
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 ?
Commenter la réponse de cptpingu
cs_DARKSIDIOUS 15838 Messages postés jeudi 8 août 2002Date d'inscription 4 mars 2013 Dernière intervention - 4 juin 2009 à 21:32
0
Merci
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
Commenter la réponse de cs_DARKSIDIOUS
cptpingu 3794 Messages postés dimanche 12 décembre 2004Date d'inscription 10 juin 2018 Dernière intervention - 4 juin 2009 à 22:24
0
Merci
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.
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
Commenter la réponse de cptpingu
cs_DARKSIDIOUS 15838 Messages postés jeudi 8 août 2002Date d'inscription 4 mars 2013 Dernière intervention - 5 juin 2009 à 08:01
0
Merci
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 ?
Commenter la réponse de cs_DARKSIDIOUS
kirua12 1155 Messages postés samedi 17 janvier 2004Date d'inscription 29 avril 2011 Dernière intervention - 5 juin 2009 à 11:04
0
Merci
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)
Commenter la réponse de kirua12
hakker 23 Messages postés vendredi 15 février 2008Date d'inscription 20 février 2010 Dernière intervention - 3 août 2009 à 14:32
0
Merci
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!!
Commenter la réponse de hakker
hakker 23 Messages postés vendredi 15 février 2008Date d'inscription 20 février 2010 Dernière intervention - 3 août 2009 à 23:50
0
Merci
salut tout le monde vous pouvez m'aider?

nice working with u all guz!!
Commenter la réponse de hakker
kirua12 1155 Messages postés samedi 17 janvier 2004Date d'inscription 29 avril 2011 Dernière intervention - 4 août 2009 à 09:43
0
Merci
Pour hakker : pose ta question dans ton propre topic et donne le maximum de détail
Commenter la réponse de kirua12
hakker 23 Messages postés vendredi 15 février 2008Date d'inscription 20 février 2010 Dernière intervention - 4 août 2009 à 10:39
0
Merci
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!!
Commenter la réponse de hakker

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.