【问题标题】:Problems Mapping a List of Serializable Objects with JDO使用 JDO 映射可序列化对象列表的问题
【发布时间】:2010-04-08 19:13:21
【问题描述】:

我有两个类 Invoice 和 InvoiceItem。我希望 Invoice 有一个 InvoiceItem Objets 列表。我有红色的列表必须是原始或可序列化的对象。我已将 InvoiceItem 设为可序列化。

Invoice.java 看起来像

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.jdo.annotations.Column;
import javax.jdo.annotations.Embedded;
import javax.jdo.annotations.EmbeddedOnly;
import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.IdentityType;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.Element;
import javax.jdo.annotations.PrimaryKey;

import com.google.appengine.api.datastore.Key;
import com.softamo.pelicamo.shared.InvoiceCompanyDTO;

@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class Invoice {  
    @PrimaryKey
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
    private Long id;

    @Persistent
    private String number;

    @Persistent
    private Date date;

    @Persistent
    private List<InvoiceItem> items = new ArrayList<InvoiceItem>();

    public Invoice() {} 

    public Long getId() { return id; }
    public void setId(Long id) {this.id = id;}

    public String getNumber()           { return number;}
    public void setNumber(String invoiceNumber) { this.number = invoiceNumber;}

    public Date getDate()               { return date;}
    public void setDate(Date invoiceDate)       { this.date = invoiceDate;}


    public List<InvoiceItem> getItems()         { return items;}
    public void setItems(List<InvoiceItem> items)   { this.items = items;}

}

InvoiceItem.java 看起来像

import java.io.Serializable;
import java.math.BigDecimal;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;

@PersistenceCapable
public class InvoiceItem implements Serializable {  

    @Persistent
    private BigDecimal amount;

    @Persistent
    private float quantity;

    public InvoiceItem() {}

    public BigDecimal getAmount()               {   return amount;}
    public void setAmount(BigDecimal amount)        { this.amount = amount;}

    public float getQuantity()              { return quantity;}
    public void setQuantity(float quantity)         { this.quantity = quantity;}
}

我在运行 JUnit 测试时遇到下一个错误。

javax.jdo.JDOUserException: Attempt to handle persistence for object using datastore-identity yet StoreManager for this datastore doesn't support that identity type
    at org.datanucleus.jdo.NucleusJDOHelper.getJDOExceptionForNucleusException(NucleusJDOHelper.java:375)
    at org.datanucleus.jdo.JDOPersistenceManager.jdoMakePersistent(JDOPersistenceManager.java:674)
    at org.datanucleus.jdo.JDOPersistenceManager.makePersistent(JDOPersistenceManager.java:694)
    at com.softamo.pelicamo.server.InvoiceStore.add(InvoiceStore.java:23)
    at com.softamo.pelicamo.server.PopulateStorage.storeInvoices(PopulateStorage.java:58)
    at com.softamo.pelicamo.server.PopulateStorage.run(PopulateStorage.java:46)
    at com.softamo.pelicamo.server.InvoiceStoreTest.setUp(InvoiceStoreTest.java:44)
    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 org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:27)
    at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
