DAO générique en java

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:

  • Laissez Spring faire la gestion des exceptions.
  • Utilisez JdbcTemplate au lieu de créer vous-même des instructions préparées.

Indépendamment de l’utilisation de Spring, je recommanderai les éléments suivants:

  • N’envoyez pas le nom de la table en paramètre. Cela devrait être fait dans la phase d’initialisation.
  • Utilisez une chaîne sur le paramètre id, car c’est beaucoup plus générique.
  • Envisagez de renvoyer un object générique au lieu d’une collection, car celle-ci doit toujours contenir un seul object.

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:

  • Ne pas écrire un DAO générique; Les classes génériques reviennent vous mordre quand vous réalisez qu’elles ne font pas tout ce dont vous avez besoin dans une situation donnée et finissent souvent par devenir de plus en plus complexes pour couvrir le nombre croissant de cas d’utilisation. Mieux vaut coder les DAO spécifiques à une application, puis tenter de générer ultérieurement un comportement commun.
  • Envisagez d’utiliser Spring JDBC pour écrire des DAO spécifiques à une application, mais de manière beaucoup plus compacte et moins sujette aux erreurs que JDBC. De plus, contrairement à Hibernate, Spring JDBC n’agit que comme une fine pellicule autour du JDBC brut, ce qui vous donne un contrôle plus fin et une visibilité accrue.

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.