Spring'in JDBCTemplate ile etkili bir şekilde IN () SQL sorguları yürütmek nasıl?


177

Spring'in JDBCTemplate ile IN () sorguları yapmanın daha zarif bir yolu olup olmadığını merak ediyordum. Şu anda böyle bir şey yapıyorum:

StringBuilder jobTypeInClauseBuilder = new StringBuilder();
for(int i = 0; i < jobTypes.length; i++) {
    Type jobType = jobTypes[i];

    if(i != 0) {
        jobTypeInClauseBuilder.append(',');
    }

    jobTypeInClauseBuilder.append(jobType.convert());
}

IN () sorgusu için yan tümce oluşturmak için dokuz satır varsa, oldukça acı verici. Hazırlanan ifadelerin parametre ikamesi gibi bir şey istiyorum

Yanıtlar:


275

Bir parametre kaynağı istiyorsunuz:

Set<Integer> ids = ...;

MapSqlParameterSource parameters = new MapSqlParameterSource();
parameters.addValue("ids", ids);

List<Foo> foo = getJdbcTemplate().query("SELECT * FROM foo WHERE a IN (:ids)",
     parameters, getRowMapper());

Bu yalnızca getJdbcTemplate()türün bir örneğini döndürürse çalışırNamedParameterJdbcTemplate


5
Mükemmel, NamedParameterJdbcTemplate tam olarak aradığım şeydi. Ayrıca tüm bu soru işaretleri daha adlandırılmış parametreleri seviyorum. Çok teşekkürler!
Malax

5
Bu, küçük listeler için çalışır, ancak büyük bir listede kullanmaya çalışmak şu sorguda sonuçlanır: kimlikleri "?,?,?,?,? ......" ile değiştirilir ve taşan yeterli liste öğeleriyle. Büyük listeler için çalışan bir çözüm var mı?
nsayer

Muhtemelen değerleri geçici bir tabloya eklemeli ve kullanarak durumu oluşturmalısınız WHERE NOT EXISTS (SELECT ...).
Esneme


9
garip, bunu denediğimde "hata kodu [17004]; Geçersiz sütun türü" alıyorum.
Trevor

61

Bunun gibi bahar jdbc ile "yan tümce" sorgusu yapmak:

String sql = "SELECT bg.goodsid FROM beiker_goods bg WHERE bg.goodsid IN (:goodsid)";

List ids = Arrays.asList(new Integer[]{12496,12497,12498,12499});
Map<String, List> paramMap = Collections.singletonMap("goodsid", ids);
NamedParameterJdbcTemplate template = 
    new NamedParameterJdbcTemplate(getJdbcTemplate().getDataSource());

List<Long> list = template.queryForList(sql, paramMap, Long.class);

10
Neredeyse üç yıllık bir soruya, kabul edilen cevabın verdiği aynı çözümle bir cevap gönderdiniz. Bunun arkasında iyi bir neden var mı? :-)
Malax

16
Bu yanıt, bu API için NamedParameterJdbcTemplate'in gerekli olduğunu gösterdiği için daha fazla netlik sağlar ... bu nedenle ek ayrıntı için teşekkürler janwen
IcedDante

@janwen, çözüm için teşekkürler !!! Benim şartının gibi iyi çalışıyor !!
Karthik Amarnath Saakre

19

Şunun için bir istisna alırsanız: Geçersiz sütun türü

Lütfen getNamedParameterJdbcTemplate()yerine kullanıngetJdbcTemplate()

 List<Foo> foo = getNamedParameterJdbcTemplate().query("SELECT * FROM foo WHERE a IN (:ids)",parameters,
 getRowMapper());

İkinci iki argümanın değiştirildiğini unutmayın.


2
Bu, bu sorunun cevabı gibi görünmüyor. Başka bir cevaba bir yorum olmalı mı?
Dave Schweisguth

2
@DaveSchweisguth İki yıl sonra, kesinlikle bir cevap olması gerekiyor.
dwjohnston

2

Buraya bakın

adlandırılmış parametre ile sorgu yazma ListPreparedStatementSetter, sırayla tüm parametreleri ile basit kullanın . Sorguyu mevcut parametrelere göre geleneksel biçimde dönüştürmek için aşağıdaki snippet'i eklemeniz yeterlidir,

ParsedSql parsedSql = NamedParameterUtils.parseSqlStatement(namedSql);

List<Integer> parameters = new ArrayList<Integer>();
for (A a : paramBeans)
    parameters.add(a.getId());

MapSqlParameterSource parameterSource = new MapSqlParameterSource();
parameterSource.addValue("placeholder1", parameters);
// create SQL with ?'s
String sql = NamedParameterUtils.substituteNamedParameters(parsedSql, parameterSource);     
return sql;

benim için sadece birkaç yer tutucu kurmak istediğim gibi çalışan tek cevap
buydu

-4

2009'dan beri çok şey değişti, ancak sadece NamedParametersJDBCTemplate'i kullanmanız gerektiğini söyleyen cevaplar bulabilirim.

Benim için sadece bir

db.query(sql, new MyRowMapper(), StringUtils.join(listeParamsForInClause, ","));

SimpleJDBCTemplate veya JDBCTemplate kullanarak


11
Bu çözümün sorunu, içeriğin listeParamsForInClausekaçmaması ve SQL enjeksiyonuna karşı savunmasız kalmasıdır.
Malax
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.