Некоторые сомнения в использовании RowMapper в JDBC в приложении Spring Framework

Я изучаю, как выполнять запрос в базе данных с помощью JDBC в Spring Framework.

Я следую этому руководству: http://www.tutorialspoint.com/spring/spring_jdbc_example.htm

В этом уроке я определяю интерфейс StudentDAO, который определяет только метод CRUD.

Затем определяется класс Студент, который является объектом, который я хочу сохранить в таблице базы данных учащихся.

Затем определяется класс StudentMapper, который представляет собой конкретную реализацию интерфейса RowMapper, который в этом случае используется для сопоставления определенной записи в ResultSet (возвращенный запросом) в объект Студент.

Затем у меня есть StudentJDBCTemplate, который представляет реализацию моего интерфейса StudentDAO, в этом классе я реализую метод CRUD, который был определен в интерфейсе.

Хорошо, и теперь у меня есть сомнение в том, как работает класс StudentMapper: в этом классе StudentJDBCTemplate указан метод, который возвращает список всех записей, которые в таблице базы данных Студента:

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

Как вы можете видеть, этот метод возвращает объект List of Student и работает следующим образом:

первое, что он делает, это определить запрос, который возвращает всю запись в таблице базы данных Student в SQL String.

Затем этот запрос выполняется вызовом метода запроса в объекте jdbcTemplateObject (это istance JdbcTemplate Spring class **

Этот метод принимает два параметра: SQL String (содержащий SQL-запрос, который должен быть выполнен) и новый объект StudentMapper, который принимает объект ResultSet, возвращенный запросить и сопоставить запись на новом объекте Student

Чтение здесь: http://static.springsource.org/spring/docs/current/javadoc-api/org/springframework/jdbc/core/JdbcTemplate.html sayas, что: Выполнять запрос, заданный статическим SQL, сопоставляя каждую строку с объектом Java через RowMapper.

Мое сомнение связано с тем, что мой StudentMapper сопоставляет запись ResultSet на объекте Student с помощью метода mapRow(), это код:

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;
   }
}

Итак, кто вызывает этот метод mapRow? это автоматически называется Spring Framework? (потому что в этом примере никогда не вызывается вручную...)

Тпх

Andrea

Затем этот запрос выполняется вызовом метода запроса в объекте jdbcTemplateObject (это istance JdbcTemplate Spring class **

Ответы

Ответ 1

Когда вы передаете экземпляр вашего RowMapper в метод JdbcTemplate

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

JdbcTemplate, в зависимости от того, какой метод вы вызывали, будет внутренне использовать mapper с набором результатов, который он получает от JDBC Connection, чтобы создать объект вашего запрошенного типа. Например, поскольку вы вызвали JdbcTemplate#query(String, RowMapper), метод будет использовать ваш String SQL для запроса базы данных и будет проходить через каждую "строку" в виде ResultSet, как это:

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;

Итак, метод Spring JdbcTemplate будет использовать RowMapper, который вы предоставляете, и вызывать его метод mapRow для создания ожидаемого объекта возврата.

Вам может понравиться посмотреть Мартин Фаулер Data Mapper в сочетании с Table Data Gateway для идеи как распределяются эти вещи и обеспечивают низкую связь.

Ответ 2

Вот типичный образец, который я использую с BeanPropertyRowMapper. Это экономит много кодирования. Ваш запрос должен иметь псевдоним каждого столбца, чтобы он соответствовал имени свойства в классе. В этом случае species_name as species и другие имена столбцов уже совпадают.

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;
    }
}

Альтернативой является использование RowMapper (этот пример просто использует анонимный класс), когда вам нужно больше настроек для каждой строки:

    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;
        }
    });

Ответ 3

Использование RowMapper в Spring

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());
}

Ответ 4

Итак, кто вызывает этот метод mapRow? он автоматически вызывается Spring Рамки? (потому что в этом примере никогда не вызывается вручную...)

Это автоматически вызывается инфраструктурой Spring. Все, что вам нужно, это указать

  • Параметры подключения,
  • Оператор SQL
  • Объявлять параметры и предоставлять значения параметров
  • Выполняйте работу для каждой итерации.