-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 posts ] 
Author Message
 Post subject: Using example queries on Polymorphic objects
PostPosted: Tue Dec 07, 2004 4:23 pm 
Newbie

Joined: Thu Dec 02, 2004 3:51 pm
Posts: 8
Hibernate version:
2.1.7c

I have to classes, A and B that both implement interface C. What I am trying to do is query for any instances of A or B that match a criteria.

If I use the criteria object and create my expression like so

Code:
Criteria criteria = session.createCriteria(C.class);
criteria.add(Expression.eq("lastName", lastNameParam);
List results = criteria.list();


Everything works fine and I get back a list that contains both A and B objects.
The problem is that I have multiple search fields to work with. In this situation they have a form they can fill out with search criteria (Last Name, First Name, Address, City, etc....) The more they populate, the more restrictive the search gets. Becuase the fields the populate is going to change so much from user to user, I wanted to use the "Example" object to do my queries becuase it gives me a clean way to implement this.

With the example object my code becomes.

Code:
Criteria criteria = session.createCriteria(C.class);
Example example = Example.create(exampleObject);
criteria.add(example);
List results = criteria.list();


When I try to run this I get the following error

Code:
net.sf.hibernate.PropertyAccessException: exception getting property value with CGLIB (set hibernate.cglib.use_reflection_optimizer=false for more info) getter of tapestry.demo.domain.A.?


Now the specific class that shows the error changes depending on which concrete implementation is passed to the example object. In the situation above "exampleObject" is of type B. If "exampleObject" was of type A, the class B would throw the error.

Looking through the stack trace it seems to be caused by a ClassCastException getting thrown beneath the hood.

Is there anyway to make this type of Example query work with a polymorphic mapping? Or am I stuck going back to the
Code:
criteria.add(Expression.eq("lastName", lastNameParam);

way of doing things?

I am really trying to avoid the if/else tree that this way requires. (I have to if/else for each paramter of the example object to see if it's null or not and then add it to the criteria as needed).

Any help would be appreciated.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Dec 08, 2004 2:49 am 
Beginner
Beginner

Joined: Wed Nov 19, 2003 6:46 pm
Posts: 41
Location: Auckland, New Zealand
Not sure what the cause of the exception is, but I would think that the Criteria API is a good way of doing things.

You needn't resort to a complex if/else tree of code - surely you could put the paramters in a Map and then iterate through the keys and add Expression objects to the Criteria in a loop? Would be quite elegant, I think...

Either that or perhaps use reflection to find the non-null fields on your example object. But then, I'm a little confused if you have an interface, but you're providing an example object of one of the classes that implement that interface.

HTH

Craig


Top
 Profile  
 
 Post subject:
PostPosted: Wed Dec 08, 2004 1:35 pm 
Newbie

Joined: Thu Dec 02, 2004 3:51 pm
Posts: 8
I have a interface, but becuase I can't instantiate a copy of the interfact (by definition) and I have to provide a actual object to the Example API. The only way to do that was to actually instantiate a copy of one of the implementors of the interface.

I could do a Map and interate through it, but at some point I still have to evaluate each property they can search on to see if it is populated or it is null. That's what the if/else tree would be doing. So using the Map just moves where the if/else takes place.

I will look into using the reflection to do it.

But there is still something odd about this. I have told it to query on the interface, so why would it try to cast the class as anything. The only way I can imagine it throughing a ClassCast is if it was trying to cast A as B. But why would it try to do that? Could this be a bug in the way the Example object works?

Also, when I get the results back (even from the Criteria API which I used to test) they are not sorted according to the criteria provided. If I sort by lastName, and get both A and B types object back, what happens is I get objects of Type A sorted by lastName, and then B type objects sorted by lastName, but not intermixed.

This prevents me from using the criteria.maxResultsSize() attribute, becuase if I need the first 100 results, I don't know that's what I got becuase the sorting is more of a grouping. (Probably needs to be in a new thread)


Top
 Profile  
 
 Post subject:
PostPosted: Wed Dec 08, 2004 3:08 pm 
Beginner
Beginner

Joined: Wed Nov 19, 2003 6:46 pm
Posts: 41
Location: Auckland, New Zealand
I understand your point about the interface, and certainly there is a problem with it throwing an exception.

However, to explore the idea of a map a little further, no if/else is required. Simply do something like this:

Code:
Criteria criteria = session.createCriteria(C.class);
for (Iterator iter = map.keySet().iterator(); iter.hasNext();)
{
    String key = (String) iter.next();
    criteria.add(Expression.eq(key, map.get(key)));
}

return c.list();



HTH

Craig


Top
 Profile  
 
 Post subject: Map of criteria
PostPosted: Wed Dec 08, 2004 3:13 pm 
Newbie

Joined: Thu Dec 02, 2004 3:51 pm
Posts: 8
Yes, I absolutely could do something like that.

But the problem is that when I get the submitted values out of the local properties (using Tapestry as a front end in this) I still have to do the if/else tree for null values. Becuase what I don't want to do is put null values into the map becuase then they end up as null criteria in the query.

That's why the example object was so nice becuase it supported using multiple different fields for each query based on which ones were populated, and it automatically assumes that null properties should be ignored. So now, I just populate each field in the object, using StringUtils.trimToNull() along they way, and I don't have to for which fields have been populated at any point in the cycle.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.