JellyBean

The following examples will work with the following example domain classes:

//---------------------------------------------------------
// Parent class to demonstrate inheritance.
// (Also shows that MapToData annotations are optional.)
//---------------------------------------------------------
public abstract class Jelly {
  private Long jellyId;
  private String jellyType;
}
//---------------------------------------------------------
// Domain class demonstrating aggregate classes.
// Note the two approaches to aggregates:
//  1. Set isAggregateTarget in the annotation.
//  2. Setup the Aggregate classes when constructing the 
//     mapper.
//---------------------------------------------------------
public class JellyBean extends Jelly { 
  String targetMarket;
  BigDecimal weight;
  @MapToData (columnPrefix = "flavour_")
  JellyAttribute flavour; 
  @MapToData (columnPrefix = "colour_")
  JellyAttribute colour; 
  @MapToData (isAggregateTarget = true)
  JellyCompany company;
}
//---------------------------------------------------------
// Domain class demonstrating column alias.
//---------------------------------------------------------
public class JellyCompany {
  @MapToData
  String companyName;
  @MapToData ( columnAliases= { "company_address" } )
  String address;
}
//---------------------------------------------------------
// By default annotations are required.
// This domain class demonstrating the effect of including the
// annotations just to document that something will occur
// for the annoted fields. (It is obvious that anotherValue
// will not be mapped when annotations are required).
//---------------------------------------------------------
public class JellyAttribute { 
  @MapToData
  String name;
  @MapToData
  String value;
  String anotherValue;
}
//---------------------------------------------------------
// Second domain class for inheritance example.
//---------------------------------------------------------
public class JellyCup extends Jelly {
  String productName;
  @MapToData ( columnAliases = { "cup_volume" } )
  BigDecimal volume;
  @MapToData (columnPrefix = "shape_")
  JellyAttribute shape;
}

JDBC Examples

With no configuration, the result set mapper requires @MapToData annotations. Populate the JellyCompany:

ResultSet results = stmt.executeQuery("SELECT * FROM jelly_companies");

ResultSetMapper<JellyCompany> resultSetMapper = new ReflectionResultSetMapper<JellyCompany>(JellyCompany.class);

while (results.next()) {
  JellyCompany jellyCompany = resultSetMapper.mapRow(resultSet);
  // Order some jelly beans.
}

Turn off annotations requirement and specify the aggregate classes that have not be marked via annotations. Populate the JellyBean:

ResultSet results = stmt.executeQuery("SELECT * FROM jellies");

ResultSetMapper<JellyBean> resultSetMapper = new ReflectionResultSetMapper<JellyBean>(JellyBean.class);
resultSetMapper.setAnnotationRequired(false);
// If the aggregates were all marked in the annotations, the aggregate setup would not be required.
List<Class> aggregateClasses = new ArrayList<Class>();
aggregateClasses.add(JellyAttribute.class);
resultSetMapper.setAggregateTargets(aggregateClasses);

while (results.next()) {
  JellyBean jellyBean = resultSetMapper.mapRow(resultSet);
  // Eat the jelly bean.
}

Spring JDBC Examples

RowCallbackHandler

Use a wrapper for RowCallbackHandler.

JellyCompany:

CallbackResultSetMapper<JellyCompany> mapper = new CallbackResultSetMapper<JellyCompany>(JellyCompany.class);

JdbcTemplate template = new JdbcTemplate(dataSource);
template.query("SELECT * FROM jelly_companies", mapper);

List<JellyCompany> jellyCompanies = mapper.getObjects();

JellyBean:

CallbackResultSetMapper<JellyBean> mapper = new CallbackResultSetMapper<JellyBean>(JellyBean.class);
List<Class> aggregateClasses = new ArrayList<Class>();
aggregateClasses.add(JellyAttribute.class);
mapper.setAggregateTargets(aggregateClasses);
mapper.setAnnotationRequired(false);

JdbcTemplate template = new JdbcTemplate(dataSource);
template.query("SELECT * FROM jellies", mapper);

List<JellyBean> jellyBeans = mapper.getObjects();

ParameterizedRowMapper

Use a wrapper for ParameterizedRowMapper.

JellyCompany:

ResultSetRowMapper<JellyCompany> mapper = new ResultSetRowMapper<JellyCompany>(JellyCompany.class);

SimpleJdbcTemplate simpleTemplate = new SimpleJdbcTemplate(dataSource);
JellyCompany jellyCompany = simpleTemplate.queryForObject("SELECT * FROM jelly_companies WHERE company_id = ?", mapper, companyId);

