2012-02-22 99 views
0

我有一个名为的父类,我将这些对象存储在高复制数据存储中。如何删除持久性/非持久性收集字段为空的对象?

每个对象都有与我通过存储重点对象的列表管理孩子对象无主的关系。

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

收集字段不是我打算坚持的东西。但是,由于According to DataNucleus's Andy, Google's JDO @Persistent documentation is potentially incorrect,我没有在该字段上添加@NotPersistent注释。现在,我在数据存储中拥有用户数据,并且需要注意不要通过修改父类来意外地销毁它。我不确定这是可能的还是可能发生的,所以我谨慎行事。

这里没有数据null 收藏cardList value;但是,我经常会因为不能分开领域而出现错误。

  • 没有任何注释在字段上(根据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(); 

} 

堆栈跟踪试图删除对象时:

请注意,再次,没有数据是存储为此字段。我似乎也无法成功解散这个领域。

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) 

问题:

  • 我怎样才能删除父对象?

  • 我需要做什么才能从数据存储中删除空集合字段而不会丢失所有数据?我觉得最好的方法可能是使用2个独立但镜像的对象:一个用于将父键和子键存储在数据存储中,另一个用于将父键和所有关联的子键作为JSON表示进行返回。

  • 有没有一种方法可以追溯性地将Collection cardList字段设置为NotPersistent,这样我就可以将它用于序列化前端数据?

+0

不知道这是否会有所帮助,但是当我在收集的childList运行@NotPersistent,我得到:“类‘’在CLASSPATH中没有被发现”作为JDOException。 – jmort253 2012-02-22 23:15:17

回答

1

如果您的集合仅用于以暂时方式转换@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(); 
    } 
} 

父类:

可现在没有得到classpath中添加警告@NotPersistent。除了JAR依赖性问题之外,我还需要将一个参数化类型添加到集合定义中。如果省略,则会发出以下警告:

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

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

是的,我将您注释过的行添加为故障排除步骤。它似乎没有区别。另外,我在我的问题评论中提到,添加@NotPersistent注释导致'Class'“在CLASSPATH中找不到。' JDOException被抛出。 – jmort253 2012-02-23 02:26:17

+0

我更新了答案并接受了它,因为您添加的内容帮助我最终找到了解决问题的原因和解决方案。谢谢! – jmort253 2012-02-23 03:12:11