commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From David Graham <grahamdavid1...@yahoo.com>
Subject Re: [DbUtils] ListHandler
Date Sun, 30 May 2004 18:37:15 GMT

--- Mikhail Krivoshein <info@mikkri.com> wrote:
> Hello David,
> 
> --- Mikhail Krivoshein <mikhail@mikkri.com> wrote:
>  > I'm wondering why DbUtils has no simple way to combine
>  > ResultSetHandlers.
>  > In my code it is very common when I need to provide two methods: one
>  > retrieves List of items and another retrieve only one item.
>  >
>  > Currently I use three methods in such case:
>  > 1) public Object get(int id) { ... } - retrieves one row and convert
> it
>  > into JavaBean with read method.
>  > 2) public List list() { ... } - retrieves many rows and convert them
>  > into List of JavaBeans with read method also.
>  > 3) private Object read(ResultSet rs) { ... } - converts current
>  > ResultSet row data into JavaBean object.
>  >
>  > Now I'm moving to DbUtils library and want to use the same approach.
>  >
>  > I plan:
>  > 1) implement custom ResultSetHandler to translate ResultSet row into
>  > JavaBean.
>  > 2) use ListHandler (sources bolow) to convert ResultSet into List
> with
>  > help from ResultSetHandler from point 1.
> 
> Doesn't BeanListHandler provide this exact behavior?
> 
> David
> 
> Not exactly. BeanListHandler generates List of JavaBeans.
> But I may want to generate List of Strings for example. 

The nightly builds include a ColumnListHandler that will generate a List
of Strings provided the column is a CHAR or VARCHAR.

> Or I may need to
> 
> make some additional processing while
> filling JavaBean with data.

So you would implement a custom ResultSetHandler that loops over the
ResultSet and uses a BeanProcessor (in the nightlies) to generate the
bean, then customize the bean as needed.

> 
> Just simple example of code that I need to have:
> ========================
>     /**
>      * Method retrieves keywords as comma separated string.
>      *
>      * @param serviceId service id
>      * @return keywords as comma separated string.
>      * @throws SQLException error occurs
>      */
>     private static String getKeywords(int serviceId) throws SQLException
> {
>         QueryRunner runner = new 
> QueryRunner(DbConnectionManager.getDataSource());
>         List keywords =
>             (List) runner.query(
>                 "SELECT keyword FROM keyword WHERE service_id = ?",
>                 new Integer(serviceId),
>                 new ListHandler(new ScalarHandler()));
>         return StringUtils.combineString(keywords);
>     }
> ========================
> With ScalarHandler applied to individual rows and ListHandler used to 
> combine them into List code became
> very straighforward.

The implementation of ScalarHandler.handle() is trivial.  It would be
easier to just call ResultSet.getObject() yourself from a custom
ResultSetHandler.

> 
> And I see performance problem with BasicRowProcessor because it just 
> forwards calls to BeanProcessor that
> definetely has performance problems because of heavy reflection use and 
> absance of any metadata caching.
> Assume I need to generate 5 item list about 30 times per minute (caching
> 
> can't be applied).
> With BeanProcessor I need to study metadata of the table 30 times!
> I prefer to avoid this cost and write JavaBean <-> DB table mapping code
> 
> by hands.

The only place BeanProcessor uses ResultSetMetaData is in the
mapColumnsToProperties() method.  That method is protected so that you can
override it and provide caching.  

Also note that Java's Introspector caches all Class meta data so
introspection only occurs the first time you create an object of a
particular bean class.

>  From my point of view clearest way is to implement one custom 
> ResultSetHandler for each JavaBean.
> And if I combine this custom ResultSetHandler with discussed ListHandler
> 
> I will reuse List generation/result set iteration
> code for all my handlers.

I think what you're asking for is a ResultSetHandler you can subclass that
does this:

handle(ResultSet rs) {
    while(rs.next()) {
        handleRow(rs);
    }
}

where you would override handleRow() to do your processing.  This was
considered for inclusion but it's so trivial that you could write this
base class in about 5 minutes.  Maybe we should include it though.

David

> 
> I see another solution - implement one RowProcessor for each JavaBean. 
> But I dislike this solution and it looks less clear
> than one with custom ResultSetHandlers. Also I guess it is not way how 
> DbUtils is designed to be used.
> 
> I appreciate your help with this topic.
> 
> Best regards,
> Mikhail Krivoshein



	
		
__________________________________
Do you Yahoo!?
Friends.  Fun.  Try the all-new Yahoo! Messenger.
http://messenger.yahoo.com/ 

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


Mime
View raw message