问题
I am using DataNucleus 3.0.0-release JDO implementation to connect my Java app to MongoDB.
The related JARs in my CLASSPATH are as follows:
- datanucleus-api-jdo-3.0.0-release.jar
- datanucleus-core-3.0.0-release.jar
- datanucleus-jdo-query-3.0.0-release.jar
- datanucleus-mongodb-3.0.0-release.jar
- mongo-java-driver-2.5.2.jar
The class that I am persisting is as follows:
@PersistenceCapable(detachable = "true")
public class Record implements Serializable, Cacheable<String> {
private static final long serialVersionUID = 9022509306966814904L;
@PrimaryKey
@Persistent(defaultFetchGroup = "true", valueStrategy = IdGeneratorStrategy.IDENTITY)
private String id;
@Name
@Persistent(defaultFetchGroup = "true")
private String name;
@Name
@Persistent(defaultFetchGroup = "true")
private String surname;
@Persistent(defaultFetchGroup = "true")
private Date dateOfBirth;
@Persistent(defaultFetchGroup = "true")
private Date dateRecorded;
@Persistent(defaultFetchGroup = "true")
private String locationId;
@Persistent(embedded = "true", defaultFetchGroup = "true")
private CustomLocation customLocation;
@Persistent(defaultFetchGroup = "true")
private Category category;
@Persistent(embedded = "true", defaultFetchGroup = "true")
private CustomCategory customCategory;
@Persistent(defaultFetchGroup = "true")
private String description;
@Persistent(embeddedElement = "true", defaultFetchGroup = "true")
private List<StoredImageInfo> images;
@Persistent(embeddedElement = "true", defaultFetchGroup = "true")
private List<StoredAudioInfo> audio;
@Persistent(embeddedElement = "true", defaultFetchGroup = "true")
private List<StoredFileInfo> files;
@Persistent(defaultFetchGroup = "true")
private ModerationMode moderationMode;
@Persistent(defaultFetchGroup = "true")
private VisibilityMode visibilityMode;
@Persistent(embedded = "true", defaultFetchGroup = "true")
private UserProfileSummary owner;
@Persistent(embeddedElement = "true", defaultFetchGroup = "true")
private Map<String, UserProfileSummary> editors;
@Persistent(embeddedElement = "true", defaultFetchGroup = "true")
private Map<String, UserProfileSummary> connections;
@Persistent(embeddedElement = "true", defaultFetchGroup = "true")
private Map<String, RecordSummary> recordConnections;
@Persistent(defaultFetchGroup = "true")
private RecordType type;
@Persistent(defaultFetchGroup = "true")
private Date expiry;
public Record() {
}
public Record(Record copy) {
deepCopy(copy);
}
...
}
And the CustomLocation
class:
@PersistenceCapable(embeddedOnly="true")
public class CustomLocation implements Serializable {
private static final long serialVersionUID = -7754029273366194129L;
@PrimaryKey
@Persistent(defaultFetchGroup = "true", valueStrategy = IdGeneratorStrategy.IDENTITY)
private String id;
@Persistent(defaultFetchGroup = "true")
private String city;
@Persistent(defaultFetchGroup = "true")
private String countryKey;
@Persistent(defaultFetchGroup = "true")
private String locale;
@SuppressWarnings("unused")
private CustomLocation() {
// for serialization
}
...
}
The code that tries to fetch the object from the DB is as follows:
PersistenceManager pm = MyPersistenceManagerFactory.get().getPersistenceManager();
Record record = null;
try {
record = pm.getObjectById(Record.class, recordId);
}
catch (JDOObjectNotFoundException onfe) {
// handle
}
catch (Exception e) {
// handle
}
The following is the resulting error:
java.lang.NullPointerException
at org.datanucleus.store.mongodb.fieldmanager.FetchFieldManager.fetchStringField(FetchFieldManager.java:243)
at org.datanucleus.state.AbstractStateManager.replacingStringField(AbstractStateManager.java:2165)
at com.myproject.location.domain.CustomLocation.jdoReplaceField(CustomLocation.java)
at com.myproject.location.domain.CustomLocation.jdoReplaceFields(CustomLocation.java)
at org.datanucleus.state.JDOStateManagerImpl.replaceFields(JDOStateManagerImpl.java:1989)
at org.datanucleus.state.JDOStateManagerImpl.replaceFields(JDOStateManagerImpl.java:2009)
at org.datanucleus.store.mongodb.fieldmanager.FetchFieldManager.fetchObjectField(FetchFieldManager.java:353)
at org.datanucleus.state.AbstractStateManager.replacingObjectField(AbstractStateManager.java:2182)
at com.myproject.domain.Record.jdoReplaceField(Record.java)
at com.myproject.domain.Record.jdoReplaceFields(Record.java)
at org.datanucleus.state.JDOStateManagerImpl.replaceFields(JDOStateManagerImpl.java:1989)
at org.datanucleus.state.JDOStateManagerImpl.replaceFields(JDOStateManagerImpl.java:2009)
at org.datanucleus.store.mongodb.MongoDBPersistenceHandler.fetchObject(MongoDBPersistenceHandler.java:600)
at org.datanucleus.state.JDOStateManagerImpl.loadFieldsFromDatastore(JDOStateManagerImpl.java:1696)
at org.datanucleus.state.JDOStateManagerImpl.validate(JDOStateManagerImpl.java:3576)
at org.datanucleus.ObjectManagerImpl.findObject(ObjectManagerImpl.java:3246)
at org.datanucleus.api.jdo.JDOPersistenceManager.getObjectById(JDOPersistenceManager.java:1731)
at org.datanucleus.api.jdo.JDOPersistenceManager.getObjectById(JDOPersistenceManager.java:1749)
at com.myproject.server.GetRecordHandler.execute(GetRecordHandler.java:37)
Can anyone spot what the problem is?
Note: I know that DataNucleus 3.1.0-release is available, but I can't use it because of a problem with its enhancer.
UPDATE: I have done some further testing of this issue and it turns out that DataNucleus throws a NullPointerException
for those embedded
fields that are also marked as being in the defaultFetchGroup
and have a value of null
.
来源:https://stackoverflow.com/questions/11842527/nullpointerexception-in-jdopersistencemanager-getobjectbyid-using-datanucleus