web-dev-qa-db-fra.com

Obtention de l'erreur "org.hibernate.TransactionException: transactions imbriquées non prises en charge" lors de la suppression

Lors de l'exécution de la méthode removeUserFromConference, obtention de cette 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

Méthode Dao:

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();
}

La classe de modèle:

@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;
    }
}
9
alonp

Vous avez probablement déjà commencé une transaction et essayé d'en commencer une autre sans avoir validé ou annulé la précédente. L'idiome utilisé lors de l'utilisation de la démarcation programmatique de transaction est le suivant:

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

    // do some work

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

C'est une tâche lourde et sujette aux erreurs, et c'est l'une des raisons pour lesquelles utiliser des EJB ou Spring pour effectuer des transactions déclaratives est si utile.

22
JB Nizet

Tout d’abord, vous devez injecter 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>

ensuite, vous pouvez utiliser getCurrentSession () pour obtenir la 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();
7
user2204125

J'ai le même problème avant. Première exécution:

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

quand interroger quelque chose par:

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

la même exception est levée à la deuxième beginTranscation. Je l'ai résolu en utilisant 

session.getTransaction().begin();

au lieu de 

session.beginTransaction();

à la fois dans la requête et enregistrer.

4
user1443692

Qu'est-ce que vous avez fait ici:

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

essaie actuellement d’utiliser une session ouverte sans la fermer.

C'est ce qui m'est arrivé et j'ai rencontré le même problème. Ce que j'ai fait est:

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

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

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

et il n'y a pas eu d'erreur "Erreur de transaction imbriquée imbriquée dans Hibernate" qui a de nouveau été soulevée ...

0
code.improve

Essayez enfin de fermer votre session Hibernate, comme ceci:

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();
    }
}
0
Santi Barbat

Je résous ce problème en créant différentes sessions avec 

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

//your code here

session.getTransaction().commit();
0
Santi Garcia

Je pourrais le résoudre avec le code suivant:

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;
   }

...

}
0
Juan Francisco

cette ligne "session.beginTransaction ();" empêchez plusieurs transactions, alors supprimez cette ligne et essayez car, dans la requête select, ce n'est pas nécessaire, mais le code ne fonctionne pas après la suppression de cette requête, puis ajoutez "session.rollback ();" à la fin de ce code.

0
A.Aleem11