如何删除持久/非持久集合字段为空的对象?
我有一个名为 Parent 的类,我将这些对象存储在高复制数据存储中。
每个对象都与我通过存储Key对象列表进行管理的子对象之间存在无主关系。
我有一个 REST Web 服务,它以 JSON 表示形式返回父对象和所有子对象。为了使用 Jackson 编组器,我获取子对象的集合,并使用未定义参数化类型的原始集合将该集合添加到父对象中。
Collection 字段并不是我打算保留的东西。然而,因为根据 DataNucleus 的 Andy 的说法,Google 的 JDO @Persistent 文档可能不正确,所以我没有添加 @NotPersistent 注释在球场上。现在,我在数据存储中拥有用户数据,需要小心不要通过修改 Parent 类来意外破坏它。我不确定这是否可能或是否会发生,所以我正在谨慎行事。
此空 Collection cardList 值中没有存储任何数据;但是,我经常会遇到无法分离该字段的错误。
- 如果该字段上没有任何注释(根据 Andy 的说法,默认为 @Persistent),我无法删除该对象。
- 如果我将 @NotPersistent 放在该字段上,则无法访问任何数据并且没有任何作用。
这是“Parent”类:
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)
问题:
如何删除父对象?
我需要做什么才能从数据存储中删除空集合字段而不丢失所有数据?我觉得最好的方法可能是使用 2 个独立但镜像的对象:一个用于将父键和子键存储在数据存储中,另一个用于以 JSON 表示形式返回父键和所有关联的子键。
有没有办法追溯地使 Collection cardList 字段不持久,以便我可以使用它在前端序列化数据?
I have a class called Parent, and I'm storing these object's in the High replication datastore.
Each object has an unowned relationship with child objects that I manage by storing a List of Key objects.
I have a REST web service that returns the Parent and all Child objects as a JSON representation. In order to use the Jackson marshaller, I take the collection of Child objects and add that collection to the Parent using a raw Collection with no parameterized types defined.
The Collection field was not something I intended to persist. Yet, because According to DataNucleus's Andy, Google's JDO @Persistent documentation is potentially incorrect, I didn't put a @NotPersistent annotation on the field. Now I have user data in the datastore and need to be careful not to accidentally destroy it by modifying the Parent class. I'm not sure if that's possible or if it can happen, so I'm proceeding cautiously.
There is no data stored in this null Collection cardList value; however, I oftentimes get errors about not being able to detach the field.
- Without any annotations on the field, (which according to Andy, defaults to @Persistent), I am unable to delete the object.
- If I put @NotPersistent on the field, then none of the data can be accessed and nothing works.
Here is the class "Parent":
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 ...
Here is the code I'm using to delete the object:
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 when trying to delete object:
Note that again, no data is stored for this field. I also can't seem to successfully detach the field.
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)
Questions:
How can I delete the Parent object?
What do I need to do to remove the null Collection field from the datastore without losing all my data? I feel like the best approach might be to use 2 separate but mirrored objects: One for storing the parent and child keys in the datastore and another for returning the parent and all associated children as a JSON representation.
Is there a way to retroactively make the Collection cardList field NotPersistent so I can just use it for serializing data on the frontend?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果您的 Collection 仅用于以瞬态方式转换 @Persistent childRealKeys,那么它应该是 @NotPersistent childList。
在这种情况下:
在这种情况下你还会遇到另一个例外吗?
@jmort253 更新:
检查以确保项目中不包含重复的 appengine JAR 文件。我之前升级过,一些旧的 JAR 没有从 CLASSPATH 中删除。类加载器可能会加载旧版本并忽略新版本,这就是我的情况。事实证明,解决依赖关系就可以解决这个问题。
此外,我可以毫无问题地使用 @NotPersistent,并且可以使用事务和 PMF DataNucleus DetachOnClose 属性 作为 Andy 在此 Google 网上论坛中进行了描述。
删除父级:
父类:
现在可以添加@NotPercient,而不会收到类路径警告。除了 JAR 依赖性问题之外,我还必须向 Collection 定义添加参数化类型。如果省略,您会收到以下警告:
在 CLASSPATH 中找不到类“”。请检查您的规范和 CLASSPATH。
If your Collection is only used for transforming @Persistent childRealKeys in a transient way, then it should be @NotPersistent childList.
In that context:
Are you getting another exception in that case?
UPDATE by @jmort253:
Checked to be sure there aren't duplicate appengine JAR files included in the project. I upgraded earlier and some of the older JARS weren't removed from the CLASSPATH. The classloader may load the older versions and ignore the newer versions, and this was happening in my case. It turns out that resolving the dependencies takes care of the issue.
Additionally, I can then use @NotPersistent without issues, and I can detach the object using a Transaction and the PMF DataNucleus DetachOnClose property as Andy describes in this Google Group.
Deleting Parent:
Parent Class:
Can now add @NotPersistent without getting classpath warnings. In addition to the JAR dependency issues, I had to add a parameterized type to the Collection definition. If it's omitted, you get the following warning:
Class "" was not found in the CLASSPATH. Please check your specification and your CLASSPATH.