删除时出现“org.hibernate.TransactionException:不支持嵌套事务”错误

时间:2021-07-14 10:45:19

When running removeUserFromConference method getting this exception:

运行removeUserFromConference方法时获取此异常:

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

8 个解决方案

#1


22  

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.

这很麻烦且容易出错,这也是使用EJB或Spring进行声明式事务非常有用的原因之一。

#2


7  

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

首先,你应该注入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.

然后你可以使用getCurrentSession()来获取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();

#3


4  

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

第二次beginTranscation会引发同样的异常。我用它来解决它

session.getTransaction().begin();

instead of

代替

session.beginTransaction();

both in query and save.

在查询和保存中。

#4


0  

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 ...

并且没有再次提出“Hibernate嵌套事务不支持错误”...

#5


0  

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

...

}

#6


0  

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

尝试使用finally来关闭你的Hibernate会话,如下所示:

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

#7


0  

I solve this problem creating diferent sessions with

我解决了这个问题,创建了不同的会话

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

//your code here

session.getTransaction().commit();

#8


0  

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();".

这一行“session.beginTransaction();”防止多个事务,所以删除此行并尝试,因为在选择查询中它不是必要的但它删除后代码不起作用然后在此代码的末尾添加“session.rollback();”。

#1


22  

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.

这很麻烦且容易出错,这也是使用EJB或Spring进行声明式事务非常有用的原因之一。

#2


7  

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

首先,你应该注入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.

然后你可以使用getCurrentSession()来获取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();

#3


4  

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

第二次beginTranscation会引发同样的异常。我用它来解决它

session.getTransaction().begin();

instead of

代替

session.beginTransaction();

both in query and save.

在查询和保存中。

#4


0  

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 ...

并且没有再次提出“Hibernate嵌套事务不支持错误”...

#5


0  

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

...

}

#6


0  

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

尝试使用finally来关闭你的Hibernate会话,如下所示:

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

#7


0  

I solve this problem creating diferent sessions with

我解决了这个问题,创建了不同的会话

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

//your code here

session.getTransaction().commit();

#8


0  

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();".

这一行“session.beginTransaction();”防止多个事务,所以删除此行并尝试,因为在选择查询中它不是必要的但它删除后代码不起作用然后在此代码的末尾添加“session.rollback();”。