Ответ 1
Вы должны использовать # {name} вместо ${name}.
В приведенном ниже примере будет создан действительный SQL
<mapper namespace="sql1">
<select id="select1" parameterType="map" resultType="String" >
SELECT * FROM USERS
WHERE
name LIKE #{name} AND num = #{number}
</select>
</mapper>
MyBatis напрямую копирует и вставляет строковый параметр, если вы используете $character. С другой стороны, он использует привязку параметров, если вы используете символ #.
Затем вы должны выполнить свой sql, используя selectMap, selectList или selectOne,
List<String> resultSet = sessionFactory.openSession().selectList("sql1.select1", pars);
Этот вызов автоматически привяжет параметры к оператору и выполнит его.
Внимание:
<select id="select1" parameterType="map" resultType="String" >
SELECT * FROM USERS
WHERE
name LIKE #{name} AND num = #{number}
</select>
может не выполняться, так как MyBatis не может сопоставить несколько столбцов (SELECT *) с одной строкой ( resultType = "String" ) показаны две возможные поправки к запросу ниже:
<!--Solution One-->
<select id="select1" parameterType="map" resultType="String" >
SELECT name FROM USERS
WHERE
name LIKE #{name} AND num = #{number}
</select>
<!--Solution Two-->
<select id="select1" parameterType="map" resultType="java.util.LinkedHashMap" >
SELECT * FROM USERS
WHERE
name LIKE #{name} AND num = #{number}
</select>
Для решения два вы должны выполнить mybatis-запрос, используя код java ниже:
List<Map<?, ?>> resultSet = sessionFactory.openSession().selectList("sql1.select1", pars);
Подробности о том, почему getBoundSql возвращает запрос с?:
Связывание параметров выполняется на уровне драйвера, поэтому вы не получите строку sql, подобную этой
SELECT * FROM USERS
WHERE
name LIKE 'john' AND num = 12345
Вместо этого вы получите шаблон запроса sql, который готов к привязке параметров,
SELECT * FROM USERS
WHERE
name LIKE ? AND num = ?
Добавление параметров в строку sql позволяет sql injection. Безопасный способ - использовать метод привязки параметров, предоставляемый с помощью SQL Driver, и MyBatis всегда использует привязку параметров.
Предположим, что вы вручную создали свою команду sql в виде строки и предположите, что я пользователь malicius пытается получить доступ к вашим данным. Я могу написать
john' or ''='
Итак, это создаст команду sql ниже:
SELECT * FROM USERS
WHERE
name LIKE 'john' or ''='' AND num = 12345
Дополнительные преимущества привязки параметров
Вторым преимуществом привязки параметров является то, что он позволяет создавать подготовленные операторы. Предположим, что вам нужно выполнить один и тот же sql 1000 раз с разными параметрами.
Если вы создаете строки sql с привязанными параметрами,
SELECT * FROM USERS WHERE name LIKE 'john' AND num = 12345;
SELECT * FROM USERS WHERE name LIKE 'foo' AND num = 67890;
Сервер базы данных должен будет каждый раз анализировать каждую команду sql, а затем выполнять их.
С параметризованными sql-запросами
SELECT * FROM USERS WHERE name LIKE ? AND num = ?
SQL-драйвер кэширует запрос, поэтому синтаксический анализ выполняется только один раз, а затем он связывает разные параметры с той же самой командой SQL.
Обновление: использование BoundSql вне MyBatis
Вы все равно можете использовать параметризованный sql (boundSql) с другой библиотекой или Java java.sql.Connection. Ниже приведен пример:
Connection myConnection;
PreparedStatement preparedStatement = myConnection.prepareStatement(boundSql);
preparedStatement.setString(1, "john"); //First parameter starts with 1 not 0!
preparedStatement.setInt(2, 12345);
ResultSet results = preparedStatement.executeQuery();