Rakesh Rakesh - 3 months ago 35
Java Question

Objectify filter entities with parent key

I have written a piece of code that fetches entities from google datastore by filtering the entity with the supplied parent key. When I run the code I am getting

java.lang.IllegalArgumentException
.

I know the problem is with the way I am creating the parent key, can you please guide me how to effectively create a parent key for this use case?

I am getting the below exception in
Myservice.java
line 8

Method threw 'java.lang.IllegalArgumentException' exception
- Class hierarchy for class java.lang.Class has no @Entity annotation


Appengine v1.9.36,
Objectify v5.1.7,
JDK v1.7


Below is a sample code

import com.googlecode.objectify.Key;
import com.googlecode.objectify.annotation.Cache;
import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Id;

@Entity
@Cache
public class ParentEntity {

@Id
Long id;

String name;

String value;

public static Key<ParentEntity> getKey(Long id){
return Key.create(ParentEntity.class, id);
}

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getValue() {
return value;
}

public void setValue(String value) {
this.value = value;
}
}


Another entity class

import com.googlecode.objectify.Key;
import com.googlecode.objectify.annotation.Cache;
import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Id;
import com.googlecode.objectify.annotation.Parent;

@Entity
@Cache
public class ChildEntity {

@Id
Long id;

@Parent Key<ParentEntity> application;

String city;

public static Key<ChildEntity> getKey(Long id){
return Key.create(Key.create(ParentEntity.class), ChildEntity.class, id);
}

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public Key<ParentEntity> getApplication() {
return application;
}

public void setApplication(Key<ParentEntity> application) {
this.application = application;
}

public String getCity() {
return city;
}

public void setCity(String city) {
this.city = city;
}
}


ServiceLaver that uses Objectify to fetch entities

import java.util.List;
import com.googlecode.objectify.ObjectifyService;

public class MyService{

public List<ChildEntity> filterByID(Long id){
return ObjectifyService.ofy().load().type(ChildEntity.class)
.filterKey(ChildEntity.getKey(id)).first().now();
}
}

Answer

change Your ParentEntity's method :

public static Key<ParentEntity> getKey(Long id){
            return Key.create(ParentEntity.class, id);
        }

to:

 public String getWebSafeKey(){
                    return Key.create(ParentEntity.class, id).getString();
            }

Now when you insert a parent entity then in response it will give you websafe key of that parent entity. Use this websafe key whenever you wants to access this inserted parent entity.

After that change:

public List<ChildEntity> filterByID(Long id){
        return ObjectifyService.ofy().load().type(ChildEntity.class)
            .filterKey(ChildEntity.getKey(id)).first().now();
    }

To:

public List<ChildEntity> filterByID(String parentWebSafeKey){
        return ObjectifyService.ofy().load().type(ChildEntity.class)
            .ancestor(Key.create(parentWebSafeKey)).first().now();
    }

Don't forget to create relationship between ParentEntity and ChildEntity while creating child entity using:

child_entity.application = Ref.create(parent_entity_key);