ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button
Article:
  Lightweight R/O Mapping
Subject:   Generics and Roundtrips
Date:   2005-12-08 22:01:09
From:   Norbert.Ehreke
Sean,


thank you for your candid thoughts. Let me clarify some of the issues you have raised.


It's important to understand Java Generics are a compiletime feature. This


List<Foo> list1 = ArrayList<Foo>();
List<Bar> list2 = ArrayList<Bar>();

becomes that

List list1 = ArrayList();
List list2 = ArrayList();

after compilation. The purpose of a BeanReader is to construct an object of an arbitrary class at runtime via reflection. The code BeanReader<T> can give me no information about class T at runtime, because T does not exist then. Assuming that your code might work I'll still need the specific argument T.class when instantiating the BeanReader. So, when I wrote that

ArrayList<T> list = reader.executeCreateBeanList( "..." );

will have the compiler issue a warning, I am right. Please
check "Tiger: A Developers Notebook" on page 29.


Still, you've raised a philosophical question: Suppose your
code works, I'd agree that it is explicit, but is it more concise? Considering type erasure and the fact that I need T.class to dynamically construct the required object (say, of type Jedi) would it be better to have a generified class BeanReader<Class<T>> to get rid of the unchecked type warning even though this information cannot be accessed for reflection? It might be nice to read, but seems cumbersome to code, wouldn't you say?


Then there is the issue you raised about roundtripping. You are
right: In the example you brought up, the code I showed would
perform poorly. What I did not show is that Amber supports you,
if you wanted to join the Jedis and the Fighters on the database return a result set that contains Jedis (redundantly in their respective columns) and their Fighters (individually). You'd then create a class that holds a Jedi plus one single Fighter, load a list of this class (1 database query) and wrap it in mapper code where you'd extract the Jedis with their Fighter list. Roughly, wrapper class might look like this.


class JediFighter {
private Jedi _jedi;
pirvate Fighter _fighter;
public JediFighter() {
_jedi = new Jedi();
_fighter = new Fighter();
}
// annotated Jedi accessors map to _jedi
// annotated Fighter accessors map to _fighter
}

The mapper code (in the client) would take a number of JediFighters and give you back a list of Jedis with their Fighters. It's not automatic and it requires an additional loop in the client, but when you need to minimize database calls, it does work with no roundtrips.


However it seems to me that we agree that table joins should be done in the database. The same goes for filtering. This begs the question, why would you want to load 10000 Jedis into the client? If the user will filter them, this should be done in the database, right?


I hope I shed some light on the issues you raised. Thanks again
for contributing your thoughts.


1 to 1 of 1
1 to 1 of 1