Query by setting parameter for mapped entity in JPA - google-app-engine

My project has two entities User and Item in one to many relationship. The paent User entity is mapped by field "owner" in Item entity which is annotated with Fetchtype.LazyLoad.
Item entity:
Item{
//other fields..
#Manytoone(#FetchType=LazyLoad)
User owner;
//getters and setters...
}
Now I am querying to get items whose parent user entity has gender set to Female like below:
String queryString="Select i from Item AS i where i.owner.gender='Female'"
Query q=QueryFactory.createQuery(queryString);
List<Item> result=q.getResultList();
My question is whether such kind of query is possible?If so, is the annotation LAZYLOAD will have any affect in getting results, since in my understanding,owner field will not be loaded implicitly when loading the Item entities.

GAE does not allow joins, as said in your comments. If you try that you should get an error.
The log should be enabled using standard log4j (internet search its docs) or java.util.logging. They allow a config file in the root of the CLASSPATH to configure how much gets logged. Things can be logged to the console or to a file depending on the config

Related

Field Type of entity-query not working, correctly retrieves list of content-items but incorrectly stores them as 'Empty Slot"

I have an Authors App which has x amount of authors. I have another app and have configured an Field Input-Type entity-query in it which pulls from the Authors App. It does this correctly and I can select multiple authors. However upon save, when I go to retrieve a content item which should contain the selected authors, I am given "empty slot" for the place of each author
Real entity fields are Entity relations, and they enforce validity. So they only work with entities in the same app, as that's kind of a sealed scope. This is important that Apps can ensure export/import and still work for all standard use cases.
To reference entities of another app you must use strings instead. This can be done using the string-query field which has the same functionality.
The only downside is that your code will need to then look up the entity in the other app using the id or guid (whichever you store) in Razor.

Spring Data MongoDB - model classes without annotations

This question is related to Spring Data MongoDB model classes without annotations.
I have a situation where I need to store my domain classes either in RDBMS store or NoSQL store. Say for example my domain classes are User, Feature, PaymentRequest, Order, OrderLine, OrderHeader etc.
I cannot use any annotation on my domain classes for various reasons.
Application team will specify in which persistent store they like to store. They might configure to store it in MongoDB or in MySQL or in Oracle etc.
My requirement is when I am storing in MongoDB say using spring-data-mongodb I want to leverage the DBRefs for associated objects in my domain object.
How can I achieve with spring-data-mongodb without using annotations in my model classes.
class Role
{
String id;
String roleName;
}
class User {
String id;
String firstName;
String lastName;
List<Role> userRoles;
}
When I save User object I want to ensure that in MongoDB Role objects are stored as DBRefs instead of actual Role object graph.
My question is ─ without using annotations in my User and Role classes ─ how can I achieve this?
I searched the user's forums and could not find a way. That's why I'm posting my question here.
Thanks,
Kishore Veleti A.V.K.
Not sure if you ever figured this out, but you can use AspectJ to create an ITD (inter-type declaration) to weave in the annotations into the class without having to actually modify the original code.
For example, to turn your userRoles into a DBRef, you just need this aspect:
import org.springframework.data.mongodb.core.mapping.DBRef;
privileged aspect User_Mongo {
declare #field: * User.userRoles : #DBRef;
}
This simply adds the #DBRef annotation to any fields within User named userRoles. You can look at the AspectJ documentation for more information on field patterns and ITDs.

Google app engine and JPA

I am try to persist an instance (entity) that contains a predefined instances(entities), with JPA and GAE, the relation is oneToOne, as the following:
#Entity class Address{ ... #OneToOne(cascade = CascadeType.ALL)private City city;}
#Entity class City{...}
I created city instance(entity) and persist it, works good, when trying to create Address instance that contains the created city instance(since from UI, it selected from dropdown box), I got the following exception:
javax.persistence.PersistenceException: Detected attempt to establish Address(no-id-yet) as the parent of City(20) but the entity identified by City(20) has already been persisted without a parent. A parent cannot be established or changed once an object has been persisted.
Is there any annotation(s) should be used in order to make this happen?
Thanks in advance
The problem is how DataStore stores keys. Your type of relation is Parent/Child, so for City you will have Adress as a Parent. This mean that you will have composite key with parent as an Address. Your City was already persists so you will not be able to change key (keys can not be changes dynamically after creation. They are immutable).
I do not think that OneToOne reference is suitable for you. Why do you need a separate object? If you really need it - do not try to keep reference integrity. It is very expensive in NoSQL and could cause a lot of problems.

