dhis2-devs team mailing list archive
-
dhis2-devs team
-
Mailing list archive
-
Message #09412
Re: A question on generics
On 8 January 2011 00:05, Bob Jolliffe <bobjolliffe@xxxxxxxxx> wrote:
> Hi all
>
> I have a small problem which I can't seem to get right. I am sure
> Lars, Jo, Saptarshi and all ye java experts will know. Lars I guess
> you are pretty familiar with the amplecode jdbc stuff.
>
> I have an interface and a class for iterating over a result set from a
> query on the aggregatedatavalue table:
>
> the interface:
>
> package org.hisp.dhis.aggregation;
>
> public interface AggregatedDataValueStoreIterator {
>
> // ----------------------------------------------------------------------
> // AggregatedDataValueStoreIterator
> // ----------------------------------------------------------------------
>
> /**
> * Gets the next AggregatedDataValue
> *
> * @return the aggregated value or null.
> */
> AggregatedDataValue next();
>
> /**
> * Close any underlying resources
> *
> */
> void close();
> }
>
> and the class:
>
> public class JdbcAggregatedDataValueStoreIterator implements
> AggregatedDataValueStoreIterator {
>
> private static final Log log =
> LogFactory.getLog(AggregatedDataValueStoreIterator.class);
>
> static RowMapper<AggregatedDataValue> rowmapper = new
> AggregatedDataValueRowMapper();
>
> private ResultSet resultSet;
>
> public ResultSet getResultSet() {
> return resultSet;
> }
>
> public void setResultSet(ResultSet resultSet) {
> this.resultSet = resultSet;
> }
>
> private StatementHolder holder;
>
> public StatementHolder getHolder()
> {
> return holder;
> }
>
> public void setHolder( StatementHolder holder )
> {
> this.holder = holder;
> }
>
> public JdbcAggregatedDataValueStoreIterator(ResultSet resultSet,
> StatementHolder holder) {
> this.resultSet = resultSet;
> this.holder = holder;
> }
>
> @Override
> public AggregatedDataValue next() {
> AggregatedDataValue row = null;
> try {
> if (resultSet.next()) {
> row = rowmapper.mapRow(resultSet);
> } else {
> this.close();
> }
> } catch (SQLException ex) {
> log.warn("Error reading aggregateddatavalue row: " + ex);
> }
> return row;
> }
>
> @Override
> public void close() {
> try {
> if (!resultSet.isClosed()) {
> resultSet.close();
> }
> } catch (SQLException ex) {
> log.warn("Error closing resultset: " + ex);
> }
>
> holder.close();
> }
> }
>
> This works very well, but now I also want to iterate over aggregate
> indicator values. Now obviously I could just copy and paste the above
> with minor adjustments, but it seems to makes sense to do this more
> generically. 95% of the code in the class is pretty generic. What I
> would like instead to have is an interface like:
>
> public interface StoreIterator<T> {
>
> // ----------------------------------------------------------------------
> // generic StoreIterator
> // ----------------------------------------------------------------------
>
> /**
> * Gets the next object value
> *
> * @return the object value or null.
> */
> T next();
>
> /**
> * Close any underlying resources
> *
> */
> void close();
> }
>
> That would be fine and dandy, but I can't implement the class
>
> public class JdbcStoreIterator<T> implements StoreIterator<T>
>
> by parameterizing the above JdbcAggregatedDataValueStoreIterator
> class. The problem has to do with the rowmapper in the class.
>
> I can't say:
>
> static RowMapper<T> rowmapper = new AggregatedDataValueRowMapper();
>
> because T is generic so I don't know the type of the rowmapper in
> advance and the AggregateDataValueRowMapper (presumably like all the
> other row mappers) is declared like:
>
> public class AggregatedDataValueRowMapper
> implements RowMapper<AggregatedDataValue>
>
> In desperation I tried adding an extra type parameter to the
> JdbcStoreIterator, like
>
> public class JdbcStoreIterator<T, R> implements StoreIterator<T>
>
> to pass in the rowmapper type, but it still defeats me - you can't
> "simply" instantiate a new object based on a Type and various tricks
> around Class<R> and getInstance() don't seem to work.
>
> Anybody have any good ideas of the best way to do this? Maybe I can
> pass in a concrete RowMapper<T> into the JdbcStoreIterator<T>
> constructor? Just thought of that now as a possibility and haven't
> tried it.
OK I just answered my own question. That works. Pleased as a pig in
sh**!. Sorry for the long email ...
>I have to confess i have a much better understanding of C++
> generics than the Java variant, which is probably working against me
> here :-(
>
> Failing which I will either return to copy and paste (which would have
> taken all of half an hour instead of 3 hours puzzling over this) or
> just do away with using the rowmapper at all and just program directly
> to the jdbc resultset.
>
> Cheers
> Bob
>
References