JdbcTemplate queryForInt / Long은 Spring 3.2.2에서 더 이상 사용되지 않습니다. 무엇으로 교체해야합니까?


104

JdbcTemplate의 queryforInt / queryforLong 메소드는 Spring 3.2에서 더 이상 사용되지 않습니다. 이러한 방법을 사용하여 기존 코드를 대체하는 가장 좋은 방법이 무엇인지 이유를 알 수 없습니다.

일반적인 방법 :

int rowCount = jscoreJdbcTemplate.queryForInt(
    "SELECT count(*) FROM _player WHERE nameKey = ? AND teamClub = ?",
    playerNameKey.toUpperCase(),
    teamNameKey.toUpperCase()
);

위의 방법을 다음과 같이 다시 작성해야합니다.

Object[] params = new Object[] { 
   playerNameKey.toUpperCase(), 
   teamNameKey.toUpperCase()
};
int rowCount = jscoreJdbcTemplate.queryForObject(
    "SELECT count(*) FROM _player WHERE nameKey = ? AND teamClub = ?",
    params, Integer.class);

분명히이 폐기는 JdbcTemplate 클래스를 더 단순하게 만듭니다 (또는 그렇게합니까?). QueryForInt는 항상 편리한 방법이었고 (내 생각에) 오랫동안 사용되었습니다. 제거 된 이유. 결과적으로 코드가 더 복잡해집니다.


더 이상 사용되지 않는 메소드 세부 정보 : static.springsource.org/spring/docs/current/javadoc-api/…
Dan

내 소스가없는 이유는 당신이 바로, 나도 몰라 야@Deprecated
소티 리오스 Delimanolis

Spring 버전을 3.2.2로 업데이트했습니다. 여기에서 처음 사용이 중단 된 것 같습니다
Dan MacBean

기존 코드베이스를 3.1에서 3.2.2로 업그레이드했으며 이러한 방법은 모든 곳에서 사용됩니다. 코드를 업데이트하는 이유와 방법을 이해해야합니다.
Dan MacBean 2013 년

queryForObject가 반환 될 수 있습니다 null(귀하의 예에서는 해당되지 않음). 이제 queryForInt / Long의 null 확인 코드를 복제하는 것 외에 다른 방법을 찾지 못했습니다.
hochraldo 2013

답변:


110

내가 생각하는 것은 누군가 queryForInt / Long 메소드가 혼란스러운 의미를 가지고 있다는 것을 깨달았다는 것입니다. 즉, JdbcTemplate 소스 코드에서 현재 구현을 볼 수 있습니다.

@Deprecated
public int queryForInt(String sql, Object... args) throws DataAccessException {
    Number number = queryForObject(sql, args, Integer.class);
    return (number != null ? number.intValue() : 0);
}

결과 집합이 비어 있으면 0을 반환하지만 예외가 발생한다고 생각할 수 있습니다.

org.springframework.dao.EmptyResultDataAccessException: Incorrect result size: expected 1, actual 0

따라서 다음 구현은 본질적으로 현재 구현과 동일합니다.

@Deprecated
public int queryForInt(String sql, Object... args) throws DataAccessException {
    return queryForObject(sql, args, Integer.class);
}

그리고 이제 더 이상 사용되지 않는 코드를 추악한 코드로 바꿔야합니다.

    queryForObject(sql, new Object { arg1, arg2, ...}, Integer.class);

또는이 (더 좋은) :

    queryForObject(sql, Integer.class, arg1, arg2, ...);

12
사실이 아닙니다. 세 번째 코드 조각은 구현과 동일하지 않습니다! 자동 개봉 기능이있는 숨겨진 NPE가 있기 때문입니다. 쿼리가 결과를 반환했지만 null 인 경우 이전 코드는 null 대신 0을 반환합니다. 이전 동작을 제대로 재현하려면 다음과 같습니다. Integer result = queryForObject (sql, args, Integer.class); 반환 결과 == null? 0 : 결과;
MetroidFan2002 2013

@ MetroidFan2002 : 사실 당신의 관찰은 사실입니다! 그러나 API 디자인의 관점에서 쿼리가 하나의 NULL 값만 반환하는 경우 NULL이 0과 같다고 가정하는 대신 (queryForInt가 수행하는 것처럼) 그대로 반환하는 것이 좋습니다. 이러한 종류의 조건을 평가하기 위해 API 사용자의
Gabriel Belingueres 2013