How to delete a column (attribute) from a GAE datastore?

I have a persistent class stored in a GAE datastore. I have removed one of the attributes from the class. The new records in this table show a value <none> for the removed attribute. But is there a way I can completely drop this column off the table?
Thanks.
Added the following 'migration' code according to moraes' suggestion, but it isn't achieving the desired result:
PersistenceManager pm = PMF.get().getPersistenceManager();
try {
Query q = pm.newQuery(UserLogin.class);
Collection<UserLogin> list = (Collection<UserLogin>) q.execute();
Iterator<UserLogin> iter = list.iterator();
while (iter.hasNext()) {
UserLogin obj = (UserLogin) iter.next();
obj.setLoginDate(obj.getLoginDate());
}
pm.makePersistentAll(list);
} finally {
pm.close();
}
I found the answer to this problem in this Article:
http://code.google.com/appengine/articles/update_schema.html
"Removing Deleted Properties from the Datastore
If you remove a property from your model, you will find that existing entities still have the property. It will still be shown in the admin console and will still be present in the datastore. To really clean out the old data, you need to cycle through your entities and remove the data from each one.
Make sure you have removed the properties from the model definition.
If your model class inherits from db.Model, temporarily switch it to inherit from db.Expando. (db.Model instances can't be modified dynamically, which is what we need to do in the next step.)
Cycle through existing entities (like described above). For each entity, use delattr to delete the obsolete property and then save the entity.
If your model originally inherited from db.Model, don't forget to change it back after updating all the data."
And here is an example with code:
http://sandrylogan.wordpress.com/2010/12/08/delattr/
If you are using ndb (and you probably should), you can easily delete properties by deleting them from entity._properties:
for entity in MyModel.query():
if 'old_property' in entity._values:
del entity._properties['old_property']
del entity._values['old_property']
entity.put()
Or you could make it faster by using an asynchronous query map:
#ndb.tasklet
def cleanup(entity):
if 'old_property' in entity._values:
del entity._properties['old_property']
del entity._values['old_property']
yield entity.put_async()
MyModel.query().map(cleanup)
There is no concept of "table" in datastore. Each entity can have arbitrary properties that don't follow a common schema. The only "schema" is in your model code, and existing records don't change automatically when you change your models.
So, to delete the property from existing records, you need to iterate over all records and re-save them without the property.
The datastore viewer gets its list of columns from the datastore stats, which are updated on a regular basis. If you've removed that column from every entity that had it, wait a day or two and the datastore viewer will stop showing it.

Silverlight RIA: Server-side extension properties on model are not ignored by RIA

In my SilverLight app I have a simple entity-model containing one table: [Memo].
The memo table definition/class layout:
pseudo-code-mode
Partial Class Memo
ID [int autonumbering]
Memo [string]
UserID [int]
End Class
For my client I need to see a normal name, and not a [UserID] number in the UI
so we need to translate that number in field/property [UserID] to a readable
[UserName].
to accomplish that we'll extend the [Memo] Class SERVER-SIDE with this:
pseudo-code-mode
Partial Class Memo
UserName [string]
End Class
So now we have one complete class containing both the UserID and the UserName (Very usefull for like when you use binding to a datagrid)
At the CLIENT-SIDE we have a cached list of users, so at the CLIENT-SIDE we'll fill the UserName property after the EntitySet has been uploaded to the client. This is where my problem occurs: After setting the property, the Entity object is tracked as being changed by the DomainService engine (DomainContext.HasChanges = true).
So when loading a datagrid with 100 records, all records are tagged changed because of setting the UserName property in the client, and after editing 1 record, all 100 records are posted back to the server as being 'changed' instead of just 1 record.
Since this property is an extension property and I do not want to track changes for the UserName, I thought: Lets add the [Ignore] attribute, but no dice. The DomainService keeps tracking the UserName changes. I also tried the [IgnoreDataMember] attribute, no Dice. The [Exclude] attribute does not work, since then it's no longer projected to the client-side.
So I need to be able to reset the DomainService's object tracking state after loading and extending the data from database. Another solution is to extend the data at the server-side, but this is not an option for now.
If your new property is only required client-side, then add your Partial class extension to the client side. Not to the server side.
We often add new helper properties (like Fullname, which returns LastName+FirstName) to our Client-side RIA services project.

Resources