web-dev-qa-db-fra.com

Quelques doutes sur l'utilisation de RowMapper dans JDBC dans une application Spring Framework

J'étudie comment exécuter une requête sur une base de données à l'aide de JDBC dans Spring Framework.

Je suis ce tutoriel: http://www.tutorialspoint.com/spring/spring_jdbc_example.htm

Dans ce tutoriel, je définis une interface StudentDAO qui ne définit que la méthode CRUD souhaitée.

Ensuite, la classe Student est définie et correspond à l'entité que je souhaite conserver dans la table de la base de données Student.

On définit ensuite la classe StudentMapper qui est une implémentation spécifique de l'interface RowMapper qui, dans ce cas, est utilisée pour mapper un enregistrement spécifique dans le ResultSet (retourné). par une requête) à un objet Student.

Ensuite, j'ai le StudentJDBCTemplate qui représente l'implémentation de mon interface StudentDAO, dans cette classe, j'implémente la méthode CRUD définie dans l'interface.

Ok, et maintenant j'ai un doute sur le fonctionnement de la classe StudentMapper: dans cette classe StudentJDBCTemplate, la méthode qui renvoie la liste de tous les enregistrements de la table de la base de données Student est définie. , celui-là:

   public List<Student> listStudents() {
      String SQL = "select * from Student";
      List <Student> students = jdbcTemplateObject.query(SQL, 
                                new StudentMapper());
      return students;
   }

Comme vous pouvez le constater, cette méthode renvoie un objet List of Student et fonctionne comme suit:

la première chose à faire est de définir la requête qui renvoie tous les enregistrements de la table de la base de données Student} dans la chaîne SQL.

Ensuite, cette requête est exécutée par l'appel de la méthode de requête sur l'objet jdbcTemplateObject (c'est-à-dire une résistance de JdbcTemplate} Spring class **

Cette méthode utilise deux paramètres: la chaîne SQL (contenant la requête SQL à exécuter) et un nouvel objet StudentMapper prenant l'objet ResultSet renvoyé par la requête et mappe son enregistrement. sur un nouvel objet Student

En lisant ici: http://static.springsource.org/spring/docs/current/javadoc-api/org/springframework/jdbc/core/JdbcTemplate.html sayas que: Exécute une requête en mode SQL statique , mappant chaque ligne sur un objet Java via un RowMapper.

Mon doute est lié au fait que mon StudentMapper mappe un enregistrement ResultSet sur un objet Student à l'aide de la méthode mapRow (), voici le code:

package com.tutorialspoint;

import Java.sql.ResultSet;
import Java.sql.SQLException;
import org.springframework.jdbc.core.RowMapper;

public class StudentMapper implements RowMapper<Student> {
   public Student mapRow(ResultSet rs, int rowNum) throws SQLException {
      Student student = new Student();
      student.setId(rs.getInt("id"));
      student.setName(rs.getString("name"));
      student.setAge(rs.getInt("age"));
      return student;
   }
}

Alors, qui appelle cette méthode mapRow? est-il appelé automatiquement par le cadre de printemps? (parce que dans cet exemple, il n'est jamais appelé manuellement ...)

Tnx

Andrea

Ensuite, cette requête est exécutée par l'appel de la méthode de requête sur l'objet jdbcTemplateObject (c'est-à-dire une résistance de JdbcTemplate} Spring class **

15
AndreaNobili

Lorsque vous passez une instance de votre RowMapper à la méthode JdbcTemplate

List <Student> students = jdbcTemplateObject.query(SQL, new StudentMapper());

La variable JdbcTemplate, selon la méthode que vous avez appelée, utilisera en interne le mappeur avec le jeu de résultats qu'il obtient de la connexion JDBC pour créer un objet du type demandé. Par exemple, puisque vous avez appelé JdbcTemplate#query(String, RowMapper), la méthode utilisera votre String SQL pour interroger la base de données et effectuera une boucle sur chaque "ligne" du type ResultSet de la manière suivante:

ResultSet rs = ... // execute query
List<Student> students = ...// some list
int rowNum = 0;
while(rs.next()) {
    Student student = rowMapper.mapRow(rs, rowNum);
    students.add(student);
    rowNum++;
}

return students;

Ainsi, la méthode Spring de JdbcTemplate utilisera la RowMapper que vous fournissez et appellera sa méthode mapRow pour créer l'objet de retour attendu.

Vous voudrez peut-être consulter Data Mapper de Martin Fowler -/en conjonction avec Table Data Gateway pour une idée de la façon dont ces éléments sont distribués et fournissent un faible couplage .

22
Sotirios Delimanolis

Voici le modèle typique que j'utilise avec BeanPropertyRowMapper. Cela économise beaucoup de code. Votre requête doit aliaser chaque colonne pour correspondre au nom de la propriété dans la classe. Dans ce cas, species_name as species et les autres noms de colonnes correspondent déjà.

public class Animal {
    String species;
    String phylum;
    String family;
    ...getters and setters omitted
}

@Repository
public class AnimalRepository {
    private NamedParameterJdbcTemplate namedParameterJdbcTemplate;

    @Autowired
    public void setDataSource(DataSource dataSource) {
        this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
    }

    public List<Animal> getAnimalsByPhylum(String phylum) {
        String sql = " SELECT species_name as species, phylum, family FROM animals"
                 +" WHERE phylum = :phylum";

        Map<String, Object> namedParameters = new HashMap<String, Object>();
        namedParameters.put("phylum", phylum);
        SqlParameterSource params = new MapSqlParameterSource(namedParameters);
        List<Animal> records = namedParameterJdbcTemplate.query(sql,
                params, BeanPropertyRowMapper.newInstance(Animal.class));

        return records;
    }
}

Une alternative consiste à utiliser un RowMapper (cet exemple utilise uniquement une classe anonyme) lorsque vous avez besoin de plus de personnalisation par ligne:

    List<Animal> records = namedParameterJdbcTemplate.query(sql,
            params, new RowMapper<Animal>(){
        public Animal mapRow(ResultSet rs, int i) throws SQLException {
            Animal animal = new Animal();   
            animal.setSpecies(rs.getString("species_name"));
            if (some condition) {
                animal.setPhylum(rs.getString("phylum"));
            } else {
                animal.setPhylum(rs.getString("phylum")+someThing());
            }
            animal.setFamily(rs.getString("family"));

            return animal;
        }
    });
4
Jim

Utilisation de RowMapper au printemps

import Java.sql.ResultSet;
import Java.sql.SQLException;

import org.springframework.jdbc.core.RowMapper;

public class RowsMap implements RowMapper<EmpPojo>{

    @Override
    public EmpPojo mapRow(ResultSet rs, int counts) throws SQLException {
        EmpPojo em=new EmpPojo();
        em.setEid(rs.getInt(1));
        em.setEname(rs.getString(2));
        em.setEsal(rs.getDouble(3));

        return em;
    }

}

Finally in Main class

List<EmpPojo> lm=jt.query("select * from emps", new RowsMap());
for(EmpPojo e:lm)
{
    System.out.println(e.getEid()+" "+e.getEname()+" "+e.getEsal());
}
2
Raja Rao

Alors, qui appelle cette méthode mapRow? est-il appelé automatiquement par le Cadre de printemps? (parce que, dans cet exemple, il n'est jamais appelé manuellement ...)

Ceci est appelé automatiquement par spring framework . Tout ce dont vous avez besoin est de spécifier

  1. Paramètres de connexion,
  2. Instruction SQL
  3. Déclarer des paramètres et fournir des valeurs de paramètres
  4. Faites le travail pour chaque itération.
1
Arsen Alexanyan