NestedThrowablesStackTrace:
Attempt to handle persistence for object using datastore-identity yet StoreManager for this datastore doesn't support that identity type
org.datanucleus.exceptions.NucleusUserException: Attempt to handle persistence for object using datastore-identity yet StoreManager for this datastore doesn't support that identity type
    at org.datanucleus.state.AbstractStateManager.<init>(AbstractStateManager.java:128)
    at org.datanucleus.state.JDOStateManagerImpl.<init>(JDOStateManagerImpl.java:215)
    at org.datanucleus.jdo.JDOAdapter.newStateManager(JDOAdapter.java:119)
    at org.datanucleus.state.StateManagerFactory.newStateManagerForPersistentNew(StateManagerFactory.java:150)
    at org.datanucleus.ObjectManagerImpl.persistObjectInternal(ObjectManagerImpl.java:1297)
    at org.datanucleus.sco.SCOUtils.validateObjectForWriting(SCOUtils.java:1476)
    at org.datanucleus.store.mapped.scostore.ElementContainerStore.validateElementForWriting(ElementContainerStore.java:380)
    at org.datanucleus.store.mapped.scostore.FKListStore.validateElementForWriting(FKListStore.java:609)
    at org.datanucleus.store.mapped.scostore.FKListStore.internalAdd(FKListStore.java:344)
    at org.datanucleus.store.appengine.DatastoreFKListStore.internalAdd(DatastoreFKListStore.java:146)
    at org.datanucleus.store.mapped.scostore.AbstractListStore.addAll(AbstractListStore.java:128)
    at org.datanucleus.store.mapped.mapping.CollectionMapping.postInsert(CollectionMapping.java:157)
    at org.datanucleus.store.appengine.DatastoreRelationFieldManager.runPostInsertMappingCallbacks(DatastoreRelationFieldManager.java:216)
    at org.datanucleus.store.appengine.DatastoreRelationFieldManager.access$200(DatastoreRelationFieldManager.java:47)
    at org.datanucleus.store.appengine.DatastoreRelationFieldManager$1.apply(DatastoreRelationFieldManager.java:115)
    at org.datanucleus.store.appengine.DatastoreRelationFieldManager.storeRelations(DatastoreRelationFieldManager.java:80)
    at org.datanucleus.store.appengine.DatastoreFieldManager.storeRelations(DatastoreFieldManager.java:955)
    at org.datanucleus.store.appengine.DatastorePersistenceHandler.storeRelations(DatastorePersistenceHandler.java:527)
    at org.datanucleus.store.appengine.DatastorePersistenceHandler.insertPostProcess(DatastorePersistenceHandler.java:299)
    at org.datanucleus.store.appengine.DatastorePersistenceHandler.insertObjects(DatastorePersistenceHandler.java:251)
    at org.datanucleus.store.appengine.DatastorePersistenceHandler.insertObject(DatastorePersistenceHandler.java:235)
    at org.datanucleus.state.JDOStateManagerImpl.internalMakePersistent(JDOStateManagerImpl.java:3185)
    at org.datanucleus.state.JDOStateManagerImpl.makePersistent(JDOStateManagerImpl.java:3161)
    at org.datanucleus.ObjectManagerImpl.persistObjectInternal(ObjectManagerImpl.java:1298)
    at org.datanucleus.ObjectManagerImpl.persistObject(ObjectManagerImpl.java:1175)
    at org.datanucleus.jdo.JDOPersistenceManager.jdoMakePersistent(JDOPersistenceManager.java:669)
    at org.datanucleus.jdo.JDOPersistenceManager.makePersistent(JDOPersistenceManager.java:694)
    at com.softamo.pelicamo.server.InvoiceStore.add(InvoiceStore.java:23)
    at com.softamo.pelicamo.server.PopulateStorage.storeInvoices(PopulateStorage.java:58)
    at com.softamo.pelicamo.server.PopulateStorage.run(PopulateStorage.java:46)
    at com.softamo.pelicamo.server.InvoiceStoreTest.setUp(InvoiceStoreTest.java:44)
    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 org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:27)
    at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

此外,当我尝试通过我的应用程序存储带有项目列表的发票时。在开发控制台中,我可以看到项目没有保留到任何字段,而发票类属性的其余部分被正确存储。

有谁知道我做错了什么?

解决方案

正如答案中所指出的,错误表明 InvoiceItem 类缺少主键。我试过了:

@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Long id;

但我得到了

javax.jdo.JDOFatalUserException: Error in meta-data for InvoiceItem.id: Cannot have a java.lang.Long primary key and be a child object (owning field is Invoice.items).

persist list of objets@aldrin 中指出

对于子类,主键具有 成为一个 com.google.appengine.api.datastore.Key 值(或编码为字符串)see

所以,我尝试使用 Key。有效。

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

【问题讨论】:

    标签: google-app-engine mapping storage jdo


    【解决方案1】:

    错误说明了什么?您正在使用数据存储标识(用于 InvoiceItem)并且正在使用的数据存储 (GAE/J) 不支持数据存储标识。在 InvoiceItem 上定义一个 PK 字段

    【讨论】:

    • 啊,一个downvoter已经出局了;很高兴他们不必费心添加评论,为什么他们不赞成某件事,以便改进答案。也许他们有一个隐藏的议程?
    • downvoter 可能没有注意到您的回答中的问题是修辞性的,并认为应该是评论...冷静一下,我刚刚补偿了它! ;)
    猜你喜欢
    • 1970-01-01
    • 2011-01-04
    • 2018-08-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-08
    • 2021-12-16
    • 2019-06-01
    相关资源
    最近更新 更多