我在我的 Google App Engine 网络应用程序中使用 Java 和 JPA 1。我有这个问题Caused by: javax.transaction.xa.XAException: Concurrent Modification
Profile
并ViewedProfile
使用相应的 getter 和 setter:
public class Profile {
...
@OneToOne(cascade={CascadeType.PERSIST, CascadeType.REMOVE})
private ViewedProfile viewed = null;
...
}
public class ViewedProfile {
...
private LinkedHashSet<String> viewedBy = null;
private LinkedHashSet<String> profilesViewed = null;
...
}
报错的方法:
public void recentlyViewed (String email, String emailVisited) throws PersistenceException{
EntityManager em = EMF.get().createEntityManager();
EntityTransaction tx = null;
Profile user = null;
try{
tx = em.getTransaction();
tx.begin();
user = em.find(Profile.class, email);
//nobody viewed your profile yet
if (user.getViewed() == null){
LinkedHashSet<String> set = new LinkedHashSet<String>();
set.add( emailVisited );
ViewedProfile view = new ViewedProfile();
view.setProfilesViewed( set);
user.setViewed( view );
} else if ( user.getViewed().getProfilesViewed().contains( emailVisited ) ){
//remove then added to bubble up
user.getViewed().getProfilesViewed().remove( emailVisited );
user.getViewed().getProfilesViewed().add( emailVisited );
} else {
user.getViewed().getProfilesViewed().add( emailVisited );
if (user.getViewed().getProfilesViewed().size() > MAX_VISITED){
user.getViewed().getProfilesViewed().remove(
user.getViewed().getProfilesViewed().iterator().next());
}
}
tx.commit();
}finally{
try {
if (tx != null && tx.isActive()) {
tx.rollback();
}
} finally {
em.close();
}
}
}
堆栈跟踪:
Uncaught exception from servlet
javax.persistence.RollbackException: Transaction failed to commit
at org.datanucleus.jpa.EntityTransactionImpl.commit(EntityTransactionImpl.java:118)
at org.datanucleus.store.appengine.jpa.DatastoreEntityTransactionImpl.commit(DatastoreEntityTransactionImpl.java:58)
at ...recentlyViewed(DetailsAccess.java:356)
at ...randomUser(UserAction.java:258)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:45)
at com.opensymphony.xwork2.DefaultActionInvocation.invokeAction(DefaultActionInvocation.java:453)
at com.opensymphony.xwork2.DefaultActionInvocation.invokeActionOnly(DefaultActionInvocation.java:292)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:255)
at org.apache.struts2.interceptor.debugging.DebuggingInterceptor.intercept(DebuggingInterceptor.java:256)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
at com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor.doIntercept(DefaultWorkflowInterceptor.java:176)
at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
at com.opensymphony.xwork2.validator.ValidationInterceptor.doIntercept(ValidationInterceptor.java:265)
at org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor.doIntercept(AnnotationValidationInterceptor.java:68)
at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
at com.opensymphony.xwork2.interceptor.ConversionErrorInterceptor.intercept(ConversionErrorInterceptor.java:138)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:211)
at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:211)
at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
at com.opensymphony.xwork2.interceptor.StaticParametersInterceptor.intercept(StaticParametersInterceptor.java:190)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
at org.apache.struts2.interceptor.MultiselectInterceptor.intercept(MultiselectInterceptor.java:75)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
at org.apache.struts2.interceptor.CheckboxInterceptor.intercept(CheckboxInterceptor.java:90)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
at org.apache.struts2.interceptor.FileUploadInterceptor.intercept(FileUploadInterceptor.java:243)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
at com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor.intercept(ModelDrivenInterceptor.java:100)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
at com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor.intercept(ScopedModelDrivenInterceptor.java:141)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
at com.opensymphony.xwork2.interceptor.ChainingInterceptor.intercept(ChainingInterceptor.java:145)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
at com.opensymphony.xwork2.interceptor.PrepareInterceptor.doIntercept(PrepareInterceptor.java:171)
at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
at com.opensymphony.xwork2.interceptor.I18nInterceptor.intercept(I18nInterceptor.java:176)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
at org.apache.struts2.interceptor.ServletConfigInterceptor.intercept(ServletConfigInterceptor.java:164)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
at com.opensymphony.xwork2.interceptor.AliasInterceptor.intercept(AliasInterceptor.java:192)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
at com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor.intercept(ExceptionMappingInterceptor.java:187)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
at ...LoginInterceptor.intercept(LoginInterceptor.java:37)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
at org.apache.struts2.impl.StrutsActionProxy.execute(StrutsActionProxy.java:54)
at org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:510)
at org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:77)
at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:91)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388)
at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)
at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at org.mortbay.jetty.Server.handle(Server.java:326)
at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:923)
at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
at com.google.tracing.TraceContext$TraceContextRunnable.runInContext(TraceContext.java:480)
at com.google.tracing.TraceContext$TraceContextRunnable$1.run(TraceContext.java:487)
at com.google.tracing.TraceContext.runInContext(TraceContext.java:774)
at com.google.tracing.TraceContext$DoInTraceContext.runInContext(TraceContext.java:751)
at com.google.tracing.TraceContext$AbstractTraceContextCallback.runInInheritedContextNoUnref(TraceContext.java:342)
at com.google.tracing.TraceContext$AbstractTraceContextCallback.runInInheritedContext(TraceContext.java:334)
at com.google.tracing.TraceContext$TraceContextRunnable.run(TraceContext.java:484)
at java.lang.Thread.run(Thread.java:722)
Caused by: javax.persistence.PersistenceException: Transaction rolled back due to failure during commit
at org.datanucleus.jpa.NucleusJPAHelper.getJPAExceptionForNucleusException(NucleusJPAHelper.java:283)
at org.datanucleus.jpa.EntityTransactionImpl.commit(EntityTransactionImpl.java:116)
... 81 more
Caused by: javax.transaction.xa.XAException: Concurrent Modification
at org.datanucleus.store.appengine.DatastoreXAResource.commit(DatastoreXAResource.java:93)
at org.d...(length 9822)
我怀疑问题出在 LinkedHashSet 上,所以我在单独的项目中进行了尝试。
public class Person {
private LinkedHashSet<String> viewers = null;
public LinkedHashSet<String> getViewers() {
return viewers;
}
public void setViewers(LinkedHashSet<String> viewers) {
this.viewers = viewers;
}
}
然后修改集合:
Person p = new Person();
LinkedHashSet<String> viewers = new LinkedHashSet<String>();
viewers.add("one");
viewers.add("two");
viewers.add("three");
viewers.add("four");
p.setViewers(viewers);
p.getViewers().remove(p.getViewers().iterator().next());
p.getViewers().remove("two");
p.getViewers().add("two");
for (String s: p.getViewers()){
System.out.println(s);
}
但是这个工作。有什么帮助吗?谢谢