运行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
道方法:
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(); }
模型类:
@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; } }
您可能已经开始了一笔交易,并尝试开始另一笔交易而没有提交或回滚上一笔交易。使用程序化事务划分时的惯用法如下:
try { sess.getTransaction().begin(); // do some work sess.getTransaction().commit() } catch (RuntimeException e) { sess.getTransaction().rollback(); throw e; }
这很麻烦且容易出错,这就是为什么使用EJB或Spring具有声明式事务如此有用的原因之一。