JellyBean:

ResultSetRowMapper<JellyBean> mapper = new ResultSetRowMapper<JellyBean>(JellyBean.class);
List<Class> aggregateClasses = new ArrayList<Class>();
aggregateClasses.add(JellyAttribute.class);
mapper.setAggregateTargets(aggregateClasses);
mapper.setAnnotationRequired(false);

SimpleJdbcTemplate simpleTemplate = new SimpleJdbcTemplate(dataSource);
JellyBean jellyBean = simpleTemplate.queryForObject("SELECT * FROM jellies WHERE jelly_id = ?", mapper, jellyId);

Apache DBUtils Examples

Use a mapping BeanProcessor implementation.

JellyCompany:

MappingBeanProcessor<JellyCompany> processor = new MappingBeanProcessor<JellyCompany>(JellyCompany.class);

QueryRunner queryRunner = new QueryRunner(dataSource);

ResultSetHandler handler = new BeanListHandler(Object.class,
  new BasicRowProcessor(processor));

List<JellyCompany> jellyCompanies;
try {
  jellyCompanies = (List<JellyCompanies>) queryRunner.query("SELECT * FROM jelly_companies", handler);
} catch (SQLException e) {
  throw new RuntimeException(e);
}

JellyBean:

MappingBeanProcessor<JellyBean> processor = new MappingBeanProcessor<JellyBean>(JellyBean.class);
ReflectionResultSetMapper<JellyBean> mapper = processor.getReflectionResultSetMapper();
List<Class> aggregateClasses = new ArrayList<Class>();
aggregateClasses.add(JellyAttribute.class);
mapper.setAggregateTargets(aggregateClasses);
mapper.setAnnotationRequired(false);

QueryRunner queryRunner = new QueryRunner(dataSource);

ResultSetHandler handler = new BeanListHandler(Object.class,
  new BasicRowProcessor(processor));

List<JellyBean> jellyBeans;
try {
  jellyBeans = (List<JellyBean>) queryRunner.query("SELECT * FROM jellies", handler);
} catch (SQLException e) {
  throw new RuntimeException(e);
}

Inheritance Examples

In all the above examples the JellyBean class was used to construct the ResultSetMapper. For inheritance, construct with a list of classes, and supply some way of determining which object to keep when processing a ResultSet row. This determination can be via the domain class implementing the ClassValidator interface, or by suppling an ObjectValidator (shown here):

List<Class> targetClasses = new ArrayList<Class>();
targetClasses.add(JellyBean.class);
targetClasses.add(JellyCup.class);
ObjectValidator jellyValidator = new JellyValidator();


// JDBC
ResultSetMapper<Jelly> resultSetMapper = new ReflectionResultSetMapper<Jelly>(targetClasses);
resultSetMapper.setObjectValidator(jellyValidator);

// Apache DBUtils
MappingBeanProcessor<Jelly> processor = new MappingBeanProcessor<Jelly>(targetClasses);
processor.getReflectionResultSetMapper().setObjectValidator(jellyValidator);

// Spring ParameterizedRowMapper
ResultSetRowMapper<Jelly> mapper = new ResultSetRowMapper<Jelly>(targetClasses);
mapper.setObjectValidator(jellyValidator);

// Spring RowCallbackHandler
CallbackResultSetMapper<Jelly> mapper = new CallbackResultSetMapper<Jelly>(targetClasses);
mapper.setObjectValidator(jellyValidator);

Instead of supplying an ObjectValidator, you could have the domain classes implement the ClassValidator interface:

public abstract class Jelly implements ClassValidator {
  private Long jellyId;
  private String jellyType;
}
public class JellyBean extends Jelly { 
  String targetMarket;
  BigDecimal weight;
  @MapToData (columnPrefix = "flavour_")
  JellyAttribute flavour; 
  @MapToData (columnPrefix = "colour_")
  JellyAttribute colour; 
  @MapToData (isAggregateTarget = true)
  JellyCompany company;

  public boolean isValid() {
    if (jellyType.equals("jellybean") {
      return true;
    }
    return false;
  }
}
public class JellyCup extends Jelly {
  String productName;
  @MapToData ( columnAliases = { "cup_volume" } )
  BigDecimal volume;
  @MapToData (columnPrefix = "shape_")
  JellyAttribute shape;

  public boolean isValid() {
    if (jellyType.equals("jellycup") {
      return true;
    }
    return false;
  }
}