Как искать строку LIKE 'something%' с помощью Java Spring Framework?

У меня есть таблица MySQL с Foos. Каждый Foo имеет числовой неуникальный код и имя. Теперь мне нужно найти, есть ли у какого-либо Foo с одним из определенных кодов имя, начинающееся с заданной строки. В обычном SQL это было бы тривиально:

select * from FOO where CODE in (2,3,5) and NAME like 'bar%';

Но как мне правильно сделать это весной сейчас? Без необходимости оператора «нравится» я бы сделал это так:

public List<Foo> getByName(List<Integer> codes, String namePart) {
    String sql = "select * from FOO where CODE in (:codes) and NAME=:name"
    Map<String,Object> params = new HashMap<String,Object>();
    params.put("codes", codes);
    params.put("name", namePart);
    return getSimpleJdbcTemplate().query(sql, new FooRowMapper(), params);
}

Однако с «нравится» ничего не работает: NAME like :name%, NAME like ':name%' или NAME like ?% при использовании заполнителей вместо именованных параметров.

Я мог бы быть жестоким и ввести его как

String sql = "select * from FOO where CODE in (:codes) and NAME like '"+namePart+"%'";` 

но, очевидно, было бы более чем приятно, если бы Spring корректно очищал входные параметры и т. д., понимаете...

Вы могли бы подумать, что Spring каким-то образом поддержит это, но я не могу этого понять.


person ZeroOne    schedule 19.06.2012    source источник
comment
у меня это работает, если я использую: выберите * из FOO, где КОД в (: коды) и ИМЯ, например +namePart+ '%';   -  person Navrattan Yadav    schedule 20.01.2017


Ответы (3)


Подождите, конечно, мне пришлось «попробовать еще одну последнюю вещь», прежде чем закончить день, и о чудо, все мои модульные тесты внезапно проходят:

public List<Foo> getByName(List<Integer> codes, String namePart) {
    String sql = "select * from FOO where CODE in (:codes) and NAME like :name"
    Map<String,Object> params = new HashMap<String,Object>();
    params.put("codes", codes);
    params.put("name", namePart+"%");
    return getSimpleJdbcTemplate().query(sql, new FooRowMapper(), params);
}

Я не думал вводить «%» в параметре, я был уверен, что Spring автоматически избежит его. Интересно, правильно ли я делаю?

person ZeroOne    schedule 19.06.2012
comment
Nerf, это было решение, которое я собирался дать :D Я так и делал здесь, до того, как перешел на MyBatis, но это уже другая история :p - person Olivier Coilland; 19.06.2012
comment
AFAIK Spring ускользает, но только в том, что касается предотвращения SQL-инъекций. В противном случае LIKE ожидает выражение, а % является частью выражения, так что я вижу это более-менее логично. - person Istvan Devai; 19.06.2012
comment
@OlivierCoilland Ха, извините, что украл ваш ответ. ;) Спасибо за подтверждение, по крайней мере, я знаю, что кто-то еще использует эту технику. И спасибо за указатель на MyBatis; Я никогда не слышал об этом раньше, но это выглядит интересно. - person ZeroOne; 19.06.2012
comment
Будет ли Spring экранировать список кодов несколькими вопросительными знаками? Я так не думаю. - person Michael-O; 21.06.2012

Для работы именованных параметров необходимо использовать Шаблон NamedParameterJdbc

params.put("name", "Joe%");

jdbcTemplate.query("select * from FOO where CODE in (:codes) and NAME like :name" 
person Istvan Devai    schedule 19.06.2012

В другой форме я столкнулся с той же проблемой и попытался решить ее следующим образом:

public List<MyEntity> getMyEntityValuesBySearchText(String searchText) {

    String query = "SELECT * FROM MY_ENTITY_TABLE WHERE NAME LIKE ?";
    return this.getJdbcTemplate().query(query, new String[] { "%" + searchText + "%" },
                (rs, rowNum) -> new MyEntity(rs.getLong("PK"), rs.getString("NAME")));
}
person MMKarami    schedule 26.04.2018