I will be very thankful if someone could help me to solve this problem
as I have already spent a lot of time on it.
The frontend of my application sends employee data to server end,
which creates Emmployee object and saves the data on datastore. My
application provides the keyword search functionality on title,
company and jobDesc so I am using Search Api.
The problem is that I want to use datastore for storing the complete
data and document for storing searchable data. How can I link
datastore with document? I know it can be achieved if I set employee’s
key as document id but the problem is how will I get the key of the
data which is being store. If I try to get key using e.getKey() that
obviously returns nullPointerException because it does have the key at
that time.
I can achieve this by reading all employee data stored on datastore
and creating document with it and setting employee’s key as document
id but I want to create document as the data is received from frontend
of application.
//EmployeeServlet
PersistenceManager pm = PMF.get().getPersistenceManager();
Employee e = new Employee(title, company, location, category,
jobType, gender,
careerLevel, salaryRange,
sector, jobDesc);
Document newDoc = Document.newBuilder().setId(???)
.addField(Field.newBuilder().setName("title").setText(title))
.addField(Field.newBuilder().setName("company").setText(company))
.addField(Field.newBuilder().setName("jobDesc").setText(jobDesc)).build();
SearchIndexManager.INSTANCE.indexDocument("Employee", newDoc);
pm.makePersistent(e);
//Employee
#PersistenceCapable
public class Employee {
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key key;
#Persistent
private String title;
#Persistent
private String company;
#Persistent
private String location;
#Persistent
private String category;
#Persistent
private String jobType;
#Persistent
private String gender;
#Persistent
private String careerLevel;
#Persistent
private String salaryRange;
#Persistent
private String sector;
#Persistent
private Text jobDescription;
public Employee(String title, String company, String location,
String category,
String jobType, String gender,
String careerLevel, String salaryRange,
String sector,
String jobDescription) {
super();
this.title = title;
this.company = company;
this.location = location;
this.category = category;
this.jobType = jobType;
this.gender = gender;
this.careerLevel = careerLevel;
this.salaryRange = salaryRange;
this.sector = sector;
this.jobDescription = new Text(jobDescription);
}
}
Save employee entity. Get the id.
Set this id as a document id, index the document.
Both steps can be done in the same server call. Just move your makePersistent() before you create a document.
Related
I have document user and document adventureHolidays. There is a lot of users and as well adventure holidays. So far I created a controller that return me a random element from adventureHolidays document. On that page I have button to randomize again and on each click new document from adventureHoliday is provided. What is my goal right now? I want to create a button that will actually save a current document that is provided as field in user document, so he can see on his profile which adventureHolidays he has saved.
This is user entity
#Document
public class User {
#Id
private String id;
#Indexed(unique = true)
#NonNull
private String username;
#Indexed(unique = true)
#NonNull
private String email;
#JsonIgnore
#NonNull
private String password;
#DBRef
private List<AdventureHolidays> adventureHolidaysList;
And this is AdventureHoldiays
#Document("adventureholidays")
public class AdventureHolidays {
#Id
private String id;
private String title;
private String description;
private String state;
private String typeOfAdventureHolidays;
private String image;
How I can now save document that is random returned to user to user entity? I even dont know where to start. Guess I need ID and that to save somehow it to field in user document
I have those two entites:
#Document
public class User {
#Id
private String id;
#Indexed(unique = true)
#NonNull
private String username;
#Indexed(unique = true)
#NonNull
private String email;
#JsonIgnore
#NonNull
private String password;
#Document("adventureholidays")
public class AdventureHolidays {
#Id
private String id;
private String title;
private String description;
private String state;
private String typeOfAdventureHolidays;
private String image;
I want to create a service that will save into user document element from adventureholidays.
I have a service to return a random element from adventureholidays document, so If user want to save that document I would like to save title of that document into user document.
So somehow I need to take a ID of current adventureholiday that is provided and then to save to current logged user.
I am just giving you the logic, add
#DBRef
private AdventureHolidays adventureHolidays;
in your User class it will map both classes, then get the id of holiday from the save button using link or value from your form and then using that id in find() function and fetch the data of that particular holiday store it in a object ie. holiday.
Now just save it in service class inside a method like this:
User user=new User();
user.setAdventureHolidays(holiday);
// create a userRepository which extends MongoRepository
userRepository.save(user);
I'm building an application with Google App Engine. I'm using Objectify for Datastore persistence. I have two POJO class.
#Entity
public class Book
{
#Id private Long id;
private String name;
private String isbn;
private String author;
}
and
#Entity
public class Person {
#Id private String email;
private String password;
private String name;
private List<Book> myBooks;
}
A person can contain many books but book only belongs to one person. Currently I'm saving data like this.
//data from Front-end
Person p = new Person(email, password, name);
PersonDAO dao = new PersonDAO();
dao.save(p);
//...
//data from Front-end
Book b = new Book(name, author, isbn);
BookDAO daoBook = new BookDAO();
daoBook.save(b);
//...
Person q = dao.load(email);
q.addBook(b);
dao.save(q);
ObjectifyService ofy() with methods are implemented in DAO classes.
It's ok my implementation? How can I optimize the relationship? Every time that I need create a book this is saved like Entity but I need the relationship with a person, therefore I'm saving book twice. I've seen implementantions with Key, Ref #Load tags but I don't know how are working them.
Besides, Person POJO has a Date field. will It be saved normally?
It has being quite a while since I wrote this code, but here it goes:
#Entity
public class Book {
#Id
private Long id;
#Parent
#ApiResourceProperty(ignored = AnnotationBoolean.TRUE)
private Key<User> user;
private String author;
private String isbn;
private String name;
}
Take a look at Udacity Conference Central for full example. It is the final project of Developing Scalable Apps in Java
with Google App Engine, by Udacity.
I'm trying to store in the GAE DB a class which some of its fields are classes themselves.
Just before going into more details I want to say it worked just fine before I added these new class field.
So, I followed the documentation here: https://developers.google.com/appengine/docs/java/datastore/jdo/dataclasses
and I'm getting this error :
org.datanucleus.jdo.exceptions.ClassNotPersistenceCapableException: The class "The class "sporteam.web.client.User" is not persistable. This means that it either hasnt been enhanced, or that the enhanced version of the file is not in the CLASSPATH (or is hidden by an unenhanced version), or the Meta-Data/annotations for the class are not found." is not persistable. This means that it either hasnt been enhanced, or that the enhanced version of the file is not in the CLASSPATH (or is hidden by an unenhanced version), or the Meta-Data for the class is not found.
The main class I'm trying to use is User:
#SuppressWarnings("serial")
#PersistenceCapable(identityType = IdentityType.APPLICATION)
public class User implements Serializable
{
// data members
// user unique facebook id
#Persistent
#PrimaryKey
private String facebook_id;
// users facebook code
#Persistent
private String facebook_code;
// users device ID code
#Persistent
private String dev_id;
// users registration ID code
#Persistent
private String reg_id;
// user first name
#Persistent
private String first_name;
// user last name
#Persistent
private String last_name;
// user age, should be grater then 8
#Persistent
private int age;
// user email, as setup in facebook
#Persistent
private String email;
// user weight, should be greater then 40
#Persistent
private double weight;
// user workout_level (0.8 is the highest(best shape) and 1 is the lowest)
#Persistent
private double workout_level;
// user gender ("male"/"female"/"unknown")
#Persistent
private String gender;
#Persistent
#Embedded
private UserTracks userTracks = null;
// default constructor
public User()
{
}
//....
}
This is the UserTracks class:
#PersistenceCapable
#EmbeddedOnly
#SuppressWarnings("serial")
public class UserTracks implements Serializable
{
#Persistent
#Embedded
//#Element(embedded="true")
private List<Track> tracks = null;
#Persistent
private long date = 0;
public UserTracks()
{
}
}
And theses are the other 2 classes used:
#PersistenceCapable
#EmbeddedOnly
#SuppressWarnings("serial")
public class Track implements Serializable
{
/** running information **/
#Persistent
private double avgSpeed = 0;
#Persistent
private double distance = 0;
#Persistent
private double calories = 0;
#Persistent
private long time = 0;
/************************/
#Persistent
private long date = 0;
#Persistent
private String name = null;
#Persistent
#Embedded
private List<GeoPtr> track = null;
public Track()
{ // needed for Serializable
}
}
GeoPtr:
#PersistenceCapable
#EmbeddedOnly
#SuppressWarnings("serial")
public class GeoPtr implements Serializable
{
/** the speed is in m/s **/
#Persistent
float speed;
#Persistent
long time;
#Persistent
double altitude;
#Persistent
double latitude;
#Persistent
double longitude;
#Persistent
double calorie = 0;
public GeoPtr()
{ //needed for Serializable
}
}
As far as I can see, every class is PersistenceCapable and all the fields are either PersistenceCapable themselves or a collection of it and according to the documentation above it should work.
Ideas?
Thanks
You try to use embedded class Track to store collection of GeoPtr to UserTracks. How DataStore will handle it? When embedding into UserTracks fields of GeoPtr added to common single record in DataStore. You will have:
avgSpeed, distance, ...., speed, time
What DataStore should do in collection case?
avgSpeed, distance, ...., speed_1, time_1, ..., speed_2, time_2, ... speed_N, time_N
???
Is this make any sence?
Don't use embedded. Create three separate classes with primary keys. Use one-to-one relationship for User - UserTracks and one-to-many for UserTracks - GeoPtr.
Read about relations here
Well apparently there is some problem with embedding a collection of user defined classes.
I've read somewhere that its not possible to embed a collection field that has an embedded collection field itself. However, you can achieve almost the same by serializing these fields (you wont be able to index them - that's the difference between serialized to embedded, but I don't need indexes on these fields for my use so it worked out just fine) you can do so by using the next notation :
#Persistent(serialized = "true")
Hoped it will save all of you the pain I've been through.
Bar.
I have just one week experience in GAE/Java and trying to port an legacy application(developed using PHP/MySQL) to GAE+JDO. I'm now stuck with a basic issue in creating a relationship between two tables(kinds in GAE).
So here is the case:
We have a Users table which holds the user authentication information. It also has a field user_role which store role_id, which is actually a foreign key of another table user_roles.
From the the Entity-Relationship documentation in GAE, I understand that DataStore doesn't support foreign-key relationships and designed the Users class by adapting the Employee-ContactInfo example in the docs.
When I executed the application, the user_roles kind is inserted each time I add an entry in Users table. The user_roles kind is supposed to have only three static values. But this is having redundant values as I input more records in Users.
I think that I'm missing something very trivial, but I couldn't figure it out due to my inexperience to datastore. It would be very nice if someone could guide me to solve this issue.
Here is the code:
#PersistenceCapable(identityType = IdentityType.APPLICATION)
public class Users {
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key key;
#Persistent
private String userName;
#Persistent
private String password;
#Persistent
private String salt;
#Persistent
private Date createdDate;
#Persistent
private Key createdBy;
#Persistent
private Date lastLogin;
#Persistent
private boolean status;
#Persistent
private String authKey;
#Persistent(defaultFetchGroup="true")
private SecurityRole securityRole;
#Autowired
SecurityRepository securityRepository ;
public SecurityPrincipals(String userName, String password,SecurityRole securityRole,boolean status) {
this.securityRole = securityRole;
this.userName = userName;
this.password = password;
this.status = status;
}
//getters and setters
}
Definition for Roles:
#PersistenceCapable(detachable="true")
public class SecurityRole {
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key key;
#Persistent
private String securityRoleName;
#Persistent
private String securityRoleDescription;
#Persistent
private String securityRoleStatus;
#Persistent
private Date securityRoleCreatedDate;
public SecurityRole(String securityRoleName, String securityRoleDescription, String securityRoleStatus,String securityBaseType)
{
this.securityRoleName = securityRoleName;
this.securityRoleDescription = securityRoleDescription;
this.securityRoleStatus = securityRoleStatus;
this.securityBaseType = securityBaseType;
}
// getters and setters
}
The relevant code from Controller:
SecurityRole securityRole = securityRepository.getSecurityRole( securityRoleName);
users = new Users(userName,password,status,securityRole);
iUserRepository.save(employeeDetails);
Here is the definition of getSecurityRole:
public SecurityRole getSecurityRole(String securityRoleName)
{
PersistenceManagerFactory pmf = this.jdoTemplate.getPersistenceManagerFactory();
PersistenceManager pm = pmf.getPersistenceManager();
try {
Query query = pm.newQuery( SecurityRole.class);
query.declareImports("import java.lang.String");
query.declareParameters("String securityRoleName");
query.setFilter("this.securityRoleName == securityRoleName");
List<SecurityRole> securityRoles = (List<SecurityRole>)query.execute(new String(securityRoleName));
SecurityRole temp = null;
for(SecurityRole securityRole: securityRoles)
{
temp = securityRole;
}
return temp;
}
finally {
pm.close();
}
}
Here is the definition of iUserRepository.save():
public void save(Users user) {
jdoTemplate.makePersistent(companyDetails);
}
In the Users class, you have the defined the property
#Persistent(defaultFetchGroup="true")
private SecurityRole securityRole;
This statement creates an "owned" relationship in GAE datastore, which means that when you create an object of the Users class, an object of the SecurityRole class will be created as well.
What you need, is an unowned relationship that can be created as follows:
#Persistent(defaultFetchGroup="true")
private Key securityRole;
In this way, a SecurityRole object is not created each time you create an instance of the Users class. For more information about owned and unowned relationships, take a look at http://code.google.com/appengine/docs/java/datastore/jdo/relationships.html
Hope this helps!