Я довольно долго боролся с проблемой и, полагаю, я просто еще не до конца понимаю, как работает GAE Datastore.
У меня есть следующая сущность (я удалил ненужный для вопроса код)
@Entity
public class Post{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long Id;
//info
private String title;
//comments
@OneToMany(fetch = FetchType.LAZY,mappedBy = "post")
private List<Comment> comments;
//getter and setters...
}
А также следующий объект:
@Entity
public class Comment {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Key key;
@ManyToOne(fetch = FetchType.LAZY)
private Vibe vibe; // vibe id
//getters and setters...
}
Пока все хорошо ... я использую конечные точки, и у меня уже есть несколько функций, которые работают правильно, если я хочу добавить новый пост или опубликовать новый комментарий к сообщению, у меня проблемы только тогда, когда я хочу получить список всех комментариев к конкретному посту - как для доступа к Post.getComments ();
Я использую fetch = FetchType.LAZY, потому что в некоторых случаях я просто хочу получить все сообщения в моей базе данных без комментариев, например, чтобы показать их в каком-то виде индекса.
Например, когда я пробую это:
@ApiMethod(name = "getPostComments")
public List<Comment> getPostComments(@Named("postId") Long postId) {
EntityManager mgr = getEntityManager();
List<Comment> results = new ArrayList<Comment>();
try {
Post p = mgr.find(Post.class, postId);
if (p == null) {
throw new EntityNotFoundException("Post does not exist");
} else {
results = p.getComments();
}
} finally {
mgr.close();
}
return results;
}
Я получаю ошибку неверного запроса 400 с java.lang.IllegalArgumentException
Я пробовал всевозможные способы, но безуспешно, и все решения, которые я нашел, говорили, что я должен использовать fetch = FetchType.EAGER, чего я не хочу, и, честно говоря, создается впечатление, что тип LAZY бесполезен. так очевидно я что-то упускаю! пожалуйста помоги! если бы вы могли написать пример для получения списка, было бы здорово!
1 ответ
В конечном итоге моими решениями было создать новый тип объекта, который не имел никаких ссылок на ленивый загруженный внутренний объект, и скопировать в него нужную информацию, а затем вернуть ее.
В этом примере я сделал следующее: новый класс CommentResults:
public class CommentResults{
private String message;
private Long userId;
//getters and setters...
}
Мой новый метод getComments будет выглядеть так:
@ApiMethod(name = "getPostComments")
public List<CommentResults> getPostComments(@Named("postId") Long postId) {
EntityManager mgr = getEntityManager();
List<CommentResults> results = new ArrayList<Comment>();
try {
Post p = mgr.find(Post.class, postId);
if (p == null) {
throw new EntityNotFoundException("Post does not exist");
} else {
for(Comment c:p.getComments()){ //copying the data
CommentResults cr = new CommentResults();
cr.setMessage(c.getMessage);
cr.setUserId(c.getUserId);
results.add(cr);
}
}
} finally {
mgr.close();
}
return results;
}
Я все еще не уверен, что это лучшее решение, необходимость создавать новый объект и копировать информацию по каждому запросу кажется большой задачей для всего одного запроса к серверу, но сейчас это работает, если вы знаете более элегантное решение, поделитесь !
Похожие вопросы
Новые вопросы
java
Java — это высокоуровневый объектно-ориентированный язык программирования. Используйте этот тег, если у вас возникли проблемы с использованием или пониманием самого языка. Этот тег часто используется вместе с другими тегами для библиотек и/или фреймворков, используемых разработчиками Java.