运行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;
}
}
答案 0 :(得分:21)
您可能已经开始了一项交易,并尝试在没有提交或回滚前一个交易的情况下开始另一个交易。使用程序化事务划分时的习惯用法如下:
try {
sess.getTransaction().begin();
// do some work
sess.getTransaction().commit()
}
catch (RuntimeException e) {
sess.getTransaction().rollback();
throw e;
}
这很麻烦且容易出错,这也是使用EJB或Spring进行声明性事务非常有用的原因之一。
答案 1 :(得分:7)
首先,你应该注入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>
然后你可以使用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();
答案 2 :(得分:4)
我之前遇到过同样的问题。首先运行:
session.beginTransaction();
session.save(something);
session.getTransaction().commit();
通过以下方式查询时:
session.beginTransaction();
session.query ...
第二个beginTranscation
引发了同样的异常。我用
session.getTransaction().begin();
而不是
session.beginTransaction();
在查询和保存中。
答案 3 :(得分:0)
你在这里做了什么:
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
实际上是在不关闭它的情况下尝试使用打开的会话。
发生在我身上,我遇到了同样的问题,我所做的是:
Session session = HibernateUtil.getSessionFactory().openSession();
// Hibernate bla bla bla transaction or rollback
// then always close your session :
if (session.isOpen()) {
session.close();
}
并且没有再次提出“Hibernate嵌套事务不支持错误”...
答案 4 :(得分:0)
我可以使用以下代码解决它:
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;
}
...
}
答案 5 :(得分:0)
尝试使用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();
}
}
答案 6 :(得分:0)
我解决了这个问题,用
创建了不同的会话Session session = factory.openSession();
session.beginTransaction();
//your code here
session.getTransaction().commit();
答案 7 :(得分:0)
这一行“session.beginTransaction();”防止多个事务,所以删除这一行,并尝试因为在选择查询中它不是必要的,但它删除后代码不起作用然后在此代码的末尾添加“session.rollback();”。