如何删除具有持久/非持久收集字段的对象为空?

时间:2012-02-22 20:50:59

标签: java google-app-engine jdo datanucleus

我有一个名为 Parent 的类,我将这些对象存储在高复制数据存储区中。

每个对象与我通过存储对象列表管理的对象具有无主关系。

我有一个REST Web服务,它将Parent和所有Child对象作为JSON表示返回。为了使用Jackson marshaller,我获取了Child对象的集合,并使用未定义参数化类型的原始Collection将该集合添加到Parent中。

Collection字段不是我打算坚持的东西。然而,因为According to DataNucleus's Andy, Google's JDO @Persistent documentation is potentially incorrect,我没有在字段上添加@NotPersistent注释。现在我在数据存储区中有用户数据,需要注意不要通过修改Parent类来意外破坏它。我不确定这是否可能或是否可能发生,所以我谨慎行事。

此null Collection cardList 值中没有存储数据;但是,我经常会因为无法分离现场而遇到错误。

  • 在该字段上没有任何注释(根据Andy,默认为@Persistent),我无法删除该对象。
  • 如果我在字段上放置@NotPersistent,则无法访问任何数据,也无法正常工作。

这是“父”类:

public class Parent implements Serializable {

    private static final long serialVersionUID = 1L;    

    @PrimaryKey
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
    private Key key;

    @Persistent
    private String keyString;

    @Persistent
    private String name; 

    // store keys that associate with Child objects
    @Persistent 
    private List<Key> childRealKeys = new ArrayList<Key>();

    /** 
     * If @NotPersistent, no Parent is accessible.
     * If @NotPersistent is commented, the data loads, but I cannot delete the parent.
     *
     * This field was not intended to be stored and is just used to serialize the Parent
     * and Children to a single JSON object to be returned in a REST call.
     */
     // @NotPersistent
     private Collection childList = null;

     // getter for the field I don't want to store but just use to return children in the REST service as JSON
     public Collection getChildList() { return childList; }

     // remaining getters and setters follow ...

以下是我用来删除对象的代码

public void deleteParent(String keyString) {

    PersistenceManager pm = PMF.getInstance().getPersistenceManager();
    Parent parent = null;

    Key parentKey = KeyFactory.stringToKey(keyString);
    parent = pm.getObjectById(Parent.class, parentKey);

    // I tried detaching to see if that helps. It still says the field is not detached!
    Parent detachedParent = pm.detachCopy(parent);
    pm.deletePersistent(detachedParent.getChildList());
    pm.deletePersistent(detachedParent);

    pm.close();

}
尝试删除对象时

StackTrace:

请注意,此字段不会存储任何数据。我似乎也无法成功地分离这个领域。

javax.jdo.JDODetachedFieldAccessException: You have just attempted to access field "childList" yet this field was not detached when you detached the object. Either dont access this field, or detach it when detaching the object.
at com.fullcreative.loop.Parent.jdoGetChildList(Parent.java)
at com.fullcreative.loop.Parent.getChildList(Parent.java:112)
at com.fullcreative.loop.LoopDaoJdo.deleteParent(LoopDaoJdo.java:690)
at com.fullcreative.loop.LoopService.deleteParent(LoopService.java:551)
at com.fullcreative.loop.LoopController.deleteParent(LoopController.java:1022)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.google.appengine.tools.development.agent.runtime.Runtime.invoke(Runtime.java:104)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:176)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:426)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:414)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:790)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
at org.springframework.web.servlet.FrameworkServlet.doDelete(FrameworkServlet.java:582)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:643)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:369)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:109)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:97)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:100)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:78)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:35)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
at com.fullcreative.loop.security.auth.GaeAuthenticationFilter.doFilter(GaeAuthenticationFilter.java:227)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:79)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:168)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.appengine.tools.development.HeaderVerificationFilter.doFilter(HeaderVerificationFilter.java:35)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.appengine.api.blobstore.dev.ServeBlobFilter.doFilter(ServeBlobFilter.java:60)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:43)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.appengine.tools.development.StaticFileFilter.doFilter(StaticFileFilter.java:122)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.appengine.tools.development.BackendServersFilter.doFilter(BackendServersFilter.java:97)
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 com.google.appengine.tools.development.DevAppEngineWebAppContext.handle(DevAppEngineWebAppContext.java:78)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at com.google.appengine.tools.development.JettyContainerService$ApiProxyHandler.handle(JettyContainerService.java:362)
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.HttpParser.parseNext(HttpParser.java:547)
at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:212)
at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:409)
at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)

问题:

  • 如何删除Parent对象?

  • 如何从数据存储中删除null Collection字段而不丢失所有数据?我认为最好的方法可能是使用2个独立但镜像的对象:一个用于在数据存储区中存储父键和子键,另一个用于将父级和所有关联子级作为JSON表示形式返回。

  • 有没有办法追溯性地使Collection cardList字段NotPersistent,所以我可以用它来序列化前端的数据?

1 个答案:

答案 0 :(得分:1)

如果您的Collection仅用于以瞬态方式转换@Persistent childRealKeys,那么它应该是@NotPersistent childList。

在这种情况下:

// pm.deletePersistent(detachedParent.getChildList()); becomes unnecessary, and
pm.deletePersistent(parent); //should work

在这种情况下你会得到另一个例外吗?

@ jmort253更新:

检查以确保项目中包含的重复的appengine JAR文件没有。我之前升级过,一些较旧的JARS没有从CLASSPATH中删除。类加载器可以加载旧版本并忽略较新版本,这种情况在我的情况下发生。事实证明,解决依赖关系可以解决问题。

此外,我可以毫无问题地使用@NotPersistent,我可以使用事务和PMF DataNucleus DetachOnClose property Andy describes in this Google Group分离对象。

删除父级

public boolean deleteLoop(String parentId) {
    PersistenceManager pm = PMF.getInstance().getPersistenceManager();
    Transaction tx = pm.currentTransaction();
    try {
        tx.begin();
        pm.setDetachAllOnCommit(true);
        Parent parent = null;

        Key parentKey = KeyFactory.stringToKey(parentId);
        loop = pm.getObjectById(Parent.class, parentKey);

        Parent detachedParent = pm.detachCopy(parent);

                    // this was indeed not necessary
        //pm.deletePersistent(detachedParent.getChildList());

                    // no detachment issues, object deletes just fine.
        pm.deletePersistent(detachedParent);

        tx.commit();
        //pm.close();

    } catch(Exception e) {
        log.error("Exception trying to delete Parent :: ",e);
        e.printStackTrace();


    } finally {

        if(tx.isActive()) {
            tx.rollback();
        }

        pm.close();
    }
}

家长班:

现在可以添加@NotPersistent而不会收到类路径警告。除了JAR依赖问题,我还必须在Collection定义中添加一个参数化类型。如果省略,则会收到以下警告:

  • 在CLASSPATH中找不到类“”。请检查您的规格和CLASSPATH。

     @PersistenceCapable(detachable = "true")
     public class Parent implements Serializable { 
        ...
        @NotPersistent
        private Collection<Child> childList;
        ...      
     }