有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

JDBCTemplate的java PreparedStatement在“结果集开始之前”引发异常

我正在使用Spring JdbcTemplate。我需要通过ID查询数据。 我有一个表格模式:

+---------------+--------------+------+-----+---------+-------+
| Field         | Type         | Null | Key | Default | Extra |
+---------------+--------------+------+-----+---------+-------+
| id            | varchar(150) | NO   | PRI | NULL    |       |
| position_name | varchar(150) | NO   |     | NULL    |       |
| description   | text         | YES  |     | NULL    |       |
+---------------+--------------+------+-----+---------+-------+

我使用这个模板运行:

public Position fetchById(final String id) throws Exception {
    // TODO Auto-generated method stub
    String sql = "SELECT * FROM position WHERE id = ?";

    return jdbcTemplate.query(sql, new PreparedStatementSetter() {
        public void setValues(PreparedStatement ps) throws SQLException {
            // TODO Auto-generated method stub
            ps.setString(1, id);
        }
    }, new ResultSetExtractor<Position>() {

        public Position extractData(ResultSet rs) throws SQLException,
                DataAccessException {
            // TODO Auto-generated method stub
            Position p = new Position();
            p.setId(rs.getString("id"));
            p.setPositionName(rs.getString("position_name"));
            p.setDescription(rs.getString("description"));

            return p;
        }
    });
}

但当我像这样运行单元测试时:

@Test
public void getPositionByIdTest() throws Exception {
    String id = "35910510-ef2f-11e5-9ce9-5e5517507c66";
    Position p = positionService.getPositionById(id);

    Assert.assertNotNull(p);
    Assert.assertEquals("Project Manager", p.getPositionName());
}

我发现以下错误:

org.springframework.dao.TransientDataAccessResourceException: PreparedStatementCallback; SQL [SELECT * FROM position WHERE id = ?]; Before start of result set; nested exception is java.sql.SQLException: Before start of result set
    at org.springframework.jdbc.support.SQLStateSQLExceptionTranslator.doTranslate(SQLStateSQLExceptionTranslator.java:108)
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:73)
    ...
Caused by: java.sql.SQLException: Before start of result set
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:957)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:896)
    ...

如何在Select查询JDBC模板中使用PreparedStatement? 谢谢


共 (2) 个答案

  1. # 1 楼答案

    如果使用ResultSetExtractor,则必须迭代使用next()调用的结果。这就解释了这个错误,因为在读取其值时,ResultSet仍然位于第一行之前

    对于您的用例(为给定id选择记录),有一个更简单的解决方案,使用JdbcTemplate.queryForObjectRowMapperlambda:

    String sql = "SELECT * FROM position WHERE id = ?";
    Position position = (Position) jdbcTemplate.queryForObject(
        sql, new Object[] { id }, (ResultSet rs, int rowNum)  -> {
            Position p = new Position();
            p.setId(rs.getString("id"));
            p.setPositionName(rs.getString("position_name"));
            p.setDescription(rs.getString("description"));
           r eturn p;
        });
    
  2. # 2 楼答案

    您有一个简单的用例,并使用一种更复杂的查询方法,为什么?接下来,您将使用ResultSetExtractor,而您可能希望使用RowMapper。如果使用ResultSetExtractor,则必须自己迭代结果集。用以下代码替换代码

    return getJdbcTemplate.query(sql, new RowMapper<Position>() {
        public Position mapRow(ResultSet rs, int row) throws SQLException,
                DataAccessException {
            Position p = new Position();
            p.setId(rs.getString("id"));
            p.setPositionName(rs.getString("position_name"));
            p.setDescription(rs.getString("description"));
    
            return p;
        }, id);
    } 
    

    因此,不要使用complexer方法,而是使用适合您需要的方法。不管怎样,JdbcTemplate使用PreparedStatement