Я довольно долго боролся с проблемой и, полагаю, я просто еще не до конца понимаю, как работает 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 бесполезен. так очевидно я что-то упускаю! пожалуйста помоги! если бы вы могли написать пример для получения списка, было бы здорово!

0
Dan Levin 9 Окт 2013 в 17:30
В чем конкретно проблема?
 – 
Dev
9 Окт 2013 в 17:38
Эй, я обновил квест, в основном я просто хочу знать, как это сделать правильно. Благодарность
 – 
Dan Levin
9 Окт 2013 в 18:45

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;
}

Я все еще не уверен, что это лучшее решение, необходимость создавать новый объект и копировать информацию по каждому запросу кажется большой задачей для всего одного запроса к серверу, но сейчас это работает, если вы знаете более элегантное решение, поделитесь !

0
Dan Levin 10 Окт 2013 в 12:08