J’essaie de développer DAO générique en java. J’ai essayé le suivant. Est-ce un bon moyen d’implémenter DAO générique? Je ne veux pas utiliser l’hibernation. J’essaie de le rendre aussi générique que possible pour ne pas avoir à répéter le même code encore et encore.
public abstract class AbstractDAO { protected ResultSet findbyId(Ssortingng tablename, Integer id){ ResultSet rs= null; try { // the following lines are not working pStmt = cn.prepareStatement("SELECT * FROM "+ tablename+ "WHERE id = ?"); pStmt.setInt(1, id); rs = pStmt.executeQuery(); } catch (SQLException ex) { System.out.println("ERROR in findbyid " +ex.getMessage() +ex.getCause()); ex.printStackTrace(); }finally{ return rs; } } }
Maintenant j’ai:
public class UserDAO extends AbstractDAO{ public List findbyid(int id){ Resultset rs =findbyid("USERS",id) // "USERS" is table name in DB List users = convertToList(rs); return users; } private List convertToList(ResultSet rs) { List userList= new ArrayList(); User user= new User();; try { while (rs.next()) { user.setId(rs.getInt("id")); user.setUsername(rs.getSsortingng("username")); user.setFname(rs.getSsortingng("fname")); user.setLname(rs.getSsortingng("lname")); user.setUsertype(rs.getInt("usertype")); user.setPasswd(rs.getSsortingng("passwd")); userList.add(user); } } catch (SQLException ex) { Logger.getLogger(UserDAO.class.getName()).log(Level.SEVERE, null, ex); } return userList; } }
Si vous pouvez vivre avec Spring, je proposerai les améliorations suivantes:
Indépendamment de l’utilisation de Spring, je recommanderai les éléments suivants:
Un AbstractDao avec Spring amélioré:
import java.util.Collection; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; public abstract class AbstractDao { protected final RowMapper rowMapper; protected final Ssortingng findByIdSql; protected final JdbcTemplate jdbcTemplate; protected AbstractDao(RowMapper rowMapper, Ssortingng tableName, JdbcTemplate jdbcTemplate) { this.rowMapper = rowMapper; this.findByIdSql = "SELECT * FROM " + tableName + "WHERE id = ?"; this.jdbcTemplate = jdbcTemplate; } public Collection findById(final Ssortingng id) { Object[] params = {id}; return jdbcTemplate.query(findByIdSql, params, rowMapper); } }
Comme vous le voyez, aucune exception ni manipulation ni piratage avec les classes SQL primitives. Ce modèle ferme le ResultSet pour vous, ce que je ne vois pas dans votre code.
Et le UserDao:
import java.sql.ResultSet; import java.sql.SQLException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; public class UserDao extends AbstractDao { private final static Ssortingng TABLE_NAME = "USERS"; public UserDao(JdbcTemplate jdbcTemplate) { super(new UserRowMapper(), TABLE_NAME, jdbcTemplate); } private static class UserRowMapper implements RowMapper { public User mapRow(ResultSet rs, int rowNum) throws SQLException { User user = new User(); user.setUserName(rs.getSsortingng("username")); user.setFirstName(rs.getSsortingng("fname")); user.setLastName(rs.getSsortingng("lname")); return user; } } }
Actualisé:
Lorsque vous savez que l’id et que l’id correspond à une seule ligne de la firebase database, envisagez de renvoyer un object générique au lieu d’une collection.
public T findUniqueObjectById(final Ssortingng id) { Object[] params = {id}; return jdbcTemplate.queryForObject(findByIdSql, params, rowMapper); }
Cela rend votre code de service plus lisible, car vous n’avez pas besoin de récupérer l’utilisateur depuis une liste, mais seulement:
User user = userDao.findUniqueObjectById("22");
Mon conseil:
Exemple
// Create or inject underlying DataSource. DataSource ds = ... // Initialise Spring template, which we'll use for querying. SimpleJdbcTemplate tmpl = new SimpleJdbcTemplate(ds); // Create collection of "Role"s: The business object we're interestd in. Set roles = new HashSet (); // Query database for roles, use row mapper to extract and create // business objects and add to collection. If an error occurs Spring // will translate the checked SQLException into an unchecked Spring // DataAccessException and also close any open resources (ResultSet, Connection). roles.addAll(tmpl.query("select * from Role", new ParameterizedRowMapper () { public Role mapRow(ResultSet resultSet, int i) throws SQLException { return new Role(resultSet.getSsortingng("RoleName")); } }));
Ça va mais change de méthode
private List convertToList(ResultSet rs) { List userList= new ArrayList(); User user= new User();; try { while (rs.next()) { user.setId(rs.getInt("id")); user.setUsername(rs.getSsortingng("username")); user.setFname(rs.getSsortingng("fname")); user.setLname(rs.getSsortingng("lname")); user.setUsertype(rs.getInt("usertype")); user.setPasswd(rs.getSsortingng("passwd")); userList.add(user); } } catch (SQLException ex) { Logger.getLogger(UserDAO.class.getName()).log(Level.SEVERE, null, ex); } return userList; }
à
private List convertToList(ResultSet rs) { List userList= new ArrayList (); try { while (rs.next()) { User user= new User(); user.setId(rs.getInt("id")); user.setUsername(rs.getSsortingng("username")); user.setFname(rs.getSsortingng("fname")); user.setLname(rs.getSsortingng("lname")); user.setUsertype(rs.getInt("usertype")); user.setPasswd(rs.getSsortingng("passwd")); userList.add(user); } } catch (SQLException ex) { Logger.getLogger(UserDAO.class.getName()).log(Level.SEVERE, null, ex); } return userList; }
L’object utilisateur doit être créé à l’intérieur de la boucle while.
Ne réinventez pas la roue, vous pouvez déjà y trouver de bons projets, par exemple un projet generic-dao sur google.
EDIT: a répondu trop rapidement probablement, le projet Google est basé sur JPA mais vous pouvez néanmoins utiliser certains des concepts qu’il contient.
Vous devez append un espace avant votre clause “WHERE”, voir ci-dessous:
pStmt = cn.prepareStatement("SELECT * FROM "+ tablename+ "WHERE id = ?");
à
pStmt = cn.prepareStatement("SELECT * FROM "+ tablename+ " WHERE id = ?");
Si j’ai bien compris l’énoncé du problème, vous essayez d’implémenter une sorte de couche d’isolation entre vos services et une firebase database standard exposée via une interface JDBC. La couche d’isolation servirait de mappeur de données de vos objects de domaine POJO aux ensembles de données SQL. C’est précisément la tâche de la bibliothèque iBATIS , sur laquelle je vous recommande de réfléchir au lieu d’implémenter la classe homebrew GenericDAO.
Même si tout le monde suggère Spring et son API, elle utilise des métadonnées et constitue une mauvaise combinaison de code. Donc, n’utilisez pas DAO générique ou Spring du tout.
Le code générique est lourd et multiplie votre charge.