JdbcTemplate queryForInt / Long, Spring 3.2.2'de kullanımdan kaldırıldı. Ne ile değiştirilmelidir?


104

JdbcTemplate içindeki queryforInt / queryforLong yöntemleri, Spring 3.2'de kullanımdan kaldırılmıştır. Bu yöntemleri kullanarak mevcut kodu değiştirmenin neden veya neyin en iyi uygulama olarak kabul edildiğini bulamıyorum.

Tipik bir yöntem:

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

Tamam, yukarıdaki yöntemin aşağıdaki gibi yeniden yazılması gerekiyor:

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

Açıkçası bu kullanımdan kaldırma JdbcTemplate sınıfını daha basit hale getiriyor (ya da öyle mi?). QueryForInt her zaman kolaylık sağlayan bir yöntemdi (sanırım) ve uzun zamandır var. Neden kaldırıldı. Sonuç olarak kod daha karmaşık hale gelir.


Bu, kullanımdan kaldırılan yöntemleri ayrıntılarıyla anlatıyor
Dan MacBean

Haklısın, kaynağımda neden yok bilmiyorum@Deprecated
Sotirios Delimanolis

İlkbahar sürümü 3.2.2 olarak güncellendi - görünüşe göre ilk olarak burada kullanımdan kaldırılıyor
Dan MacBean

Mevcut kod tabanını 3.1'den 3.2.2'ye yükselttim ve bu yöntemler her yerde kullanılıyor. Kodun neden ve nasıl güncelleneceğini anlamanız gerekiyor.
Dan MacBean

QueryForObject'in dönebileceğini unutmayın null(örneğinizdeki durum değil). Artık queryForInt / Long'dan boş kontrol kodunu çoğaltmaktan başka bir yol bulamadım.
hochraldo

Yanıtlar:


110

Bence biri, queryForInt / Long yöntemlerinin kafa karıştırıcı anlambilimlere sahip olduğunu fark etti, yani JdbcTemplate kaynak kodundan mevcut uygulamasını görebilirsiniz:

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

Bu, sonuç kümesi boşsa 0 döneceğini düşünmenize neden olabilir, ancak bir istisna atar:

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

bu nedenle aşağıdaki uygulama esasen mevcut uygulamaya eşdeğerdir:

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

Ve sonra artık kullanımdan kaldırılmamış kod, çirkin ile değiştirilmelidir:

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

veya bu (daha güzel):

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

12
Bu doğru değil. Üçüncü kod parçacığı, uygulamaya eşit DEĞİLDİR! Çünkü otomatik kutudan çıkarma ile gizli bir NPE var. Sorgunuz sonuç döndürdüyse, ancak bunlar boşsa, önceki kod null yerine 0 döndürür - önceki davranışı düzgün şekilde yeniden üretmek için şu olur: Tamsayı sonuç = queryForObject (sql, args, Integer.class); dönüş sonucu == null? 0: sonuç;
MetroidFan2002

@ MetroidFan2002: Gerçekten de gözleminiz doğru! Bununla birlikte, API tasarımının bakış açısından, eğer sorgu sadece bir NULL değeri döndürürse, (queryForInt do gibi) bir NULL'un 0'a eşit olduğunu varsaymak yerine, onu olduğu gibi döndürmenin daha iyi olduğuna inanıyorum. Bu tür koşulları değerlendirmek için API kullanıcısının
Gabriel Belingueres

Sorun, bir kullanıcı orada bir NPE alırsa ve aldığında, ortamlarında belirli şeyleri açıkça ayarlamadıkça (örneğin, Eclipse'in otomatik kutulama kullanımlarını vurgulama seçeneği vardır), bu satırdaki NPE'nin JDBCOperations örneği gibi görünmesidir. boş. Önceden sıfır döndürülürdü. Şimdi neden bunu null döndüren bir sorguda kullanacağın, hiçbir fikrim yok (bu temelde bunu yapan n00bs'den kaynaklanıyor, ki yapacaklar), ama bunları elimden almak harika bir hareket değil IMO.
MetroidFan2002

Yanlışlık yüzünden olası bir sebep buldum. Sorgu ForLong (String) tarafından döndürülen 10000000233174211 uzun bir değerim vardı, ancak bunun yerine 10000000233174212 döndürüyordu. Yani +1. Koda baktım ve bir Double'ı Long'a dönüştürüyor, bu yüzden belki de dönüşümle ilgili bir sorun var.
mrswadge

Yukarıdaki yorumumu biraz daha düşünürsek, sütunun veri türü sayı (19,0) idi, bu yüzden belki de bu yüzden double devreye girdi? Yine de queryForObject (sql, Long.class) kullanarak sorunu çözdüm.
mrswadge

35

Sorgu için kolaylık yöntemini (sql) kullanımdan kaldırmanın bir rahatsızlık olduğu konusunda orijinal göndericiye katılıyorum.

Spring 3.1'i kullanarak bir uygulama geliştirdim ve en son Spring sürümüne (3.2.3) güncelledim ve kullanımdan kaldırıldığını fark ettim.

Neyse ki benim için tek satırlık bir değişiklik oldu:

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

olarak değiştirildi

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

Ve birkaç Birim Testi, yukarıdaki değişikliğin işe yaradığını gösteriyor gibi görünüyor.


iyi bir nokta. Parantez olmadan da iyi çalışır. :)
SGB

14

Lehine kullanımdan kaldırıldı queryForObject(String, Class).


13

Bu tür kodu değiştirmek:

long num = jdbcTemplate.queryForLong(sql);

Bu kodla:

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

bu çok tehlikelidir çünkü eğer sütun null değerine sahipse queryForObject null döndürür ve bildiğimiz gibi ilkel türler boş olamaz ve NullPointerException olacaktır. Derleyici sizi bu konuda uyarmadı. Bu hatayı çalışma zamanında öğreneceksiniz. Aynı hata İlkel tür döndüren bir yönteminiz varsa elde edersiniz:

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

Spring 3.2.2'deki JdbcTemplate içindeki kullanımdan kaldırılmış sorguForLong yöntemi aşağıdaki gövdeye sahiptir:

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

İlkel değeri döndürmeden önce bunun boş olmadığının kontrol edildiğini ve boşsa 0 döndürdüğünü görürsünüz. Bu arada - 0L olmalı.


3
2 sent: Otomatik kutulama uyarısını etkinleştirdiyseniz, derleyici sizi bu konuda uyarabilir.
keiki

Bunu bilmiyordum. Teşekkürler dostum :)
Marcin Kapusta

2

JdbcTemplate#queryForIntsütun değeri SQL NULL veya 0 ise 0 döndürür. Bir durumu diğerinden ayırt etmenin bir yolu yoktur. Sanırım yöntemin kullanımdan kaldırılmasının ana nedeni budur. BTW, ResultSet#getIntbenzer şekilde davranır. Yine de, bu iki durumu şu şekilde ayırt edebiliriz 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;
}

Lütfen cevabınızı açıklayınız.
Sert Wardhan 05
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.