patternjavaModerate
Generic DAO written in Java
Viewed 0 times
genericwrittendaojava
Problem
I initially thought that this was just an architecture issue so I placed it on programmers as Thoughts on refactoring a generic DAO. Then I asked on codereview meta here and decided to put up the code here.
My architecture is like this
My concern
-
These
- Here's a github link if someone wants to see there.
- There are four DAOs - DAODelete, DAOUpdate, DAORead, DAOInsert but I am just putting DAORead and its implementation here so that it is easier to review.
- I have trimmed the code a lot so if something is amiss please tell me and I'll correct it. Otherwise you can see github link as it has complete code(kinda).
My architecture is like this
- Abstraction layer of DAO at top
- DataBase specific implementation of DAO BUT Table-independent
- Table dependency is passed down to a lower utility layer
- A
Enumis passed down to the lower utility layer by which it gives table specific results
- Table-specific utility classes for the lower utility layer mentioned in the previous point.
- There is a
Studentpojo that I am omitting because well it is just a pojo.privatevariables and all. Just note thatenrollmentDateis of typejava.sql.Date
My concern
- I am satisfied with the upper layer of DAO but I think that at the the lower level specifically at the
OracleSpecific.javathe things which should have strong coupling have weak coupling. e.g. there are different methods for getting pojo from resultset or getting primary key. Each of these in turn haveswitchcase for calling the functions in lower utility class.
- Although the
schema-specificmethods are tied together in different utility classes the method call themselves inOracleSpecifics.javado not have any coupling.
- I am thinking whether I should change the enum
TableNameto contain a specific state. The state I am thinking for the schema-specific lowest level utility classes.
-
These
specific states contained in enums can be used to change the state of DAO and the DAO can then call the specific functions based on an inSolution
I'll leave the actual generic DAO discussions out of this answer for now, and just offer my two cents on coding styles...
-
You can use better method names instead of
-
You can inline your conditional checks in the
-
Actually, I'm not that sure whether you really need to map the Pojo in order to determine if a row with the primary key exists or not... Perhaps there's a simpler way?
edit:
-
You can use better method names instead of
getPojo... Pojo is well-understood but still quite an informal term, and you'll probably attract equal comments whether to keep it all caps or not - it's an acronym afterall. The Spring framework calls their helper classes RowMappers with a mapRow method, so maybe you want to follow something like that. http://docs.spring.io/spring/docs/3.0.x/api/org/springframework/jdbc/core/RowMapper.html-
You can inline your conditional checks in the
return statements as such:@Override
public boolean alreadyExisting(Connection con, TableName tableName,
String primaryKey) throws SQLException {
return getPojoForPrimarKey(con, tableName, primaryKey) != null;
}
@Override
public boolean alreadyExisting(Connection con, TableName tableName,
T currentPojo) throws SQLException {
return alreadyExisting(con, tableName, OracleSpecifics. getPrimaryKey(tableName, currentPojo));
}-
Actually, I'm not that sure whether you really need to map the Pojo in order to determine if a row with the primary key exists or not... Perhaps there's a simpler way?
edit:
- Your
Oracle*classes don't really have anything Oracle-specific now, I'm not sure if that is intended because things are still work-in-progress. Or do you mean you will be creating new classes for other RDBMS software like MySQL, MariaDB etc. with their own dialect?
- DAOs should not need to keep 'states' beyond the current
ResultSetobject that it is doing the mapping for. You may need to re-consider your implementation of theTableNameenum to contain a specific state. More clarification is needed here.
- After another quick reading, you may want to consider the 'generic-ness' of your approach, because it appears that adding new classes (aka entities) to pass to your DAO framework requires a
Specclass (or updating your existingSpecStudent) for the actual implemention (e.g. calling all the getter methods on yourStudentclass), and updating yourTableNameenum as well. Maybe you can also consider using reflection for the implementation, so that there is less code to update in the long run?
Code Snippets
@Override
public <T> boolean alreadyExisting(Connection con, TableName tableName,
String primaryKey) throws SQLException {
return getPojoForPrimarKey(con, tableName, primaryKey) != null;
}
@Override
public <T> boolean alreadyExisting(Connection con, TableName tableName,
T currentPojo) throws SQLException {
return alreadyExisting(con, tableName, OracleSpecifics.<T> getPrimaryKey(tableName, currentPojo));
}Context
StackExchange Code Review Q#36519, answer score: 11
Revisions (0)
No revisions yet.