2012-02-22 280 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