GAE get Data using JDO with key - google-app-engine

I created Key with my unicue ID, and save into the database.
GoogleDrivePDF pdf = new GoogleDrivePDF();
key= KeyFactory.createKey(GoogleDrivePDF.class.getSimpleName(),"0B1IQEoiXFg3IWHhJNEtlMzlvQWs");
pdf.setKey(key);
pdf.setPdfName("NAME");
everything works!
But know I have one problem.
In order to get my Object From Db I must need Key string.
GoogleDrivePDF pdf = pm.getObjectById(GoogleDrivePDF.class, "agtsdHYtY2hlY2tlcnJoCxIRVXNlcnNQREZEb2N1bWVudHMiIXZha2h0YW5nLmtvcm9naGxpc2h2aWxpQGdtYWlsLmNvbQwLEg5Hb29nbGVEcml2ZVBERiIcMEIxSVFFb2lYRmczSVdIaEpORXRsTXpsdlFXcww");
how to create that key? I think it is enycrypted key. How can I now get this object?
P.S I think because of I have one to many relationship, that may does not work. Because When I create that pdf without 1:N it gets object very well. But I cant get another datas, which are in 1:N
I have that error:
Could not retrieve entity of kind GoogleDrivePDF with key GoogleDrivePDF("0ByMb_8ccYJRFOS1ibmFtamZ1b2M")
org.datanucleus.exceptions.NucleusObjectNotFoundException: Could not retrieve entity of kind GoogleDrivePDF with key GoogleDrivePDF("0ByMb_8ccYJRFOS1ibmFtamZ1b2M")

If you want to create a Key based on some other field of your Entity (say, for instance, a field called uniqueID), you should do something like this:
Persisting:
GoogleDrivePDF pdf = new GoogleDrivePDF();
pdf.setUniqueID("0B1IQEoiXFg3IWHhJNEtlMzlvQWs");
Key key = KeyFactory.createKey(GoogleDrivePDF.class.getSimpleName(),pdf.getUniqueID());
pdf.setKey(key);
pm.makePersistent(pdf);
BTW, it is generally not a good choice to make the key field publicly accessible. I think it is better to put the code for the creation of the key inside a specific constructor, like
public GoogleDrivePDF(String uniqueID) {
this.setUniqueID(uniqueID);
this.key = KeyFactory.createKey(GoogleDrivePDF.class.getSimpleName(),uniqueID);
}
Retrieving:
String idToBeRetrieved = "0B1IQEoiXFg3IWHhJNEtlMzlvQWs";
Key key = KeyFactory.createKey(GoogleDrivePDF.class.getSimpleName(),idToBeRetrieved);
pm.getObjectById(GoogleDrivePDF.class, key);

Solution was Unowned:
#Unowned
#Persistent
private Map <String,GoogleDrivePDF > pdfs;

Related

Appengine entity update not working

I am developing code for app engine. I tried to update an existing row by updating the same entity returned as result of query. But it creates new row instead of updating the same row. Following is the code:
public boolean updateProfile(DbProfile profile) {
Transaction txn = _datastore.beginTransaction();
Entity entity = getProfileEntity(profile.getLoginId());
if (entity != null) {
entity.setProperty(DbProfile.DbProfilePropertyNames.address, profile.getAddress());
entity.setProperty(DbProfile.DbProfilePropertyNames.name, profile.getName());
Key key = _datastore.put(entity);
txn.commit();
return true;
}
return false;
}
private Entity getProfileEntity(String userName) {
Key eRecommendationKey = KeyFactory.createKey("eRecommendation", _dbKeyName);
FilterPredicate predicateUsername =
new FilterPredicate(DbProfile.DbProfilePropertyNames.loginId, FilterOperator.EQUAL,
userName.toUpperCase());
Query query =
new Query(DbProfile.entityProfileName, eRecommendationKey).setFilter(predicateUsername);
List<Entity> profiles =
_datastore.prepare(query).asList(FetchOptions.Builder.withDefaults());
Utils.log.log( Level.SEVERE, "not found"+profiles.size() );
if (profiles.size() == 0) {
//profile data is not set yet
return null;
} else {
return profiles.get(0);
}
}
Following image shows fields in the entity.
Please let me know how can I fix the issue.
My Java skills are not too good, so I find it difficult to understand your code sample. I also don't see where updateProfile() is called and how your code is getting or constructing the profile object, especially whether the key of the profile object is altered.
But in general, if new entities are created instead of updating existing entities, the reason is that the key at your updating commit is different from the actual key of the existing entity.
Typical situations:
a string (key-name) is used instead of an integer (ID), or vice versa
a typo in the kind name of the key
different namespace or app properties of the key
parents are missing in the key path or are constructed wrongly
Suggestion:
In datastore viewer, compare the key of an existing entity with the key of the accidentally created entity. The difference between both keys might give you a hint where to look in your code for the bug.
I solved the problem. It was my mistake. I had called saveData servlet instead of updateProfile servlet.