문제는 사용자가 NPE를 얻었을 때 환경에서 특정 사항을 명시 적으로 설정하지 않는 한 (예 : Eclipse에는 오토 박싱 사용을 강조하는 옵션이 있음) 해당 줄의 NPE가 JDBCOperations 인스턴스처럼 보입니다. null입니다. 이전에는 0이 반환되었습니다. 이제 null을 반환하는 쿼리에서 이것을 사용하는 이유는 모르겠지만 (기본적으로 n00bs가이를 수행하기 때문입니다), 이러한 기능을 제거하는 것은 IMO에서 큰 영향을 미치지 않습니다.
MetroidFan2002

가능한 이유는 부정확하기 때문입니다. queryForLong (String)에 의해 10000000233174211의 long 값이 반환되었지만 대신 10000000233174212를 반환했습니다. 즉 +1. 코드를 살펴본 결과 Double을 Long으로 변환하므로 변환에 문제가있을 수 있습니다.
mrswadge

위의 의견에 대해 조금 더 생각해 보면 열의 데이터 유형은 number (19,0) 였으므로 이중이 사용 된 이유일까요? 어쨌든 queryForObject (sql, Long.class)를 사용하여 문제를 해결했습니다.
mrswadge 2015 년

35

편의 메소드 queryForLong (sql)을 사용하지 않는 것이 불편하다는 원래 포스터에 동의합니다.

저는 Spring 3.1을 사용하여 앱을 개발했고 방금 최신 Spring 버전 (3.2.3)으로 업데이트했으며 더 이상 사용되지 않는 것으로 나타났습니다.

다행히도 한 줄 변경되었습니다.

return jdbcTemplate.queryForLong(sql);  // deprecated in Spring 3.2.x

변경되었습니다

return jdbcTemplate.queryForObject(sql, Long.class);

그리고 두 개의 단위 테스트는 위의 변경 사항이 작동 함을 나타내는 것 같습니다.


좋은 지적. 괄호 없이도 잘 작동합니다. :)
SGB

14

대신 사용되지 않습니다 queryForObject(String, Class).


13

이러한 코드 교체 :

long num = jdbcTemplate.queryForLong(sql);

이 코드로 :

long num = jdbcTemplate.queryForObject(sql, Long.class);

열에 null 값이 있으면 queryForObject가 null을 반환하고 기본 유형은 null이 될 수 없으며 NullPointerException이 발생하기 때문에 매우 위험합니다. 컴파일러는 이것에 대해 경고하지 않았습니다. 런타임시이 오류에 대해 알게됩니다. 기본 유형을 반환하는 메서드가있는 경우에도 동일한 오류가 발생합니다.

public long getValue(String sql) {
    return = jdbcTemplate.queryForObject(sql, Long.class);
}

Spring 3.2.2의 JdbcTemplate에서 더 이상 사용되지 않는 메소드 queryForLong은 다음 본문을 갖습니다.

@Deprecated
public long queryForLong(String sql) throws DataAccessException {
    Number number = queryForObject(sql, Long.class);
    return (number != null ? number.longValue() : 0);
}

프리미티브 값을 반환하기 전에 이것이 null이 아닌지 확인하고 null이면 0을 반환합니다. 그런데-0L이어야합니다.


3
2 센트 : 오토 박싱 경고를 활성화 한 경우 컴파일러에서 경고 할 수 있습니다.
keiki

나는 그것에 대해 몰랐다. 감사 메이트 :
마르신 Kapusta

2

JdbcTemplate#queryForInt열 값이 SQL NULL 또는 0이면 0을 반환합니다. 한 대소 문자를 구별 할 방법이 없습니다. 이것이 방법이 더 이상 사용되지 않는 주된 이유라고 생각합니다. BTW는 ResultSet#getInt비슷하게 작동합니다. 그러나 우리는 ResultSet#wasNull.


-1
public int getCircleCount() {
    Object param = "1";
    String sql = "select count(*) from circle where id = ? ";
    jdbcTemplate.setDataSource(getDataSource());
    int result = getJdbcTemplate().queryForObject(sql, new Object[] { param }, Integer.class);
    return result;
}

당신의 대답을 설명하십시오.
거친 Wardhan
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.