72 votes

Contrôler la session hibernate (quand la fermer manuellement)

Je suis nouveau dans Hibernate, après avoir lu l'api et le tutoriel d'Hibernate, il semble que la session doit être fermée lorsqu'elle n'est pas utilisée.

Comme ça :

Session sess=getSession();
Transcration tx=sess.beginTranscration();
//do something using teh session
sess.save(obj);
tx.commit();
sess.close;

Je n'ai aucun doute quant à son utilisation dans une application autonome. Cependant, je ne suis pas sûr de l'utiliser dans une application web.

Par exemple, j'ai une servlet : TestServlet pour recevoir les paramètres du client, puis j'appelle un gestionnaire pour demander quelque chose en fonction des paramètres, comme ceci :

class TestServlet{
  doGet(HttpServletRequset,httpServletResponse){
    String para1=request.getParam...();
    String para2=.....
    new Manager().query(para1,para2);
  }
}

class Manager{
  public String query(String pa1,String pa2){
    Session=....// get the session
    //do query using para1 and 1
    session.close() //Here, I wonder if I should close it.
  }
}

Dois-je fermer la session dans la méthode d'interrogation ?

Depuis que quelqu'un m'a dit que la session dans Hibernate est juste comme la connexion dans JDBC. Donc l'ouvrir et le fermer si fréquemment est la bonne méthode ?

BTW, est-ce que tx.commit() est nécessaire à chaque fois ?

De même, quel est le problème de threads lié à l'utilisation de la session dans la servlet, puisque j'ai vu que la session n'est pas threadée dans l'api.

129voto

Pascal Thivent Points 295221

Je suis nouveau dans Hibernate, après avoir lu l'API d'Hibernate et le tutoriel, il semble que la session doit être fermée lorsqu'elle n'est pas utilisée.

Il doit être fermé lorsque vous avez terminé (mais cela peut être fait automatiquement pour vous comme nous le verrons).

Je n'ai aucun doute quant à son utilisation dans une application autonome. En revanche, je ne suis pas certain de pouvoir l'utiliser dans une application Web.

Eh bien, comme expliqué dans la section 11.1.1. Unité de travail de la documentation, le site le plus courant dans une application client/serveur multi-utilisateurs est session-par-demande .

Par exemple, j'ai une servlet:TestServlet pour recevoir les paramètres du client, puis j'appelle un Manager pour interroger quelque chose en fonction des paramètres : comme ceci (...) Dois-je fermer la session dans la méthode d'interrogation ?

Tout dépend de la façon dont vous obtenez la session.

  • si vous utilisez sessionFactory.getCurrentSession() vous obtiendrez une "session actuelle" qui est liée au cycle de vie de la transaction et sera automatiquement vidée et fermée lorsque la transaction se terminera (validation ou retour en arrière).
  • si vous décidez d'utiliser sessionFactory.openSession() vous devrez gérer vous-même la session, la vider et la fermer "manuellement".

Pour mettre en œuvre un session-par-demande préfèrent la première approche (beaucoup plus facile et moins verbeuse). Utilisez la deuxième approche pour implémenter longues conversations .

La page wiki Sessions et transactions est un bon complément à la documentation sur ce sujet.

BTW, est-ce que tx.commit() est nécessaire à chaque fois ?

Vous pourriez vouloir lire L'accès non transactionnel aux données et le mode auto-commit. pour clarifier certaines choses mais, pour faire simple, votre code Hibernate doit être exécuté au sein d'une transaction et je vous suggère d'utiliser des limites de transaction explicites (c'est-à-dire explicites beginTransaction et commit ).

De même, quel est le problème de threads lié à l'utilisation de la session dans la servlet, puisque j'ai vu que la session n'est pas threadée dans l'api.

Il suffit de ne pas en faire une variable d'instance de la servlet et vous n'aurez aucun problème.

Références

0 votes

Merci pour votre réponse. Maintenant, je décide de créer une classe statique HibernateUtil qui peut retourner la session par getCurrentSession(), puis j'appelle l'HibernateUtil pour obtenir une session à un autre endroit. Est-ce que c'est correct ?

0 votes

Aussi, chaque session par requet Je me demande si cela n'entraînera pas une baisse de performance, car si je n'utilise pas Hibernate, j'utiliserai un ConnectionPool.

6 votes

@hguser : Si vous n'utilisez pas EJB ou Spring, alors oui, optez pour une classe HibernateUtils. Et non, obtenir une session n'est pas une opération coûteuse et n'est pas un problème de performance, ce n'est pas pire que d'obtenir une connexion à partir du pool.

2voto

user6069813 Points 31

Si vous obtenez une session par le biais de sessionFactory.openSession() alors vous devez le fermer à l'extérieur . L'ouverture d'une session pendant une période non prévue peut entraîner des fuites de données. De plus, cela peut constituer une invitation à la menace de sécurité des applications Web.

1voto

AnirbanDebnath Points 836

Nous pouvons utiliser ThreadLocal .

public class MyUtil {
private static SessionFactory sessionFactory;
private static ServiceRegistry serviceRegistry;
private static final ThreadLocal<Session> threadLocal;

static {
try {
    Configuration configuration = new Configuration();
    configuration.configure();
    serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
    sessionFactory = configuration.buildSessionFactory(serviceRegistry);
    threadLocal = new ThreadLocal<Session>();

    } catch(Throwable t){
      t.printStackTrace();
      throw new ExceptionInInitializerError(t);
    }
}
public static Session getSession() {
    Session session = threadLocal.get();
    if(session == null){
        session = sessionFactory.openSession();
        threadLocal.set(session);
    }
    return session;
}

public static void closeSession() {
    Session session = threadLocal.get();
    if(session != null){
    session.close();
    threadLocal.set(null);
    }
}

public static void closeSessionFactory() {
    sessionFactory.close();
    StandardServiceRegistryBuilder.destroy(serviceRegistry);
   }
}

Ici, le SessionFactory est initialisé une seule fois à l'aide du bloc statique. Par conséquent, chaque fois que le main fait un appel à getSession() la présence de l'objet de la Session est d'abord vérifiée dans la base de données de la Session. threadLocal objet. Par conséquent, ce programme assure la sécurité des fils. Après chaque opération, closeSession() fermera la session et définira le threadLocal à null. Enfin, appelez le closeSessionFactory() .

1voto

Virendra khade Points 59

Une session est ouverte lorsque getCurrentSession() est appelé pour la première fois et fermé lorsque la transaction se termine.

Cela crée une toute nouvelle session si elle n'existe pas ou utilise une session existante si elle existe déjà. Il est automatiquement configuré avec les attributs auto-flush et auto-close en tant que moyens vrais. Session sera automatiquement vidée et fermée.

Ff vous utilisez getCurrentSession() il n'est pas nécessaire de fermer la connexion si vous essayez de le faire, vous rencontrerez une exception.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X