alonp
alonp

Reputation: 1337

Getting "org.hibernate.TransactionException: nested transactions not supported" error when deleting

When running removeUserFromConference method getting this exception:

04/06/2012 00:20:48 org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [ConferenceServlet] in context with path [/conf4u] threw exception
org.hibernate.TransactionException: nested transactions not supported
    at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.begin(AbstractTransactionImpl.java:152)
    at org.hibernate.internal.SessionImpl.beginTransaction(SessionImpl.java:1396)
    at sun.reflect.GeneratedMethodAccessor39.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.hibernate.context.internal.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:352)
    at $Proxy12.beginTransaction(Unknown Source)
    at daos.ConferenceDao.isConferenceNameExists(ConferenceDao.java:129)
    at servlets.ConferenceServlet.removeUser(ConferenceServlet.java:232)
    at servlets.ConferenceServlet.processRequest(ConferenceServlet.java:79)
    at servlets.ConferenceServlet.doPost(ConferenceServlet.java:433)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:928)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:987)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:539)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:298)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
04/06/2012 00:27:15 org.apache.catalina.core.StandardContext reload
INFO: Reloading Context with name [/conf4u] has started
04/06/2012 00:27:15 org.apache.catalina.loader.WebappClassLoader clearReferencesJdbc
SEVERE: The web application [/conf4u] registered the JDBC driver [com.mysql.jdbc.Driver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.
04/06/2012 00:27:15 org.apache.catalina.core.StandardContext reload
INFO: Reloading Context with name [/conf4u] is completed

Dao method:

public void removeUserFromConference(Conference conference, User user) {
    ConferencesUsers conferenceUser = getConferenceUser(conference, user);

    Session session = HibernateUtil.getSessionFactory().getCurrentSession();
    session.beginTransaction();

    session.delete(conferenceUser);

    session.getTransaction().commit();
}

The model class:

@Entity
@Table( name = "Conferences_Users" )
public class ConferencesUsers implements Serializable {
    private static final long serialVersionUID = -3401337605668111437L;
    private Conference conference;
    private User user; 
    private int userRole;
    private UserAttendanceStatus attendanceStatus;
    private boolean notifiedByMail;

    ConferencesUsers() {}  //not public on purpose!

    public ConferencesUsers(Conference conf, User user, int userRole) {
         this.conference = conf;
         this.user = user;
         this.userRole = userRole;
         this.attendanceStatus = null;
         this.notifiedByMail = false;
    }

    public ConferencesUsers(Conference conf, User user, int userRole, UserAttendanceStatus attendanceStatus, boolean notifiedByMail) {
         this.conference = conf;
         this.user = user;
         this.userRole = userRole;
         this.attendanceStatus = attendanceStatus;
         this.notifiedByMail = notifiedByMail;
    }

    @Id
    @ManyToOne(cascade = CascadeType.ALL)
    public Conference getConference() {
         return conference;
    }

    public void setConference(Conference conference) {
         this.conference = conference;
    }

    @Id
    @ManyToOne(cascade = CascadeType.ALL)
    public User getUser() {
         return user;
    }

    public void setUser(User user) {
         this.user = user;
    }

    @Enumerated(EnumType.STRING)
    public int getUserRole() {
         return userRole;
    }

    public void setUserRole(int userRole) {
         this.userRole = userRole;
    }

    @Nullable
    public boolean isNotifiedByMail() {
         return notifiedByMail;
    }

    public void setNotifiedByMail(boolean notifiedByMail) {
         this.notifiedByMail = notifiedByMail;
    }

    public UserAttendanceStatus getAttendanceStatus() {
         return attendanceStatus;
    }

    public ConferencesUsers setAttendanceStatus(UserAttendanceStatus attendanceStatus) {
         this.attendanceStatus = attendanceStatus;
         return this;
    }
}

Upvotes: 8

Views: 52796

Answers (8)

A.Aleem11
A.Aleem11

Reputation: 1964

this line "session.beginTransaction();" prevent multiple transactions so remove this line and try because in select query it is not neccessary but it code not works after removing this then at the end of this code add " session.rollback();".

Upvotes: 0

Santi Garcia
Santi Garcia

Reputation: 1

I solve this problem creating diferent sessions with

Session session = factory.openSession();
session.beginTransaction();

//your code here

session.getTransaction().commit();

Upvotes: 0

Santi Barbat
Santi Barbat

Reputation: 2315

Try using finally to close your Hibernate session, like this:

try {
    session.getTransaction().begin();

    // YOUR CODE

    session.getTransaction().commit();
} catch (RuntimeException e) {
    try{
        session.getTransaction().rollback();
    } catch(RuntimeException rbe) {
        log.error("Couldn’t roll back transaction", rbe);
    }
    throw e;
} finally {
    if (session != null && session.isOpen()) {
        session.close();
    }
}

Upvotes: 0

Juan Francisco
Juan Francisco

Reputation: 1

I could solve it with the following code:

public class UserDaoImpl implements UserDao {  

    Session session = null;

    public UserDaoImpl() {
        this.session = HibernateUtil.getSessionFactory().openSession();
    }

    @Override
    public List<TblUsuario> getAllUsers() {

        List<TblUsuario> listUsuarios = null;

        try {
            org.hibernate.Transaction tx = this.session.getTransaction();
            Query query = this.session.createQuery("....");
            listUsuarios = query.list();
        } catch (Exception e) {
            e.printStackTrace();
        } 

        return listUsuarios;
   }

...

}

Upvotes: -1

code.improve
code.improve

Reputation: 1

What you did here :

Session session = HibernateUtil.getSessionFactory().getCurrentSession();

is actually trying to use an open session without closing it.

It happened to me and I was facing same problem, and what I did is :

Session session = HibernateUtil.getSessionFactory().openSession();

// Hibernate bla bla bla transaction or rollback
// then always  close your session :

if (session.isOpen()) {
            session.close();
        }

and there weren't "Hibernate Nested Transaction Not Supported Error" raised again ...

Upvotes: 0

user2204125
user2204125

Reputation: 71

Firstly, you should inject the hibernateProperties, hibernate.current_session_context_class,

<property name="hibernateProperties">
    <props>
        <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
        <prop key="hibernate.show_sql">true</prop>
        <prop key="hibernate.format_sql">true</prop>
        <prop key="hibernate.hbm2ddl.auto">update</prop>
        <prop key="hibernate.current_session_context_class">thread</prop>
    </props>
</property>

then you can use getCurrentSession() to get the CurrentSession.

Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
long count = (Long) session
        .createQuery("select count(*) from User u where u.name = :name")
        .setString("name", name).uniqueResult();
session.getTransaction().commit();

Upvotes: 7

user1443692
user1443692

Reputation: 41

I have the same problem before. First run:

session.beginTransaction();
session.save(something);
session.getTransaction().commit();

when query something by:

session.beginTransaction();
session.query ...

the same exception is raised at second beginTranscation. I solved it by using

session.getTransaction().begin();

instead of

session.beginTransaction();

both in query and save.

Upvotes: 4

JB Nizet
JB Nizet

Reputation: 691835

You probably have begun a transaction, and trying to begin another one without having committed or rollbacked the previous one. The idiom when using programmatic transaction demarcation is the following one:

try {
    sess.getTransaction().begin();

    // do some work

    sess.getTransaction().commit()
}
catch (RuntimeException e) {
    sess.getTransaction().rollback();
    throw e;
}

This is cumbersome and error-prone, and this is one of the reasons why using EJBs or Spring to have declarative transactions is so useful.

Upvotes: 22

Related Questions