You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by "Philip, Anil - Kansas City, MO" <an...@kcc.usda.gov> on 2009/08/04 22:03:59 UTC

RE: Commons Dbutils: Request feedback for possible patch; handling nested beans.

ok. If anyone runs into the same problem, I have described the fix here: 
http://juwo-works.blogspot.com/2009/07/how-to-handle-nested-beans-using.html
thanks,
Anil Philip

-----Original Message-----
From: Liam Coughlin [mailto:lscoughlin@gmail.com] 
Sent: Thursday, July 23, 2009 4:40 PM
To: Commons Developers List
Subject: Re: Commons Dbutils: Request feedback for possible patch; handling nested beans.

It's not a bug though.

No where in the documentation for your push mower does it say it won't split
logs.

dbutils is not a complete DAO solution, or an ORM tool, it's a framework on
top of which to build custom DAO and ORM solutions.

handling relationships is far and beyond scope.

On Thu, Jul 23, 2009 at 1:06 PM, Philip, Anil - Kansas City, MO <
anil.philip@kcc.usda.gov> wrote:

> I disagree. I see it as an enhancement. This limitation of dbutils is not
> mentioned in the docs and the user stumbles upon it as a bug when he finds
> the member is unfilled.
> However this fix to BeanProcessor only covers bean(s) containing singly
> nested beans. IMHO It would be good if we can figure out how to do bean(s)
> containing singly nested or a list of nested beans; one-many.
> thanks,
> Anil Philip
>
> -----Original Message-----
> From: Dan Fabulich [mailto:dan@fabulich.com]
> Sent: Wednesday, July 22, 2009 7:03 PM
> To: Commons Developers List
> Subject: RE: Commons Dbutils: Request feedback for possible patch; handling
> nested beans.
>
> I share Liam's intuition that I don't think we need this.
>
> Now that you've written this processor for yourself, you can use it; it's
> easy to pass your own BeanProcessor to BasicRowProcessor, and you can
> always hand that BRP to any of our existing ResultSetHandlers.
>
> Trying to provide perfectly general bean-mapping functionality may be
> over-engineering the problem.  The fact that you were able to pull this
> together in just a few lines of code is evidence that it may not be
> necessary to provide it in DBUtils.
>
> -Dan
>
> Philip, Anil - Kansas City, MO wrote:
>
> > My fix was to create a NestedBeanProcessor that inherited from
> BeanProcessor and accepts a mapping in the constructor.
> > However, **in a patch, it would be better to simply modify the toBean()
> in BeanProcessor and add a constructor that accepts a Hashtable**.
> > Current fix:
> > 1) For each nested bean, users will provide a mapping of property to
> nested object reference so that the property can be found. In the above
> example, that would be: "bar"<---> ['activity', Bar.class]
> > 2) A new class, NestedBeanProcessor inherits from the BeanProcessor class
> in Dbutils. It overrides the toBean() method.(Note: for a patch, We would
> add a constructor that accepts a hashtable, and also modify toBean()) When
> this method is called to populate a bean from a result set, it asks the
> superclass to fill in the data. Then it examines each mapping. Using Java
> Reflection, it retrieves the nested reference. If this is null, it creates
> the nested bean. Next, it retrieves the value of the field in the result set
> and calls the setter method on the bean.
> > 3) In the case where Foo contained a list of nested beans:
> > for example
> > ArrayList<Bar> bar;
> > There is no way to specify this one-many relationship in Dbutils for
> automatic filling of bar.activity from the top-level query. We would in this
> case, fill in the fields of Foo and then use this instance to run a second
> query, using the BeanListHandler to fill in the bar list and any nested
> fields of Bar.
> >
> > Hashtable<PropertyDescriptor, String> ht = new
> Hashtable<PropertyDescriptor, String>();
> > PropertyDescriptor prop = new PropertyDescriptor("activity", Bar.class);
> > ht.put(prop, "bar");
> > NestedBeanProcessor nbp = new NestedBeanProcessor(ht);
> > QueryRunner runner = new QueryRunner();
> > BasicRowProcessor burp = new BasicRowProcessor(nbp);
> > BeanHandler bh = new BeanHandler(Foo.class, burp);
> > Foo foo = (Foo) runner.query(connection,      "select face, activity from
> Mood", bh);
> > System.out.println(foo.getFace() + " during this activity: " +
> foo.getBar().getActivity());
> >
> > Result:
> > huffing during this activity: jog
> > ----
> > public class NestedBeanProcessor extends BeanProcessor {
> >
> > ...relevant methods shown...
> >
> > Hashtable<PropertyDescriptor, String> propertyForBeanMember;
> >
> > public NestedBeanProcessor(
> > Hashtable<PropertyDescriptor, String> propertyForBeanMember) {
> >       super();
> >       this.propertyForBeanMember = propertyForBeanMember;
> > }
> > @Override
> > public Object toBean(ResultSet rs, Class type) throws SQLException {
> >       Object bean = super.toBean(rs, type);
> >       Enumeration<PropertyDescriptor> keys =
> propertyForBeanMember.keys();
> >       while (keys.hasMoreElements()) {
> >               PropertyDescriptor property = keys.nextElement();
> >               Class<?> beanClass = bean.getClass();
> >               try {
> >                       String fieldName =
> propertyForBeanMember.get(property);
> >                       String fieldNameCapitalized =
> fieldName.substring(0, 1)
> >                               .toUpperCase()
> >                                               + fieldName.substring(1);
> >                       String fieldGetterName = "get" +
> fieldNameCapitalized;
> >                       String fieldSetterName = "set" +
> fieldNameCapitalized;
> >                       Method fieldGetterMethod = beanClass
> >
> .getDeclaredMethod(fieldGetterName);
> >                       Method fieldSetterMethod = null;
> > // we have to go thru all the methods because
> > // PropertyDescriptor doesn't seem to provide a way to retrieve
> > // the fieldClass
> > // i.e. we would have liked to simply do
> > // fieldSetterMethod = beanClass.getDeclaredMethod(fieldSetterName,
>  Bar.class);
> >                       Method[] allMethods =
> beanClass.getDeclaredMethods();
> >                       for (Method m : allMethods) {
> >                               String mname = m.getName();
> >                               if (mname.equals(fieldSetterName)) {
> >                                       fieldSetterMethod = m;
> >                                       break;
> >                               }
> >                       }
> >                       Field beanField =
> beanClass.getDeclaredField(fieldName);
> >                       Class<?> nestedBeanType = beanField.getType();
> >                       Object nestedBeanValue =
> fieldGetterMethod.invoke(bean);
> >                       // nestedBeanValue is the value in the reference
> >                       if (nestedBeanValue == null) {
> >                               // create
> >                               nestedBeanValue =
> nestedBeanType.newInstance();
> >                               // set value to new instance
> >                               fieldSetterMethod.invoke(bean,
> nestedBeanValue);
> >                       }
> >                       System.out.println(" property :" + property
> >                               + " target nested Bean: " +
> nestedBeanValue);
> >                       Class<?> propType = property.getPropertyType();
> >                       Object targetValue = this.processColumn(rs, rs
> >                               .findColumn(property.getName()), propType);
> >                       if (propType != null && targetValue == null
> >                               && propType.isPrimitive()) {
> >                               targetValue =
> primitiveDefaults.get(propType);
> >                       }
> >                       this.callSetter(nestedBeanValue, property,
> targetValue);
> >               } catch (Exception e) {
> >                       e.printStackTrace();
> >                       throw new SQLException(e.getMessage());
> >               }
> >       }
> >       return bean;
> > }
> >
> >
> > thanks,
> > Anil Philip
> >
> > -----Original Message-----
> > From: Liam Coughlin [mailto:lscoughlin@gmail.com]
> > Sent: Wednesday, July 22, 2009 1:26 PM
> > To: Commons Developers List
> > Subject: Re: Commons Dbutils: Request feedback for possible patch;
> handling nested beans.
> >
> > The default BeanHandler is not a full mapping solution and I'm not sure
> you
> > really want it to be -- that's a case where it might be in your best
> > interest to implement a custom Handler.
> >
> > Cheers
> > -L
> >
> > On Wed, Jul 22, 2009 at 12:59 PM, Philip, Anil - Kansas City, MO <
> > anil.philip@kcc.usda.gov> wrote:
> >
> >>
> >> Here is the example - I had an idea and implemented a possible fix that
> >> works. I would like to know before I submit a patch, whether it really
> is a
> >> solution or if there is a better way. In short, can I get feedback here?
> >> --------
> >> Problem:
> >> Some of our beans contain object references to other beans. Those nested
> >> beans may have properties that are intended to be filled in by one or
> more
> >> fields from a query. However, since it is not on the surface, Dbutils
> cannot
> >> find where the property is and so the nested property remains unfilled.
> >>
> >> Example:
> >> Consider a table Moods to track our demeanor while we engage in an
> >> activity. So it has two columns; face (demeanor) and activity.
> >>
> >> Face            Activity
> >> -----       --------
> >> huffing Jog
> >> smile           Work
> >> engrossed       movie
> >> sad             Cry
> >> distant distracted
> >> bored           waiting
> >>
> >> Bean Foo contains an object reference to an instance - a bean- of class
> >> Bar. Foo contains data field or property 'face', and Bar contains the
> >> property 'activity', that we want to fill from this query:
> >> "select face, activity from Mood"
> >>
> >> public class Foo {
> >>        private String face;
> >>        private Bar bar;
> >>        public String getFace() {return face;}
> >>        public void setFace(String face) {this.face = face;}
> >>        public void setBar(Bar bar) {this.bar = bar;}
> >>        public Bar getBar() {return bar;}
> >> }
> >> public class Bar {
> >>        private String activity;
> >>        public String getActivity() {return activity;}
> >>        public void setActivity(String activity) {this.activity =
> activity;}
> >> }
> >>
> >> Old way:
> >> QueryRunner runner = new QueryRunner();
> >> BeanHandler bh = new BeanHandler(Foo.class);
> >> Foo foo = (Foo) runner.query(connection,
> >>        "select face, activity from Mood", bh);
> >>
> >> Result:
> >> Foo.bar is null and its fields are unpopulated.
> >>
> >> thanks,
> >> Anil Philip
> >>
> >> -----Original Message-----
> >> From: Dan Fabulich [mailto:dan@fabulich.com]
> >> Sent: Tuesday, July 21, 2009 7:13 PM
> >> To: Commons Developers List
> >> Subject: Re: Commons Dbutils: Request feedback for possible patch;
> handling
> >> nested beans.
> >>
> >> Philip, Anil - Kansas City, MO wrote:
> >>
> >>> We use dbutils in my team and found a problem when a bean has nested
> >> object references.
> >>> The properties in the nested bean are obviously not filled in.
> >>
> >> File a bug with an example?  I'm not sure I quite understand your
> >> scenario.
> >>
> >> http://issues.apache.org/jira/browse/DBUTILS
> >> (You need to login to file a bug.)
> >>
> >> -Dan
> >>
> >> ---------------------------------------------------------------------
> >> To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
> >> For additional commands, e-mail: dev-help@commons.apache.org
> >>
> >>
> >> ---------------------------------------------------------------------
> >> To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
> >> For additional commands, e-mail: dev-help@commons.apache.org
> >>
> >>
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
> > For additional commands, e-mail: dev-help@commons.apache.org
> >
> >
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
> For additional commands, e-mail: dev-help@commons.apache.org
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
> For additional commands, e-mail: dev-help@commons.apache.org
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
For additional commands, e-mail: dev-help@commons.apache.org