سؤال

I'm trying to write an application for the google app engine using Objectify and am having some trouble. I'm new to noSQL datastores so it's probably a conceptual problem.

I have an entity called a message, and each message has a from User - the user who created the message.

@Entity
public class Message {


@Index private Key<User> fromUserKey;
@IgnoreSave private  User fromUser;

Annoyingly, I have to have both a User and a Key field in the message. JSON needs the User object to populate the response with useful fields, and the google app engine needs the Key to be able to store the reference to the user. The @IgnoreSave annotation is used to stop Objectify asking the google app engine to try to store the User object (which will fail).

When fetching messages, the from user key is populated, but the from User object is not. Here's what the DAO code looks like for my "getMessages" operation:

    public static List<Message> getSentMessages(long userId) {
    List<Message> result;
    result= ofy().load().type(Message.class).filter("from", Key.create(User.class, userId)).limit(1000).list();
    return result;
}

But the fromUser object is not populated on each Message, only the fromUserKey. How do I get the actual User object populated in the response? I need to access such fields as forename, surname, etc - not just the ID of the User. I could get the from User from the DB, loop through the results, then call setFromUSer on each message, but it's ugly. And it also causes a ConcurrentModificationException...

I'm sure I'm doing something wrong here, but I can't work out what.

هل كانت مفيدة؟

المحلول

What you can do is have a property Ref<User> on the Message entity and annotate it with '@Parent'. This means that each Message entity will become part of the user's entity group. The Ref<?> works like a key but allows you to directly access the actual entity object; that way you can easily get the forename, surname etc.

Change your class as follows:

@Entity
@Cache
public class Message
{
    @Id Long id;
    @Load @Parent private Ref<User> user;

    public User getUser() { return this.user.get(); }
    public void setUser(User value) { this.user = Ref.Create(value); }
}

Having done that, you will be able to perform ancestor queries to retrieve all the message entities associated with a particular user:

public static List<Message> getSentMessages(long userId) 
{
    User parent = ofy().load().type(User.class).id(userId).now();
    List<Message> results = ofy().load().type(Message.class).ancestor(parent).limit(1000).list();   
    return results;
}

You should now be able to do what you wanted, and hopefully not get any more errors.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top