0
votes

I'm trying to return an entity (Room) from Google App Engine datastore, using endpoints. This method (auto-generated) returns all entities in the datastore:

    @SuppressWarnings({ "unchecked", "unused" })
public CollectionResponse<Room> listRoom(
        @Nullable @Named("cursor") String cursorString,
        @Nullable @Named("limit") Integer limit) {

    EntityManager mgr = null;
    Cursor cursor = null;
    List<Room> execute = null;

    try {
        mgr = getEntityManager();
        Query query = mgr.createQuery("select from Room as Room");
        if (cursorString != null && cursorString != "") {
            cursor = Cursor.fromWebSafeString(cursorString);
            query.setHint(JPACursorHelper.CURSOR_HINT, cursor);
        }

        if (limit != null) {
            query.setFirstResult(0);
            query.setMaxResults(limit);
        }

        execute = (List<Room>) query.getResultList();
        cursor = JPACursorHelper.getCursor(execute);
        if (cursor != null)
            cursorString = cursor.toWebSafeString();

        // Tight loop for fetching all entities from datastore and accomodate
        // for lazy fetch.
        for (Room obj : execute)
            ;
    } finally {
        mgr.close();
    }

    return CollectionResponse.<Room> builder().setItems(execute)
            .setNextPageToken(cursorString).build();
}

I want to edit this so it only returns one entity based on a property, a string. So I'll pass the string in as a parameter, find it in the datastore and return it. The string will not be the primary key.

EDIT:

Trying this but still doesn't work:

        public Room getRoom(@Named("id") String mac) {
    EntityManager mgr = null;
    Room room = null;
    try {
        mgr = getEntityManager();
        Query query = mgr.createQuery("SELECT * FROM Room WHERE mac_adds IN ('"+mac+"')");
        room = (Room) query.getSingleResult();
    } finally {
        mgr.close();
    }
    return room;
}

Any help appreciated.

Thanks,

2

2 Answers

2
votes

You may try to replace:

    for (Room obj : execute)
        ;

with

    for (Room obj : execute) {
        if( obj.your_property.equal(your_string) ) {
            // do something with new found `obj`, maybe return it
        }
    }

also you most probably don't need the CollectionResponse return at the end of the function.

0
votes

I had a similar issue and the way I solved it was as followed

I created a new API method in the endpoint class. In my case I had to fetch row(s) corresponding to specific email address from a userTable entity class. So I passed on emailAddress as a String parameter to the API Method I has added in the endpoint class. I the example below emaiAddress was not the primary key for my entity.

@SuppressWarnings({ "unchecked", "unused" })
@ApiMethod(name = "getUserTableByEmail")
public CollectionResponse<UserTable> getUserTableByEmail(
        @Nullable @Named("cursor") String cursorString,
        @Nullable @Named("limit") Integer limit,
        @Named ("emailAddress") String email) {

    EntityManager mgr = null;
    Cursor cursor = null;
    List<UserTable> execute = null;

    try {
        mgr = getEntityManager();
        Query query = mgr.createQuery("select n from UserTable n where n.emailAddress = '"+email+"'");
        if (cursorString != null && cursorString != "") {
            cursor = Cursor.fromWebSafeString(cursorString);
            query.setHint(JPACursorHelper.CURSOR_HINT, cursor);
        }

        if (limit != null) {
            query.setFirstResult(0);
            query.setMaxResults(limit);
        }

        execute = (List<UserTable>) query.getResultList();
        cursor = JPACursorHelper.getCursor(execute);
        if (cursor != null)
            cursorString = cursor.toWebSafeString();

        for (UserTable obj : execute)
            ;
    } finally {
        mgr.close();
    }

    return CollectionResponse.<UserTable> builder().setItems(execute)
            .setNextPageToken(cursorString).build();
}

Note one thing however. I still used the method to return a CollectionResponse object, you can very well return just a userTable(entity) object if you are sure that there is only one row returned with your select criteria. I my android code, I user CollectionResponse.isEmpty() to check if there was anything returned, if it was returning rows then ii used the method CollectionResponse.getItem() to retrieve the rows. If you want the query to return only one result then you can specify the Integer parameter "limit" as 1 while executing the endpoint method in your android code or just put query.setMaxResults(1); in the method above.