我使用DataNucleus 3.0.0发布的JDO实现将我的Java应用程序连接到MongoDB。
我的CLASSPATH中的相关JAR如下:
我坚持的课程如下:
@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);
}
...
}
CustomLocation
类:
@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
}
...
}
尝试从DB获取对象的代码如下:
PersistenceManager pm = MyPersistenceManagerFactory.get().getPersistenceManager();
Record record = null;
try {
record = pm.getObjectById(Record.class, recordId);
}
catch (JDOObjectNotFoundException onfe) {
// handle
}
catch (Exception e) {
// handle
}
以下是产生的错误:
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)
有人能发现问题所在吗?
注意:我知道DataNucleus 3.1.0版本可用,但由于problem with its enhancer我无法使用它。
更新:我已经对此问题进行了一些进一步的测试,结果发现DataNucleus会为那些也标记为“{1}”字段的NullPointerException
字段投放embedded
defaultFetchGroup
,其值为null
。