问题
I have two models, Book and Chapter, in a one-to-many relationship. I manually create the keys for both Book and Chapter. To persist, I create a book object then add an instance of chapter to it and then persist book. This works fine, as I see them in the datastore. Now when I try to fetch a chapter from the datastore by key, I get a null object.
Here is how the keys look in the datastore:
Under Book: name/id = 123 chapters = [Book(123)/Chapter("abc")]
Under Chapter: name/id = abc
I created my keys, both for creating and fetching objects, using
Key key = KeyFactory.createKey(Chapter.class.getSimpleName(), chapterId);
My fetching code is this:
Key key = KeyFactory.createKey(Chapter.class.getSimpleName(), chapterId);
Chapter chp = mgr.find(Chapter.class, key);//chp is always null (yes in debug mode as well)
UPDATE:
I try the same thing on Book and it works fine. So the problem is with Chapter. Perhaps it's because I saved Chapter through Book (but I see both in the datastore as mentioned above).
So the question is: Is there a way to retrieve chapter independently (by its key), if yes a code snippet please.
UPDATE source code:
@Entity
public class Book implements java.io.Serializable{
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Key key;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private List<Chapter> Chapters = new ArrayList<Chapter>();
public List<Chapter> getChapters() {
return Chapters;
}
public void setChapters(List<Chapter> Chapters) {
this.Chapters = Chapters;
}
public Book(long num, List<Chapter> Chapters) {
super();
Key key = KeyFactory.createKey(Book.class.getSimpleName(), num);
this.key = key;
this.Chapters = Chapters;
}
public Book(long num) {
super();
Key key = KeyFactory.createKey(Book.class.getSimpleName(), num);
this.key = key;
}
public Book() {
}
public Key getKey() {
return key;
}
public void setKey(Key key) {
this.key = key;
}
}
@Entity
public class Chapter implements java.io.Serializable{
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Key key;
private String content;
public Chapter(String ChapterId, String content) {
super();
Key key = KeyFactory.createKey(Chapter.class.getSimpleName(), ChapterId);
this.key = key;
this.content = content;
}
public Key getKey() {
return key;
}
public void setKey(Key key) {
this.key = key;
}
public String getContent() {
return content;
}
public void set content(String content) {
this.content = content;
}
}
Code for adding:
Book bk = new Book(num);
Chapter chp = new Chapter(ChapterId, content);
bk.getChapters().add(chp);
bookDao.put(bk);
mgr.persist(bk);
回答1:
I did not leave any vote, but you should provide more of the surrounding code. Things mostly look fine in the code you gave, but if you created the book/chapter in a transaction (which isn't shown), the chapter may have the book specified as a parent, and you didn't specify a parent when manually creating the chapter key.
回答2:
You must always include the parent entity key to retrieve the child entity. Here is how to create a key that includes the parent:
Key keyBook = KeyFactory.createKey(Book.class.getSimpleName(),
BOOK_ID);
Key keyChapter = KeyFactory.createKey(keyBook,
Chapter.class.getSimpleName(), CHAPTER_ID);
Chapter chp = mgr.find(Chapter.class, keyChapter);
hope this helps.
来源:https://stackoverflow.com/questions/15850386/got-null-when-querying-datastore-by-key