当前位置: 首页 > 知识库问答 >
问题:

关于Spring框架应用程序中JDBC中使用RowMapper的一些疑问

卢光远
2023-03-14

我正在研究如何在Spring框架中使用JDBC在数据库上执行查询。

我遵循这个教程:http://www.tutorialspoint.com/spring/spring_jdbc_example.htm

在本教程中,我定义了一个StudentDAO接口,它只定义我想要的CRUD方法。

然后定义了Student类,它是我希望在Student数据库表中持久化的实体。

然后,定义了作为RowMapper接口的特定实现(在本例中,用于将ResultSet(通过查询返回)中的特定记录映射到学生对象)的StuentMapper类。

然后我有了StudentJDBCTemplate,它展示了StudentDAO接口的实现,在这个类中我实现了接口中定义的CRUD方法。

好的,现在我对StudentMapper类的工作方式有一个疑问:在这个StudentJDBCTemplate类中定义了一个方法,该方法返回Student数据库表中所有记录的列表,这个:

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

您可以看到,此方法返回一个List of学生对象,并按以下方式工作:

它要做的第一件事是定义返回SQL字符串中学生数据库表中所有记录的查询。

然后通过对jdbcTemplateObject对象的查询方法调用执行此查询(即JdbcTemplateObject Spring类的一个实例**

此方法有两个参数:SQL字符串(包含必须执行的SQL查询)和一个新的StudentMapper对象,该对象获取查询返回的ResultSet对象,并将其记录映射到新的Student对象上

阅读这里:http://static.springsource.org/spring/docs/current/javadoc-api/org/springframework/jdbc/core/JdbcTemplate.html说:执行给定静态SQL的查询,通过RowMapper将每行映射到Java对象。

我的疑问与以下事实有关:我的StudentMapper使用mapRow()方法将ResultSet记录映射到Student对象上,代码如下:

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框架自动调用的吗?(因为在本例中从未手动调用…)

tnx

安德莉亚

然后通过对jdbcTemplateObject对象的查询方法调用执行此查询(即JdbcTemplateObject Spring类的一个实例**

共有3个答案

澹台华翰
2023-03-14

在Spring中使用RowMapper

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());
}
柯唯
2023-03-14

下面是我使用BeanPropertyRowMapper的典型模式。它节省了大量的编码。查询需要为每个列添加别名,以匹配类中的属性名称。在本例中,species\u名称为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;
        }
    });
闻人锦
2023-03-14

RowMapper的实例传递给JdbcTemplate方法时

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

JdbcTemplate根据您调用的方法,将在内部使用映射器及其从JDBC连接获得的结果集来创建所请求类型的对象。例如,由于您调用了JdbcTemplate#query(String,RowMapper),因此该方法将使用字符串SQL查询数据库,并将循环遍历结果集中的每一行,如下所示:

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;

因此,SpringJdbcTemplate方法将使用您提供的RowMapper并调用其mapRow方法来创建预期的返回对象。

您可能希望将Martin Fowler的Data Mapper与Table Data Gateway结合起来,了解这些东西是如何分布和提供低耦合的。

 类似资料:
  • 我正在学习如何在Spring应用程序中使用JDBC,但我对此有些怀疑。 因此,让我解释一下我对一个实际例子的怀疑: 如果我有一个实现我的DAO接口的类,并且这个类包含以下方法,在我的数据库的学生表中插入一个新行: 好的...我认为SQL字符串Rapper呈现了我的SQL查询,必须执行这些查询才能在我的表中插入新行 我不明白这段代码到底是什么意思:值(?,?) 我认为,当我在JdbcTemplate

  • 我是Spring框架的新手,我对@Autow的注释和接口声明的使用有一些问题。 参考此示例: http://viralpatel.net/blogs/spring3-mvc-hibernate-maven-tutorial-eclipse-example/ 我知道@Autow的注释可用于自动链接属性上的bean。 在上一个示例中,我遇到了以下情况: 我有一个ContactDAO接口,它的实现类名为

  • 1)第一个疑问与这样一个事实有关:在这个类中,对于每个CRUD方法,我都打开一个新的会话。 我之所以这样做是因为在本教程http://www.tutorialspoint.com/hibernate/hibernate_sessions.htm中我读到: Session对象是轻量级的,设计成每次需要与数据库交互时都要实例化。持久性对象通过会话对象保存和检索。会话对象不应该保持长时间打开,因为它们通

  • 问题是关于RowMapper在主/细节场景中的最佳实践用法,我们希望使用Spring jdbc急切地获取细节。 假设我们有Invoice和InvoiceLine类。 当将Spring Jdbc与行映射器一起使用时,我们通常有 现在的问题是我想急切地获取与此发票实例相关的InvoiceLine。如果我在rowmapper类中查询数据库可以吗?或者有人喜欢另一种方式?我使用下面的模式,但对此不满意。

  • 问题内容: 我有一个用Swift编写的应用程序(简称MyApp),其目标如下: :主要目标 :一个目标,用于为应用及其扩展程序(主要是API后端和数据库处理)之间共享的代码构建框架 :使用框架的Today View小部件(或现在称为的小部件)。 该框架链接到使用它的每个目标,即和。输入Cocoapods:我以前具有以下Podfile结构: 这里的目的是仅将框架公开给其他部分,而不是将其所有pod

  • 在典型的Spring MVC项目中,有两个“容器”:一个由ContextLoaderListener创建,另一个由DispatchServlet创建。 我想知道,这真的是两个IoC容器实例吗?(我看到两个bean配置文件,一个是,另一个是) 如果有2个容器,那么有什么关系? 在一个容器中声明的bean可以在另一个容器中使用吗?