Find an object by ID that has a key member only

Im trying to query an object by ID that dosent have an ID field.
Doing key.getId() does return a number but will not work when using
//will not work due to parenting object
pm.getObjectById("EventModel", 5322);
public class EventModel extends Model
{
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
protected Key key;
...
}
NOTE: this is object is parented by a different object
i tried to query using "key.id == idParam" and it fails because the object key is not embedded is there any way to make this work so i can query the object by id not just only the key
A workaround will be to save the an id field after the key is initiazlied and query it
but this adds 2 writes each time i create an object.
If you have any idea on how to make this work please share :)
Thanks

Add field to App Engine-hosted database

I'm currently developing a mobile application who uses a Google App Engine-hosted web service.
But i'm facing an issue. I just want to add a field in one my database's table.
App Engine doesn't use classic SQL syntax, but GQL. So i cannot use the ALTER TABLE statement. How can i do this with GQL ? I looked for a solution on the web, but there's not a lot of help.
public MyEntity() {
}
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Key idStation;
private String name;
private double longitude;
private double latitude;
private java.util.Date dateRefresh = new Date(); //the field i want to add in DB
So, now when i create a "MyEntity" object, it should add the "dateRefresh" field into the database... I create my object like this:
MyEntity station = new MyEntity();
station.setName("test");
station.setLatitude(0);
station.setLongitude(0);
station.setDateRefresh(new Date("01/01/1980"));
DaoFactory.getStationDao().addStation(station);
addStation method:
#Override
public MyEntity addStation(MyEntity station) {
EntityManager em = PersistenceManager.getEntityManagerFactory().createEntityManager();
try {
em.getTransaction().begin();
em.persist(station);
em.getTransaction().commit();
} finally {
if(em.getTransaction().isActive()) em.getTransaction().rollback();
em.close();
}
return station;
}
The field "dateRefresh" is never created into my DB...
Someone to help me please ?
Thanks in advance
Just add another field to your data structure, maybe providing a default clause, and that's all. For example, if you have a UserAccount:
class UserAccount(db.Model):
user = db.UserProperty()
user_id = db.StringProperty()
you may easily add:
class UserAccount(db.Model):
user = db.UserProperty()
user_id = db.StringProperty()
extra_info = db.IntegerProperty(default=0)
timezone = db.StringProperty(default="UTC")
and let it go.
While the datastore kinda mimics tables, data is stored on a per entity basis. There is no schema or table.
All you need to do is update your model class, and new entities will be saved with the structure (fields) of the new entity.
Old entities and indexes, however, are not automatically updated. They still have the same fields as they had when they were originally written to the datastore.
There's two ways to do this. One is to make sure your code can handle situations where your new properties are missing, ie make sure no exceptions are thrown, or handle the exceptions properly when you're missing the properties.
The second way is to write a little function (usu a mapreduce function) to update every entity with appropriate or null values for your new properties.
Note that indexes are not updated unless the entity is written. So if you add a new indexed property, old entities won't show up when you query for the new property. In this case, you must use the second method and update all the entities in the datastore so that they are indexed.

JDO-GAE Key getting created even when IdGeneratorStrategy.IDENTITY is commented

I have the following code,
public class UserAccount {
#PrimaryKey
#Persistent
private Long id;
....
so, creating the primary key via code, but when I view the datastore viewer through
http://localhost:8888/_ah/admin , I see key got populated via datastore (some encoded key). Is this an expected behavior ?. The problem however is when I try to connect my child objects with the parent objects. Thanks alot.
Yes, it's absolutely expected. For more info take a look at JDO Keys

Entity object : Cloning and Inserting

I am trying to clone/copy an entity object and insert it to the DB. I am using Entity Framework.
I found several similar question here and over other forums. Though the exact issue, None of the solution worked for me.
Application orginalApp = new Application().GetById(origAppId);
Application clonedApp = orginalApp.Clone<Application>(); //uses DataContractSerializer
DataBaseContext.Current.Detach(orginalApp); // Current is a property which returns Database context which is stored in httpcontext.current.items
clonedApp.EntityKey = null; // tried with and without this
clonedApp.Application_Id = 0; // tried with and without this. This is the primary key
clonedApp.Application_Name += " (clone)";
clonedApp.Create(); //The usual Addobject and SaveChange()
This throws the following error:
An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key.
I tried to check for existance of the object in object state manager.
DataBaseContext.Current.ObjectStateManager.GetObjectStateEntry(clonedApp)
It give me Null.
* Though, I couldnt find a solution, got to a workaround for the requirement using reflection.*
This error says that you have the same primary key for your new object as you did for your old one, if you are cloning rows, you will need a new PK for the cloned row

Resources