Why do I get org.hibernate.HibernateException: No

2020-02-09 00:46发布

I'm writing a simple project, a business app written in Swing, using Hibernate for back-end. I come from Spring, that gave me easy ways to use hibernate and transactions. Anyway I managed to have Hibernate working. Yesterday, while writing some code to delete a bean from DB, I got this:

org.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions

The deletion code is simply:

    Session sess = HibernateUtil.getSession();
    Transaction tx = sess.beginTransaction();
    try {
        tx.begin();
        sess.delete(ims);
    } catch (Exception e) {
        tx.rollback();
        throw e;
    }
    tx.commit();
    sess.flush();

and my HibernateUtil.getSession() is:

    public static Session getSession() throws HibernateException {
        Session sess = null;
        try {
            sess = sessionFactory.getCurrentSession();
        } catch (org.hibernate.HibernateException he) {
            sess = sessionFactory.openSession();
        }
        return sess;
    }

additional details: I never close a hibernate session in my code, just on application closing. Is this wrong? Why do I get this on delete (only for that bean, others do work), and I don't on other operations (Insert, query, update)?

I read around and I tried to modify my getSession method simply in a sessionFactory.getCurrentSessionCall(), but I got: org.hibernate.HibernateException: No CurrentSessionContext configured!

Hibernat conf:

<hibernate-configuration>
    <session-factory >
    <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
    <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
    <property name="hibernate.connection.url">jdbc:mysql://localhost/joptel</property>
    <property name="hibernate.connection.username">root</property>
    <property name="hibernate.connection.password">******</property>
    <property name="hibernate.connection.pool_size">1</property>
    <property name="show_sql">true</property>
    <property name="hibernate.hbm2ddl.auto">update</property>


    ..mappings..

    </session-factory>
</hibernate-configuration>

3条回答
孤傲高冷的网名
2楼-- · 2020-02-09 01:24

I wanted to ask you one thing, why are you trying to use "OpenSession" method?

public static Session getSession() throws HibernateException {         
   Session sess = null;       
   try {         
       sess = sessionFactory.getCurrentSession();  
   } catch (org.hibernate.HibernateException he) {  
       sess = sessionFactory.openSession();     
   }             
   return sess;
} 

You don't have to call openSession(), because getCurrentSession() method is always returns current session (Thread in case if you have configured it to be).

I got it!... You have to specify current context in your hibernate.cfg.xml file

it should be:

<property name="hibernate.current_session_context_class">thread</property>
查看更多
够拽才男人
3楼-- · 2020-02-09 01:45

No CurrentSessionContext configured

Read the reference guide on Contextual Sessions. You're required to configure some provided or custom strategy for this. In a hibernate.cfg.xml, you'd configure it with

<property name="hibernate.current_session_context_class">...</property>

You'd probably want to use "thread" as the value to get per-thread sessions. When using Spring, it automatically sets this to a SpringSessionContext, allowing Spring to easily integrate Hibernate with its transaction management framework.

I come from Spring, that gave me easy ways to use hibernate and transactions.

If you're familiar with Spring, why aren't you using it to manage Hibernate here? You must already know how simple and foolproof it makes it.

I never close a hibernate session in my code, just on application closing. Is this wrong?

Yes, this is very wrong. Every session not closed is an open database connection, so your app is currently hemorrhaging connections.

Illegal attempt to associate a collection with two open sessions

That means exactly what it says. You tried to do some persistence operation (save(), update(), delete()) on something that was already associated to a different session. That's what will happen when you go randomly opening new sessions whenever, which is what's happening since SessionFactory.getCurrentSession() will always fail when no "current session context" is set. In general, never open a session just because one wasn't already there. You need to have well-defined strategies for opening and closing sessions and never let anything open a session outside of these "strategies". That's a sure path to resource leaks and errors like the one you've encountered.

查看更多
迷人小祖宗
4楼-- · 2020-02-09 01:47

I faced the same problem when I am working on a portal where I am using spring remoting with hibernate. This kind of problem arise only if when the called service method contains multiple DAO calls that hit database with hibernate session.

And the solution is set the @Transaction annotation for those methods with multiple DAO calls. (Implies all the DOA calls with in this method should be under one transaction.)

查看更多
登录 后发表回答