Assigning String as Google App Engine Entity Key - google-app-engine

I searched a lot. Still I am not able to understand how to assign a String to Google App Engine Entity class id(Key).
So I have:
Key id;
And
setId(String id) {
// I know that here I can use id = KeyFactory.createKey("","");
}
But I don't know how to use createKey method here to assign my string to id. Please consider User here as my Entity class name.
P.S. I am using JPA.
Thank you.

Not sure of your entity is looking but this works well for me.,
#Entity
class Person{
#Id String personId;
String firstName;
}

Related

Google app engine, objectify how to order by a sub entity field?

I have a Course entity that contains the following field
#Index
private #Load
Ref<Student> student;
The student entity then has the field
#Index
private String matric;
I want to load all the Course entities sorted using the students matric number.
I have tried using the "." operator to get the sub field like this
ofy().load().type(Course.class).filter("course", course).order("student.matric").list();
but this return no result.
Is it possible to do this? how?
I don't think that is possible with objectify. I would let Course implement Comparable:
#Entity
public class Course implements Comparable<Course> {
.
.
.
#Override
public int compareTo(Course otherCourse) {
return this.getStudent().getMatric().compareTo(otherCourse.getStudent().getMatric());
}
}
Remove the "order" part of the Objectify load and use Collections.sort() instead:
List<Course> courses = ofy().load().type(Course.class).filter("course", course).list();
Collections.sort(courses);
There are no joins in the datastore. If you want to query your Courses by Student properties, you probably will need to denormalize the data into the Course and index it. This means changing the Student data will also require changing Courses.
As an aside: This data model is weird. Are you sure what you're calling Course isn't really an Enrollment?

Google App Engine Datastore how to get entity for Key<?>

I'm new to Datastore and now I'm developing Gae application with Datastore and Objectify. Entity class has the form
#Entity
public class MyClass1 {
public Key<MyClass2> field1;
#Id Long id;
and so on
}
MyClass2 has the form
#Entity
public class MyClass2 {
....
#Id public Long id;
#Index public String field2;
....
}
I have entity of MyClass1. How can I get the value of field2 ?
If I use DatastoreService1.get(myclass1.field1) I get
method get(Key) in the DatstoreService is not applicable for arguments (Key<MyClass2>)
Please help me
Your error doesn't really relate to the question, so I assume you want to get the value of field1, not field2.
The error is because the DatastoreService get() method expects a com.google.appengine.api.datastore.Key, but you are passing it a com.googlecode.objectifyKey<T>, which is an Objectify key - they're not the same thing. Here are the docs.
I would recommend using a Ref<MyClass2> as you can then just do something like:
MyClass2 myClass2 = myClass1.field1.get();
(using your code example).

Bean Validation and Objectify

I'm using Objectify to manage GAE Datastore persistence. I cannot find much useful documentation on Bean validation using Objectify. I tried using the Hibernate Validator, but it still allows me to persist invalid data.
To make things crystal clear, here's a simple example:
#Entity
public class Person {
#Id Long id;
// validate firstName is 1-20 characters, like Hibernate's #Length(min=1, max=20) annotation
#Index private String firstName;
// GETTERS & SETTERS
}
Any help is appreciated!

GAE jpa database model example

I am totally new at this, I am sorry if it is stupid question.
I am trying to design database model for Google App Engine in JPA, but I am unable to get it right. When I find the way I can't get annotations right or I am getting error about M:N not supported in Google App Engine.
I need entity user to have multiple groups and groups have multiple users and there are users who are also group admins.
My basic model was User -> usergroup(user; group; (bool)isAdmin) <-Group
Can somebody give a clean and simple example of how to define relationships?
Please try this.
#Entity
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Key id;
private String name;
#ManyToOne(fetch = FetchType.LAZY)
private UserGroup usergroup;
}
class userGroup
#Entity
public class UserGroup {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Key id;
private String name;
private boolean admin;
#OneToMany(mappedBy = "usergroup", cascade = CascadeType.ALL)
private List<User> users = new ArrayList<User>();
}
please be noticed GAE have limitation on JPA you can read more here
I don't know anything about Google App Engine, but I can help with JPA though.
The problem here is the "isAdmin" column, which prevents the data model to be a simple #ManyToMany relationship with a joiner table.
With the introduction of this field, in the data model you need a Map on the User entity with key=Group and value=isAdmin, similarly you need a corresponding Map in the Group entity in order to know if each User is an admin.
This is modeled with #ElementCollection in the following way:
#Entity
#Table(name="User")
public class User
{
#Id
#GeneratedValue(strategy= GenerationType.TABLE)
private int id;
private String name;
#ElementCollection
#CollectionTable(name="Users_Groups", joinColumns={#JoinColumn(name="userId")})
#MapKeyJoinColumn(name="groupId")
#Column(name="isAdmin")
private Map<Group, Boolean> groups;
}
#Entity
#Table(name="Group")
public class Group
{
#Id
#GeneratedValue(strategy= GenerationType.TABLE)
private int id;
private String name;
#ElementCollection
#CollectionTable(name="Users_Groups", joinColumns={#JoinColumn(name="groupId")})
#MapKeyJoinColumn(name="userId", insertable=false, updatable=false)
#Column(name="isAdmin", insertable=false, updatable=false)
private Map<User, Boolean> users;
}
The important annotation is #ElementCollection, the other annotations are just to name the specific columns of the collection table and make sure they match from both entities: #CollectionTable gives the name of the table and the name of the column representing the id in the current entity. #MapKeyJoinColumn gives the name of the column representing the id of the "key" element in the Map, and #Column gives the name of the "value" element in the map.
I'm not sure if the insertable=false and updatable=false are needed in one of the entities, might avoid adding duplicate rows due to the cyclic dependency between User and Group.
Also you need to manually create the collection table, because at least EclipseLink tries to create it with two "groupId" and "isAdmin" columns. You might consider reviewing the design if it is absolutely needed a cyclic dependency between User and Group.

Ancestor Query with Objectify not returning results

I am using objectify 3.1 on appengine and attempting to do a ancestor query. I want to fetch all the children of an object that are of a certain kind. Below is my code:
#Cached
#Entity
public class Car {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String make;
private String model;
}
#Cached
#Entity
public class Tire {
#Id
public String keyName;
#Parent Key<Car> car;
private String brand;
private String size;
}
My query is this code:
List<Tire> list= ofy.query(Tire.class).ancestor(new Key<Car(Car.class,carID))).list();
When I create the tire objects I use this code to set the relationship:
newTire.setCar(new Key<Car>(Car.class,Car.getID()));
I know the Parent relationship is there because I can query for it in the datastore admin and it shows the parent in the decoded entity key:
Decoded entity key: Car: id=135172 > Tire: name=myCarUniqueID
This query always returns 0 results, and it seems like I have followed all the best practices on the objectify website. Any help would be appreciated!
Your code looks ok, so the only thing that might be wrong is a non-existing carID.
The Objectify javadoc listed on the site is actually for trunk version which is a forthcoming Objectify 4. What you need to look at is Objectify 3.1 javadoc: this version has fetch() on the query.
Also, #GeneratedValue is not an Objectify annotation.

Resources