2013-02-27 28 views
15

Tôi đang nghiên cứu cách thực hiện truy vấn trên cơ sở dữ liệu bằng JDBC trong Spring Framework.Một số nghi ngờ về việc sử dụng RowMapper trong JDBC trong ứng dụng Khung công tác

Tôi làm theo hướng dẫn này: http://www.tutorialspoint.com/spring/spring_jdbc_example.htm

Trong hướng dẫn này, tôi định nghĩa một giao diệnStudentDAO mà chỉ xác định các phương pháp CRUD mà tôi muốn.

Sau đó, được xác định là lớp học Sinh viên là thực thể mà tôi muốn lưu giữ trên bảng cơ sở dữ liệu Sinh viên.

Sau đó được định nghĩa lớp StudentMapper đó là một thực hiện cụ thể của giao diện RowMapper rằng, trong trường hợp này, được sử dụng để ánh xạ một bản ghi cụ thể trong ResultSet (được trả về bởi một truy vấn) cho một sinh viên đối tượng.

Sau đó, tôi có StudentJDBCTemplate rằng rappresent việc thực hiện các giao diện của tôi StudentDAO, trong lớp này tôi thực hiện phương pháp CRUD mà được định nghĩa trong giao diện.

Ok, và bây giờ tôi có một nghi ngờ về cách thức StudentMapper lớp làm việc: trong StudentJDBCTemplate lớp này có được định nghĩa phương thức trả lại danh sách của tất cả các kỷ lục mà trong bảng cơ sở dữ liệu sinh viên, chương trình này:

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

làm thế nào bạn có thể thấy, phương pháp này trả về một Danh sách các đối tượng sinh viên và làm việc theo cách sau:

điều đầu tiên mà nó làm là xác định các truy vấn mà trả lại tất cả kỷ lục trong St bảng cơ sở dữ liệu udent trong chuỗi SQL.

Sau đó truy vấn này được thực hiện bởi các cuộc gọi phương thức truy vấn trên đối tượng jdbcTemplateObject (có nghĩa là một istance của JdbcTemplate lớp Xuân **

Phương pháp này có hai tham số: String SQL (có chứa các truy vấn SQL phải được thực hiện) và một StudentMapper đối tượng mới mà lấy ResultSet đối tượng được trả về bởi các truy vấn và lập bản đồ đó là kỷ lục trên một đối tượng sinh viên mới

Đọc ở đây: http://static.springsource.org/spring/docs/current/javadoc-api/org/springframework/jdbc/core/JdbcTemplate.html sayas rằng: Ex tạo một truy vấn cho SQL tĩnh, ánh xạ mỗi hàng tới một đối tượng Java thông qua một RowMapper.

Nghi ngờ của tôi có liên quan đến thực tế là tôi StudentMapper ánh xạ một kỷ lục ResultSet trên một đối tượng sinh viên sử dụng mapRow() phương pháp, đây là đoạn 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; 
    } 
} 

Vì vậy, người gọi phương thức mapRow này? nó có được gọi tự động bởi Spring Framework không? (bởi vì trong ví dụ này không bao giờ được gọi là thủ công ...)

Tnx

Andrea

Sau đó truy vấn này được thực hiện bởi các cuộc gọi phương thức truy vấn trên đối tượng jdbcTemplateObject (có nghĩa là một istance của JdbcTemplate lớp Xuân **

Trả lời

22

Khi bạn vượt qua một thể hiện của RowMapper của bạn vào JdbcTemplate phương pháp

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

Các JdbcTemplate tùy thuộc vào cách mà bạn gọi, sẽ nội bộ sử dụng ánh xạ với kết quả thiết lập nó nhận được từ các JDBC Kết nối để tạo một đối tượng thuộc loại bạn yêu cầu. Ví dụ, kể từ khi bạn gọi JdbcTemplate#query(String, RowMapper), phương pháp này sẽ sử dụng chuỗi SQL của bạn để truy vấn cơ sở dữ liệu và ý chí lặp qua mỗi "hàng" trong ResultSet loại như thế này:

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; 

Vì vậy, Spring 's JdbcTemplate phương pháp sẽ sử dụng số RowMapper bạn cung cấp và gọi phương thức mapRow để tạo đối tượng trả về dự kiến.

Bạn có thể muốn xem số Data Mapper của Martin Fowler kết hợp với Table Data Gateway để biết cách phân phối và cung cấp những thứ này low coupling.

1

Vì vậy, người gọi phương thức mapRow này là nó được gọi tự động bởi khung công tác Spring ? (bởi vì trong ví dụ này không bao giờ được gọi là theo cách thủ công ...)

Điều này được tự động gọi là khung lò xo. Tất cả bạn cần là để xác định

  1. thông số kết nối,
  2. câu lệnh SQL
  3. thông số Declare và cung cấp tham số giá trị
  4. làm việc cho mỗi lần lặp.
4

Đây là mẫu điển hình tôi sử dụng với BeanPropertyRowMapper. Nó tiết kiệm rất nhiều mã hóa. Truy vấn của bạn cần phải bí danh từng cột để khớp với tên thuộc tính trong lớp. Trong trường hợp này, species_name as species và các tên cột khác đã khớp với nhau.

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

Một cách khác là sử dụng một RowMapper (ví dụ này chỉ sử dụng một lớp vô danh) khi bạn cần tùy biến hơn mỗi hàng:

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

Sử dụng RowMapper trong mùa xuân

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()); 
} 
Các vấn đề liên quan