Ho progettato un DAO generico in Java e sto avendo confusione sul fatto di rifattorizzarlo con un design diverso o meno.
PS Non dire di usare il framework per terze persone già esistente. So che ci sono alcuni presenti ma sto imparando Java e schemi di progettazione, quindi ho bisogno di tutta la pratica che posso ottenere.
Se c'è qualche confusione, per favore chiedi e ti chiarirò.
L'attuale architettura
DAOFactory.java
- Contiene i metodi
abstract
per la creazione diDAODelete
,DAOUpdate
e altre 2 interfacce che devono essere implementate da classi di implementazione concrete -
public
Metodo di classe per la creazione del calcestruzzo Fabbriche per la produzione dell'attuazione concreta delle interfacce menzionate in precedenza.
DAORead.java
public abstract <T> T getPojoForPrimarKey(Connection con,
TableName tableName, String primaryKey) throws SQLException;
Analogamente nelle altre mie interfacce ho metodi generici.
- Qui
Connection
viene passato dal livello di servizio e chiuso lì per la gestione delle transazioni. -
TableName
è un enum che sto usando per avere un caso switch nel livello inferiore di DAO per chiamare le funzioni specifiche della tabella. Anche usare un enum mi sta aiutando nel controllo dei tipi.
OracleRead.java
@Override
public <T> T getPojoForPrimarKey(Connection con, TableName tableName,
String primaryKey) throws SQLException {
T currentPojo = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
String queryString = OracleSpecifics.queryString(tableName,
primaryKey, QueryType.READ);
ps = con.prepareStatement(queryString);
rs = ps.executeQuery();
if (rs.next()) {
currentPojo = OracleSpecifics.getPojoFromResultSet(tableName, rs);
}
} finally {
DAOFactory.closeAll(ps, rs);
}
return currentPojo;
}
Ecco come ho implementato la funzione deleteFrom
dall'interfaccia nella classe concrete.
Qui OracleSpecifics
è il livello inferiore di DAO di cui stavo parlando. In pratica contiene% casi diswitch
per verificare la tabella specifica.
OracleSpecifics.java
// These functions call table-specific functions
@SuppressWarnings("unchecked")
static <T> T getPojoFromResultSet(TableName tableName, ResultSet rs)
throws SQLException {
switch (tableName) {
case ASEEM_MASTER:
case ASEEM_MASTER_TEMP:
return (T) SpecAseemMaster.getPojo(rs);
case AUTHENTICATE_TABLE:
return (T) SpecAseemRole.getPojo(rs);
default:
return null;
}
}
Qui SpecAseemMaster
e SpecAseemRole
sono livelli specifici di tabella (in particolare dello schema) che producono i campi richiesti
SpecAseemRole.java
public static AuthenticationDetails getPojo(ResultSet rs)
throws SQLException {
AuthenticationDetails cur = new AuthenticationDetails();
cur.setUserName(rs.getString(1));
cur.setPassWord(rs.getString(2));
cur.setRole(rs.getString(3));
return cur;
}
Nel livello di servizio
Il tipo con cui viene chiamato il metodo DAO è il Pojo che rappresenta i campi dati dello schema. per es.
myFactory.getDAORead().<AuthenticationDetails> getPojoForPrimarKey(con, CUR_TABLE, primaryKey);
Qui AuthenticationDetails
è il mio Pojo aka DTO per la comunicazione tra il mio controller e il livello di servizio (nel modello).
Nota che sto dando solo una panoramica nel modo più semplice. Ci sono 4 interfacce nei DAO astratti contenenti un totale di metodi di 8 abstract
implementati da 4 classi concrete. Tutte queste classi generiche dipendono da un livello inferiore in DAO per ottenere query specifiche, PreparedStatement
s ecc., Che chiama inoltre funzioni nelle funzioni della classe di utilità ausiliaria in base al tableName
trasmesso su questa gerarchia. Il livello inferiore è specifico dello schema.
La mia confusione sul refactoring
- Sono soddisfatto degli strati superiori di DAO, ma penso che al livello più basso, in particolare a
OracleSpecific
, le cose che dovrebbero avere un accoppiamento strong abbiano un accoppiamento debole. per esempio. ci sono diversi metodi per ottenerePreparedStatement
per l'inserimento e l'aggiornamento. Ognuno di questi a sua volta haswitch
per chiamare le funzioni nella classe di utilità inferiore. -
Sebbene i metodi
schema-specific
siano legati insieme in diverse classi di utilità, il metodo si chiama inOracleSpecifics.java
non ha alcun accoppiamento. - Sto pensando se dovrei cambiare l'enum
TableName
per contenere uno stato specifico . Lo stato che sto pensando per le classi di utilità di livello più basso specifiche dello schema. -
Questi
specific states
contenuti nelle enumerazioni possono essere utilizzati per modificare lo stato di DAO e DAO può quindi chiamare le funzioni specifiche basate su un'interfaccia implementata da tutti questi stati. Quindi, a seconda dello stato, il comportamento può cambiare automaticamente. -
Questa decisione di progettazione è corretta o sarebbe priva di significato?
- Qualunque altra cosa che potrei aver trascurato?
- Qualche idea sul design stesso?
- Perderò la sicurezza del tipo introdotta dai generici a causa di questa modifica?