У меня есть два класса Invoice и InvoiceItem. Я бы хотел, чтобы в Invoice был список объектов InvoiceItem. У меня есть красный, что список должен быть примитивных или сериализуемых объектов. Я сделал InvoiceItem Serializable.
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. Я пробовал с:
@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).
В сохраняются списки объектов , @ aldrin указано, что
Для дочерних классов первичный ключ имеет
быть
com.google.appengine.api.datastore.Key
значение (или закодированное в виде строки) см.
Итак, я попробовал с Key. Это сработало.
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key id;