并发修改 - JPA AppEngine

时间:2013-05-10 09:15:31

标签: java google-app-engine jpa

我在Google App Engine网络应用中使用Java和JPA 1。我对Caused by: javax.transaction.xa.XAException: Concurrent Modification

有这个问题

ProfileViewedProfile以及相应的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();
        }
    }

}

stacktrace:

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

但这一项工作。有帮助吗?感谢

0 个答案:

没有答案