Re: How to pass dynamic attribute values to QueryCustomizer Implementations
Saw your original message and am thinking about this one. Any chance you can post specifics? Does value need to change while running, or is it just dependent upon something at load time? -Brian On Fri, 2003-12-19 at 10:09, Guido Beutler wrote: Hello, This is a repost with a better subject, hoping to get a hint. I build a custom QueryCustomizer implementation to restrict the retrieved values of a collection to a known primary key. I saw that I could add attributes at the deployment descriptor but the value of the primary key changes dynamically during my application. My sample: public Query customizeQuery(Object anObject, PersistenceBroker aBroker, CollectionDescriptor aCod, QueryByCriteria aQuery) { aQuery.getCriteria().addEqualTo(field,value); return aQuery; } The value should change dynamically. Is there really no way to pass additional dynamic arguments to the implementation? IA Simple workaround is to use System properties but of course this just a hack for a test case. It's not thread save, it's slow etc. I found no way to find out where the current query came from to build sonething like a callback. Extending the Query implementation by a user object would be a solution buit this modification shouldn't be done without consulting the OJB crew. Implementing a user object might be difficult because the querry which is passed to the QueryCustomizer is generated by OJB and is not directly coming from my code. So a modified Query would mean that the user object must be passed around by OJB Broker. I still think that I miss something. best regards, Guido - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: How to pass dynamic attribute values to QueryCustomizer Implementations
Hello, I'm a bit restricted in posting original code but I'll do my best :-) Ok. Brian McCallister wrote: Saw your original message and am thinking about this one. Any chance you can post specifics? Does value need to change while running, or is it just dependent upon something at load time? at runtime and that is the main problem. During load time I could solve by using the attributes at the repository. I have two classes A and B and A has a 1:n relationshop to B. class-descriptor class=A table=A field-descriptor id=1 name=a_key column=a_key jdbc-type=INTEGER / collection-descriptor name=b_col element-class-ref=B auto-retrieve=true auto-update=false auto-delete=false proxy=false refresh=false inverse-foreignkey field-id-ref=2/ query-customizer class=QueryCustomizerFilterImpl attribute attribute-name=attr1 attribute-value=value1 / /query-customizer /collection-descriptor /class-descriptor class-descriptor class=B table=B field-descriptor id=1 name=b_key column=b_key jdbc-type=INTEGER primarykey=true autoincrement=false / field-descriptor id=2 name=a_key column=a_key jdbc-type=INTEGER primarykey=true autoincrement=false / /class-descriptor Criteria crit = new Criteria(); crit.addEqualTo(key, value1); Criteria crit2 = new Criteria(); crit2.addEqualTo(b_col.b_key, pk_value_of_B); Criteria crit3 = new Criteria(); crit3.addAndCriteria(crit); crit3.addAndCriteria(crit2); Query q = QueryFactory.newQuery(A.class, crit3); Collection results = broker.getCollectionByQuery(q); I would like to get a collection a.b_col which contains only the elements of B which has the primary key pk_value_of_B not ALL values. The query from above gives the correct instance of A but the collection is filled with all existing b which are very much. So I build a QueryCustomizer where I can add the missing select criteria to the query which was build from OJB to load ALL b. public Query customizeQuery(Object anObject, PersistenceBroker aBroker, CollectionDescriptor aCod, QueryByCriteria aQuery) { aQuery.getCriteria().addEqualTo(b_key,pk_value_of_B); return aQuery; } My problem is how to get the pk_value_of_B to the QueryCustomizer instance. The QueryCustomizer instance is constructed by OJB so the default constructor is called, no way to pass a argument with my pk value. After that OJB calls the customizeQuery method and again it looks like there is no way to get my key in there. Hope this is more readable and a bit more detailed. best regards, Guido -Brian On Fri, 2003-12-19 at 10:09, Guido Beutler wrote: Hello, This is a repost with a better subject, hoping to get a hint. I build a custom QueryCustomizer implementation to restrict the retrieved values of a collection to a known primary key. I saw that I could add attributes at the deployment descriptor but the value of the primary key changes dynamically during my application. My sample: public Query customizeQuery(Object anObject, PersistenceBroker aBroker, CollectionDescriptor aCod, QueryByCriteria aQuery) { aQuery.getCriteria().addEqualTo(field,value); return aQuery; } The value should change dynamically. Is there really no way to pass additional dynamic arguments to the implementation? IA Simple workaround is to use System properties but of course this just a hack for a test case. It's not thread save, it's slow etc. I found no way to find out where the current query came from to build sonething like a callback. Extending the Query implementation by a user object would be a solution buit this modification shouldn't be done without consulting the OJB crew. Implementing a user object might be difficult because the querry which is passed to the QueryCustomizer is generated by OJB and is not directly coming from my code. So a modified Query would mean that the user object must be passed around by OJB Broker. I still think that I miss something. best regards, Guido - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
RE: How to pass dynamic attribute values to QueryCustomizer Implementations
It's entirely possible to do this, but in general I think it's a bad design *to* do it. Collection descriptors are used to model relationships, not arbitrary dynamic queries. The role of query customizers is to allow you to statically refine the relationship to make it more specific than just foreign-key/primary-key. What you're attempting to do is to abuse the mechanism to make it a dynamic query mechanism which isn't the intention. As a result I think you'll find a lot of subtle problems pop up if you go down this route, the first being caching (e.g. what happens when the parent item you're retrieving is answered from the cache and already has a collection that was customized dynamically from the last time it was used). What I really think you want to do here is expose you're dynamic queries off of accessors you write yourself rather than trying to wedge them into collection descriptors. Something like: class-descriptor class=Foo table=Foo field-descriptor id=1 name=fooKey column=foo_key jdbc-type=INTEGER / /class-descriptor class-descriptor class=Bar table=Bar field-descriptor id=1 name=barKey column=bar_key jdbc-type=INTEGER primarykey=true autoincrement=false / field-descriptor id=2 name=fooKey column=foo_key jdbc-type=INTEGER primarykey=true autoincrement=false / /class-descriptor public class A { private Integer fooKey; public Collection getBarsByKey(int barKey) { Criteria crit = new Criteria(); crit.addEqualTo(fooKey, fooKey); crit.addEqualTo(barKey, barKey); Query q = QueryFactory.newQuery(Bar.class, crit); Collection results = broker.getCollectionByQuery(q); } } As an added bonus you don't have to play any tricks to get your dynamic information down to a query customizer, the dynamic information simply comes in as attributes on the method invocation. If you insist on doing it the other way, the traditional way to pass arguments past an interface that doesn't support it is to use ThreadLocal but I really think you would be better served by reconsidering your design. -Original Message- From: Guido Beutler [mailto:[EMAIL PROTECTED] Sent: Friday, December 19, 2003 10:01 AM To: OJB Users List Subject: Re: How to pass dynamic attribute values to QueryCustomizer Implementations Hello, I'm a bit restricted in posting original code but I'll do my best :-) Ok. Brian McCallister wrote: Saw your original message and am thinking about this one. Any chance you can post specifics? Does value need to change while running, or is it just dependent upon something at load time? at runtime and that is the main problem. During load time I could solve by using the attributes at the repository. I have two classes A and B and A has a 1:n relationshop to B. class-descriptor class=A table=A field-descriptor id=1 name=a_key column=a_key jdbc-type=INTEGER / collection-descriptor name=b_col element-class-ref=B auto-retrieve=true auto-update=false auto-delete=false proxy=false refresh=false inverse-foreignkey field-id-ref=2/ query-customizer class=QueryCustomizerFilterImpl attribute attribute-name=attr1 attribute-value=value1 / /query-customizer /collection-descriptor /class-descriptor class-descriptor class=B table=B field-descriptor id=1 name=b_key column=b_key jdbc-type=INTEGER primarykey=true autoincrement=false / field-descriptor id=2 name=a_key column=a_key jdbc-type=INTEGER primarykey=true autoincrement=false / /class-descriptor Criteria crit = new Criteria(); crit.addEqualTo(key, value1); Criteria crit2 = new Criteria(); crit2.addEqualTo(b_col.b_key, pk_value_of_B); Criteria crit3 = new Criteria(); crit3.addAndCriteria(crit); crit3.addAndCriteria(crit2); Query q = QueryFactory.newQuery(A.class, crit3); Collection results = broker.getCollectionByQuery(q); I would like to get a collection a.b_col which contains only the elements of B which has the primary key pk_value_of_B not ALL values. The query from above gives the correct instance of A but the collection is filled with all existing b which are very much. So I build a QueryCustomizer where I can add the missing select criteria to the query which was build from OJB to load ALL b. public Query customizeQuery(Object anObject, PersistenceBroker aBroker, CollectionDescriptor aCod, QueryByCriteria aQuery) { aQuery.getCriteria().addEqualTo(b_key,pk_value_of_B); return aQuery; } My problem is how to get the pk_value_of_B to the QueryCustomizer instance. The QueryCustomizer instance is constructed by OJB so the default constructor is called, no way to pass a argument with my pk value. After
Re: How to pass dynamic attribute values to QueryCustomizer Implementations
I completely agree with it being bad design. However, I am using OJB in struts applications. Lets take the example i gave before. The struts action would simply load a collection of managers from OJB, and put them into the request scope. The action would forward to a JSP. The JSP would itterate through the Managers, and the Employees within them, and print them to the screen. This is done using Tag libraries. If the Managers datd only has Employees that match the (dynamicly generated) query specifications, all the JSP has to do is itterate through the data. If the Managers data has Employees that dont match the query specifications, then the query has to be handled at the JSP level, which definitely is bad design! Also this creates a problem that web designers can cope with taglibs, but cannot cope with writing scriptlets. One solution is to create pageview that mimic data objects (and can even reuse the same beans) but are copies of the contents. Thus you copy the managers details into a pageview object, and copy only the employees you want into the pageview manager objects. However this means more code. Another downside of this solution is the performace loss of materialising lots of objects that are unwanted. Would the following query (slightly changed from your query) have any implications on caching, etc? Would the cache not realise that criteria have been used? Criteria crit = new Criteria(); crit.addEqualTo(fooKey, fooKey); crit.addEqualTo(bar.barKey, barKey); Query q = QueryFactory.newQuery(Foo.class, crit); Collection results = broker.getCollectionByQuery(q); Daniel. - Original Message - From: Lance Eason [EMAIL PROTECTED] To: OJB Users List [EMAIL PROTECTED] Sent: Friday, December 19, 2003 4:49 PM Subject: RE: How to pass dynamic attribute values to QueryCustomizer Implementations It's entirely possible to do this, but in general I think it's a bad design *to* do it. Collection descriptors are used to model relationships, not arbitrary dynamic queries. The role of query customizers is to allow you to statically refine the relationship to make it more specific than just foreign-key/primary-key. What you're attempting to do is to abuse the mechanism to make it a dynamic query mechanism which isn't the intention. As a result I think you'll find a lot of subtle problems pop up if you go down this route, the first being caching (e.g. what happens when the parent item you're retrieving is answered from the cache and already has a collection that was customized dynamically from the last time it was used). What I really think you want to do here is expose you're dynamic queries off of accessors you write yourself rather than trying to wedge them into collection descriptors. Something like: class-descriptor class=Foo table=Foo field-descriptor id=1 name=fooKey column=foo_key jdbc-type=INTEGER / /class-descriptor class-descriptor class=Bar table=Bar field-descriptor id=1 name=barKey column=bar_key jdbc-type=INTEGER primarykey=true autoincrement=false / field-descriptor id=2 name=fooKey column=foo_key jdbc-type=INTEGER primarykey=true autoincrement=false / /class-descriptor public class A { private Integer fooKey; public Collection getBarsByKey(int barKey) { Criteria crit = new Criteria(); crit.addEqualTo(fooKey, fooKey); crit.addEqualTo(barKey, barKey); Query q = QueryFactory.newQuery(Bar.class, crit); Collection results = broker.getCollectionByQuery(q); } } As an added bonus you don't have to play any tricks to get your dynamic information down to a query customizer, the dynamic information simply comes in as attributes on the method invocation. - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: How to pass dynamic attribute values to QueryCustomizer Implementations
Hi, Lance Eason wrote: It's entirely possible to do this, but in general I think it's a bad design *to* do it. I never said that it is the best way to do it. :-) Collection descriptors are used to model relationships, not arbitrary dynamic queries. The role of query customizers is to allow you to statically refine the relationship to make it more specific than just foreign-key/primary-key. What you're attempting to do is to abuse the mechanism to make it a dynamic query mechanism which isn't the intention. As a result I think you'll find a lot of subtle problems pop up if you go down this route, the first being caching (e.g. what happens when the parent item you're retrieving is answered from the cache and already has a collection that was customized dynamically from the last time it was used). What I really think you want to do here is expose you're dynamic queries off of accessors you write yourself rather than trying to wedge them into collection descriptors. Something like: class-descriptor class=Foo table=Foo field-descriptor id=1 name=fooKey column=foo_key jdbc-type=INTEGER / /class-descriptor class-descriptor class=Bar table=Bar field-descriptor id=1 name=barKey column=bar_key jdbc-type=INTEGER primarykey=true autoincrement=false / field-descriptor id=2 name=fooKey column=foo_key jdbc-type=INTEGER primarykey=true autoincrement=false / /class-descriptor public class A { private Integer fooKey; public Collection getBarsByKey(int barKey) { Criteria crit = new Criteria(); crit.addEqualTo(fooKey, fooKey); crit.addEqualTo(barKey, barKey); Query q = QueryFactory.newQuery(Bar.class, crit); Collection results = broker.getCollectionByQuery(q); } } As an added bonus you don't have to play any tricks to get your dynamic information down to a query customizer, the dynamic information simply comes in as attributes on the method invocation. If you insist on doing it the other way, the traditional way to pass arguments past an interface that doesn't support it is to use ThreadLocal but I really think you would be better served by reconsidering your design. You're right, that your solution would work. The other point of view ist that you have to write aditional code, the getBarsByKey method. Of course this is more flexible than using a fixed class. Maybe dependent of the application which way is the better one. I'll check what your solution would mean for my application. Thanks, it's really another point of view. best regards, Guido - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: How to pass dynamic attribute values to QueryCustomizer Implementations
I think you are right. I think there are two ways of looking at this. 1. From an OO programing point of view, OJB could be seen solely as a persistance mechanism for objects. Queries should be used for realising a collection of objects or a single object. The single object (or each of the collection of objects) should be complete trees (ie they should come back from OJB as they went in). 2. From a Modeling point of view, OJB could be seen not only as a tool for storing objects in a persistant manner, but also as a tool for working with those objects. One of the fundamental methods for working with data is projection: specifying a tree to match, and finding matching occurances of that tree. This operation of projection is provided by SQL, but not in the same manner, as all matching subtrees are returned (ie Managers are repeated on each row of the results for their employees). OJB put's it back together. The kind of projection we are debating is provided with Conceptual Graphs (peirce logic), and it works well. However wether it should be applied to OJB depends on which view you take (1 and 2 above). Well, that's my thoughts! Feel free to disregard or discuss as you so feel inclined! Daniel. - Original Message - From: Guido Beutler [EMAIL PROTECTED] Exactly and this is one reason why delegating the work to OJB for queries. This * must* not be bad design at all. It depends on the application I think. Another point is that I have a aditional hand written subselect which must be maintained and I can not see this problem by looking at the deployment descriptor. By using a queryCustomizer you can see at the descriptor that there is a dependency and where to make modifications if neccessary. best regards, Guido - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]