Некоторые сомнения в использовании 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
- Объявлять параметры и предоставлять значения параметров
- Выполняйте работу для каждой итерации.