I've just developped an alternative solution for this problem using only a Mapper.
Updating the example from Thierry:
class A {
int id;
String name;
List<B> bList;
}
class B {
int id;
String description;
}
Create a Mapper for A following this pattern:
public class AMapper implements ResultSetMapper<Empresa> {
private A mA;
@Override
public A map(int index, ResultSet r, StatementContext ctx) throws SQLException {
short id = r.getShort("id");
// TODO: resolve boilerplate
if (index == 0) {
mA= new A();
a.setId(id);
a.setName(r.getString("name"));
} else if (empresa.getId() != id) {
mA= new A();
a.setId(id);
a.setName(r.getString("name"));
}
B b = new B();
b.setId(r.getShort("b_id"));
b.setDescription(r.getString("description"));
// Avoid inserting empty bean
if (b.getId() > 0) mA.getBList().add(b);
return mA;
}
}
And your DAO must return a Set (never a List!)
Example:
@SqlQuery("SELECT id, name,
b.id as b_id, description, FROM a left join b on b.a_id =
a.id")
@Mapper(AMapper.class)
Set<A> findAll();
Note that the fact that you get a Set from the query it guarantees that you won't receive repeated objects.
I took advantage of the fact that a Set keeps the ultimate inserted instance of equal objects.
Of course, you must implement Equals and Hashcode in your model object.
Another advantage - besides the ease and clarity of implementation - from this solution is that it's not necessary to iterate twice over the result (as in the above example), but only once, representing a great processing gain.
I would appreciate enhancements.
Thanks.