When I use criteria queries, the result contains array list of lazy initialized objects. that is, the list has values with handler org.codehaus.groovy.grails.orm.hibernate.proxy.GroovyAwareJavassistLazyInitializer.
This prevent me from doing any array operation (minus, remove etc) in it. When I use, GORM methods, I get array list of actual object types. How can I get the actual objects in criteria query?
The code is listed below.
availableTypes = Type.withCriteria() {
'in'("roleFrom", from)
'in'("roleTo", to)
}
availableTypes (an array list) has one value , but not actual object but value with a handler of GroovyAwareJavassistLazyInitializer
availableTypes (an array list) has values with type Type
availableTypes = Type.findByRoleFrom(from)
---------- Update ----------
I did further troubleshooting, and this is what I found. Probably the above description might be misleading, but I kept it in case it helps.
When using findAllBy for the first time, I get proxy objects rather than the actual instance. Then, I invoke the method through an ajax call, the actual instance is loaded (anything to do with cache loading??). When I refresh the page, it again loads the proxy
def typeFrom = Type.findAllByParty(partyFrom)
there is another use of findAllBy in the same method, which always returns actual instances.
def relFrom = Relation.findAllByParty(partyFrom)
When compared the two classes, the attribute 'party' of class Roles is part of a 1-m relation. like
class Role {
RoleType roleType
LocalDate validFrom
LocalDate validTo
static belongsTo = [party : Party ]
...
}
I know if I do statement like Party.findAll(), the role instances would be proxy till they access. But, when using gorm directly on the class (Role), why I am getting the proxy objects ???
thanks for the help.
thanks.
Turns out are a couple of possible solutions which I came across but didn't try, such as
Overloading the equals method so that the proxy and the domain
object use a primary key instead of the hashCode for equality
Using a join query so that you get actual instances back and not proxies
GrailsHibernateUtil.unwrapProxy(o)
HibernateProxyHelper.getClassWithoutInitializingProxy(object)
One solution that worked for me was to specify lazy loading to be false in the domain object mapping.
History of this problem seems to be discussed here: GRAILS-4614
See also: eager load
Related
I'm trying to specify a subset of data to be returned from a database query by Web API 2.
In particular, for this query, I first turn lazy loading on:
db.Configuration.LazyLoadingEnabled = true;
This is because there are potentially infinite levels of children. For example:
Parent: {"name":"Jon","children":[{"name":"Dave","children":["name":"Ed"...
Each person in the above sequence can also have a biography. In the database, the books also have related tables for, let's say, authors, reviewers etc.
As far as I know I can add data annotations to the model to specify which fields to return:
[Key]
= specifies the key which will be returned
[DataMember]
= specifies a property which will be returned
[JsonIgnore]
[IgnoreDataMember]
= specifies a property which will not be returned
[JsonObject(IsReference = true)]
= specifies that the object is being references from another object and therefore related objects should not be loaded
I'm struggling to load the related biographies. The id for the biography is returning, but the biography objects are null. From the parent object, I have annotated both the nullable int and the virtual object references to biography with [DataMember]. In the biography object, I have then specified the id with [Key] and the name with [DataMember] and all other properties with [JsonIgnore]
[IgnoreDataMember]. However the biographies are not being loaded. The db query is returning the items loaded, but they are then being nulled by web api, I assume because of some circular reference in the chain somewhere.
There are about 50 tables linked in some way, do I need to go through them all and add data annotations to everyone - even if I have used an ignore annotation to break the chain? Hoping for a simple solution, but any solution appreciated!
It seems to be working fine that [DataMember] will load a HashSet of related data, which gets instantiated in the constructor, but related databases objects (which are not instantiated in the constructor) do not get loaded.
It seems that the update statement doesn't turn lazy loading on:
db.Configuration.LazyLoadingEnabled = true;
The related items would only be returned if I went into debug mode and loaded the related data when hovering over the object (seems strange), but basically it was staying in lazy loading = false mode.
My solution has been to turn lazy loading on globally and to use data annotations as described above to avoid circular references.
Constantly faced with a problem when I need to compare and manipulate objects that reference other objects. For example:
Class Student {
...
String Name
Integer Age
...
}
Class Stuff {
...
Student student
...
}
When I invoke an instance of Stuff (Stuff.get (id)/load(id)) and will access the Name, Age and other attribute I see in debug mode (stuff .name = null, they're like 'null' although they are not null. It
command when analyzing values of these attributes (stuff
.name == "pen") error occurs.
I need to invoke the instances and compare their values to execute business rules, but do not know how to resolve this issue.
I read something about the inclusion in the configuration Stuff Mapping 'student lazy: false' for all the time you need to load the instance ofstuff , also charge the Student, but that in addition to overload the memory (since stuff is a Domain Great) would solve this case being the only solution to put all references as 'lazy: false' which would slow the application just to make a simple comparison.
Does anyone know how to invoke instances (Stuff), automatically invoking the attribute to be working (student) just to make the comparison of data, without using the 'student lazy: false' that invokes the data at all times?...
Using Grails 2.2.0 e o Groovy 2
Stuff don't have a property called name so you should get MissingPropertyException calling stuff.name. This has nothing to do with the lazy or eager relationship.
You can check the definition of a lazy relationship in the documentation and also the difference between the types of fetch.
To access the name property you need to access the student property before:
Stuff instance = Stuff.get(id)
println instance.student.name //this, if lazy, will trigger a new database query.
If you know that your code will access the Student instance by the relation with Stuff you could fetch both in one database access (eager and not lazy):
Stuff instance = Stuff.withCriteria {
eq('id', id)
fetchMode("student", FetchMode.JOIN)
}
I have 3 domains: A, B, C.
A and C have many-to-many relationship through B.
A and C are searchable.
When I search and get list of A domain all the fields in A are accessible, however relation field is always 'null'. Why I can't access relational field? Why do I get 'null'? If I access object directly, I see a relation, but when searchable returns A domain, I get 'null' on a relation field.
P.S: I tried to make B searchable but it looks like searchable having issue with indexing it on top of that I don't see any point in indexing B since it exists for the sake of many-to-many relationship only.
Please I need help with it. I need to be able to get to C via A on a searchable return.
Thank you.
[Update]: I made a prototype project today (small DB) and made domain B searchable. Now I can access relational field. However in my real project, I don't want to make B searchable since database is big and indexing takes too long. Is there a way around it?
You can refrash all instance in result list or use reload:true property for seach method
searchableService.search(query,[reload:true])
You can find full list of options: http://grails.org/Searchable+Plugin+-+Methods+-+search
reload - If true, reloads the objects from the database, attaching them to a Hibernate session, otherwise the objects are reconstructed from the index. Default is false
Ok, I believe I solved my issue.
First checkout link to a similar question: Grails searchable plugin -- Please give GalmWing some credit.
My solution is following, I am implementing my own controller and following piece of code implements searchable service call:
if (params.q) {
try{
def searchResults = searchableService.search(params.q, params)
searchResults.results.each {
it.refresh()
}
return [carInstanceList:searchResults.results, carInstanceTotal:searchResults.total]
} catch (SearchEngineQueryParseException ex) {
return [parseException: true]
}
As you can see I have a loop where on each item of domain "A" I do refresh. Now refresh gets real record from DB with all the links. Now I return list into GSP and it extracts all of "C" domains associated with the "A" domain.
Now this way you might get performance penalty, but in my case searchable is actually not able to index "B" domain, it is working for a while and then crashes, so I don't have another choice, at least for now.
For a project I'm currently working on I need to dynamically add properties to a domain class and persist them later in the database. In general, I need a key/value store attached to a "normal" domain class. Sadly I cannot use a NoSQL database (e.g. Redis).
My approach would be to handle the additional properties on a save() by identifying them within afterInsert or afterUpdate and writing them to another table - I would prefer not to use a map property within the domain class but an additional "Field" table (to better support searches).
I tried to add properties using the metaClass approach:
person.metaClass.middlename = "Biterius"
assert person.middlename == "Biterius" // OK
This works and I can identify the additional properties in the afterInsert/afterUpdate methods but it seems that I cannot change the value thereafter - i.e., the following does not work:
person.middlename = "Tiberius"
assert person.middlename == "Tiberius" // FAIL
Then I tried an Expando approach by extending the Person class by the Expando class (directly ("Person extends Expando") and via an abstract intermediate class ("Person extends AbstractPerson" and "AbstractPerson extends Expando")).
def person = new Person()
assert person in Person // OK
assert person in AbstractPerson // OK
assert person in Expando // OK
Both variants did not work - I could assign values to arbitrary "properties" but the values were not stored!
person.mynewproperty = "Tiberius" // no MissingPropertyException is thrown
println person.mynewproperty // returns null
So how can I add properties to a domain class programmatically during runtime, change them and retrieve them during afterInsert or afterUpdate in order to "manually" store them in a "Fields" table?
Or am I doing something completely wrong? Are there other / simpler ways to do this?
What about turning your DB into a "NoSQL" one?
In one of my projects, I just used a String-property to store a map as JSON-Object.
For Groovy it's not a big problem to convert between a map and a JSON-Object. And since you can access a map just like an object with properties, I found this solution very convenient.
Only drawback: you have to plan the size of your String-property in advance...
Update: sorry, just read that you want to support searches...
what about
class Person {
...
static hasMany = [extProperties:KeyValue]
...
def invokeMethod(String name, args) {
if (name.startsWith('get')) {
//an unknown properties's getter is called
}
//add same for setter
}
}
class KeyValue {
String key
String value
}
I guess such a schema would give you all freedom you need. Even without the hasMany, you can make use of invokeMethod to handle your external tables...
The getter and setter can save your values in a transient string propertie (static transients = ['myTransientProperty']). This property should be available in the afterInsert / `afterUpdate´ events.
Why don't you just create a map of strings on the domain object and store your extra data there manually? Unless you're storing complex data you should be able to cast anything you need to/from a string.
Above is a simplified version of our domain model. NotificationOrder has a reference to an instance of a sub class (consider ReferenceNumberBase logically abstract).
Problem:
I want a query to return all NotificationOrders that satisfies XYZ and I want that query to eagerly load all referenced instances of CustomerCase (including all related objects of that graph, except Group forget about that issue for the moment).
I've tried searching for a solution to this, but all I've found are solutions to problems equivalent of querying for CustomerCase as a root object directly.
I'd like something like this:
var query = ObjectContext.CreateObjectSet<NotificationOrder>.Where(e => e.NotificationType == "Foo");
return ((ObjectSet<NotificationOrder>) query).Include("ReferenceNumberBase");
However, that won't load the Vehicle instance of CustomerCase or any of the other related objects. How can I express this so EF understands the eager load I want (I'd very much like to avoid multiple roundtrips / notification order)?
NOTE: Since CustomerCase is a derived type I can't do normal transitive include using something like this:
var query = ObjectContext.CreateObjectSet<NotificationOrder>.Where(e => e.NotificationType == "Foo");
return ((ObjectSet<NotificationOrder>) query).Include("ReferenceNumberBase.Vehicle"); //
since the Vehicle property is a member of the derived CustomerCase type, and not the ReferenceNumberBase type and instead we get errors like:
"The EntityType 'Model.ReferenceNumberBase' does not declare a navigation property with the name 'Vehicle'."
Neither can I use query.OfType<CustomerCase>... since the query type is NotificationOrder, and not ReferenceNumberBase (or can I somehow?).
ps. We are using self tracking POCO entities with EF4 (have not upgraded to 4.1 yet)
EDIT: I've searched some more, and as of about a year ago this looks to have been a limitation of the Include() method (at least at that time). Is this accurate and has this been adressed since then? [sources below]
http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/a30351ab-5024-49a5-9eb4-798043a2b75d
http://data.uservoice.com/forums/72025-ado-net-entity-framework-ef-feature-suggestions/suggestions/1057763-inheritance-eager-loading?ref=title
https://connect.microsoft.com/VisualStudio/feedback/details/594289/in-entity-framework-there-should-be-a-way-to-eager-load-include-navigation-properties-of-a-derived-class