Heterogenous Containers... JDBC (Part 3)
/**
* Use to query for {@link Person}s
*/
public class PersonService
{
/**
* All columns related to the person.
*/
private static class Columns
{
public static final Column<Integer> ID =
Column.newIntegerType("id");
public static final Column<String> NAME =
Column.newStringType("name");
public static final Column<Date> DATE =
Column.newDateType("date");
public static final ArrayList<Column<?>> ALL =
new ArrayList<Column<?>>()
{
{
this.add(Columns.ID);
this.add(Columns.NAME);
this.add(Columns.DATE);
}
};
}
/**
* Implementation of a template handler
* to create a new Person out of a Row
*/
private static final ResultSetHandler<Person> PERSON_TEMPLATE_HANDLER =
new ResultSetListHandler<Person>(Columns.ALL)
{
@Override
protected Person newType(Row row)
{
Integer id = row.get(Columns.ID);
String name = row.get(Columns.NAME);
Date date = row.get(Columns.DATE);
return new PersonBuilder()
.id(id)
.name(name)
.date(date)
.build();
}
};
/**
* Handler to use when retrieving a list of {@link Person}s
*/
private static final ResultSetHandler<List<Person>> PERSONS_HANDLER =
new ResultSetListHandler<Person>(PERSON_TEMPLATE_HANDLER);
private static final String SELECT_PERSONS =
"SELECT id, name, date, FROM person";
private final DataSource datasource;
PersonService(DataSource datasource)
{
this.datasource = datasource;
}
public List<Person> list() throws SQLException
{
QueryRunner queryRunner = new QueryRunner(this.datasource);
return queryRunner.query(SELECT_PERSONS, PERSONS_HANDLER);
}
}
From the client code side all we have to do is define the columns related to the type we’d like to query on as well as implement TemplateResultSetHandler to create an instance of it from a Row. Finally use a MultipleResultSetHandler to list all using a QueryRunner.
Going further you could introduce an annotation
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Column
{
Class<?> type();
String name();
}
to define columns on the actual type like
public class Person
{
@Column(type=Integer.class, name="id")
private final Integer id;
}
and with a little help from BeanUtils you can map them to your type thus making a step towards creating a simple CRUD framework.
Hopefully these posts gave you a better understanding over heterogeneous containers as well as spur some ideas on how to use them to your benefit.
Next on Heterogenous Containers, How to think of JSON.
You can read more about the builder pattern as part of the Don’t lose your train of thoughts series