HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaModerate

Generic DAO written in Java

Submitted by: @import:stackexchange-codereview··
0
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.

  • 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 Enum is 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 Student pojo that I am omitting because well it is just a pojo. private variables and all. Just note that enrollmentDate is of type java.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.java the 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 have switch case for calling the functions in lower utility class.



  • Although the schema-specific methods are tied together in different utility classes the method call themselves in OracleSpecifics.java do not have any coupling.



  • I am thinking whether I should change the enum TableName to 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 in

Solution

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 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 ResultSet object that it is doing the mapping for. You may need to re-consider your implementation of the TableName enum 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 Spec class (or updating your existing SpecStudent) for the actual implemention (e.g. calling all the getter methods on your Student class), and updating your TableName enum 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.