I have a set of data objects, which correspond to rows in RDMS table, as in ClassA -> Rows of TableA ClassB -> Rows of TableB . . . ClassZ -> Rows of TableZ I am fetching these records using JDBC and creating objects from the result set(Please note that the result set can be huge) I have custom parsers for each class i.e parseClassA(), parseClassB()....parseClassZ(), currently i am having a function with a huge switch statement which determines the type of the class like switch(classType) and gives me an object of the corresponding class, i want to eliminate this switch statement, which is the optimal way to do this?
-
First, I'd say "optimal" might be the wrong word since there probably are multiple ways to do it. Those might have different tradeoffs so you'd need to better define "optimal". Second it also would depend on your code, requirements etc. but _one_ way to do it might be a `Map
`. Then you'd just try to get the parser out of that map and if you got one you call some method (e.g. something like `parse(ResultSet)`). – Thomas Jul 03 '17 at 12:22 -
2I think that what you are searching for is here. Maybe a dublicate subject? https://stackoverflow.com/a/6094602/3543153 – DamienB Jul 03 '17 at 12:23
-
@Thomas how would you construct the map? do you want me to construct the map everytime i query the database ? – kumarD Jul 03 '17 at 12:24
-
Possible duplicate of [Creating an instance using the class name and calling constructor](https://stackoverflow.com/questions/6094575/creating-an-instance-using-the-class-name-and-calling-constructor) – DamienB Jul 03 '17 at 12:24
-
Of course not. Since the map would probably not change at runtime you could create it when you start up the application or do it lazily. – Thomas Jul 03 '17 at 12:25
-
The Sql commands for fetching the resultset are also different for each class – kumarD Jul 03 '17 at 12:25
-
2Another option (and maybe a better one) would be to use an ORM (or at least look into what they are doing) such as Hibernate, EclipseLink etc. - In fact, what you describe is what ORMs are meant to do: map relational data to objects. Although you _could_ write one yourself you might want to save yourself some headaches and just use one of the frameworks that already solved 80% of the problems for you (those 80% being the most common cases). – Thomas Jul 03 '17 at 12:25
-
Thanks for the suggestions, i don't think ORM will work here because the data model of the resultset and the datamodel of the classes which i am parsing into are different – kumarD Jul 03 '17 at 12:31
-
Oh I'd bet you'd be surprised of what can done with ORM. You might have to change your code a bit but it might well be worth it. – Thomas Jul 04 '17 at 08:22
2 Answers
This is called an ORM - hibernate is far-and-away the most widely adopted. Or, you could opt for a DSL. However, since we are on the subject, and we might want to have a functional looking approach here are the outlines:
Stream.of(resultSet).flatMap(r -> someHowMakThisAStream(r))
But, you're lookup map should be of type
Map<String,Function<Map<String,Object>,T> lookup...
lookup.put("SomeTable", SomeClass::new);
You will want each class to take a Map of column names to values (normalizing) and not the resultset directly so that each instantiation can't accidentally forward the resultset too far.
Then you can, in psuedo functional, do: stream.of(results).flatMap().map(valMap -> lookup.get(tableName).apply(valMap))

- 5,150
- 3
- 38
- 76
You could use a map structure that associates the class to create to the parser to create it :
Map<Class<?> clazz, Supplier<Parser>>
You could initialize the map with all required mappings :
static{
parserByClass = new HashMap<>();
parserByClass.put(MyClass.class, MyParserMyClass::new);
parserByClass.put(MyOtherClass.class, MyOtherParserMyClass::new);
...
}
When you need to create a specific class, you could use the map to retrieve the parser of this class:
Parser<MyClass> parser = parserByClass.get(MyClass.class).get();
You can so call the parse()
method of the parser :
ResultSet resultSet = ...;
MyClass parse = parser.parse(resultSet);
Ideally, you should have a Parser
interface to define the parse()
method and to allow to define the returned type :
public interface Parser<T> {
T parse(ResultSet resultSet);
}
Please note that it is a untested code.

- 125,838
- 23
- 214
- 215