предисловие
При использовании Mybatis в разработке часто используются #{} и ${}, и все еще есть много разработчиков, которые не очень хорошо понимают их использование.
Динамический sql является одной из его основных функций в mybatis.После того, как параметры, определенные в mapper, передаются в xml, mybatis будет динамически анализировать их перед выполнением операции. mybatis предоставляет два синтаксиса, которые поддерживают динамический sql: #{} и ${},Самая большая разница заключается в том, что первый метод может в значительной степени предотвратить внедрение SQL (безопасность), а второй метод не может предотвратить внедрение SQL.. Какие? ? Не понимаю, что такое Sql-инъекция? Лоб. . . Внедрение Sql означает, что при анализе программы параметры, которые вы передаете, будут использоваться как часть исходного оператора SQL, нарушая структуру исходного SQL, и обычно нам просто нужно передать один параметр.
Глубокое понимание SQL-инъекций
Какие? Я до сих пор не понимаю SQL-инъекций, поэтому у меня есть QAQ. . . Тогда давайте возьмем самый простой пример: в общей разработке должно быть два поля ввода на переднем плане, одно имя пользователя и один пароль.В фоновом режиме два параметра, переданные передним планом, будут считаны и объединены в кусок SQL, например: выберите count(1) на вкладке, где users=userinput и pass = passinput, после подключения этого SQL к данным посмотрите, существует ли имя пользователя/пароль, если да, вы можете успешно войти в систему, если нет, то Сообщить об ошибке входа в систему. Правильно. Но есть такая ситуация, этот кусок SQL прописан по вводу пользователя.Если пользователь умышленно вводит строку которая может привести к сбою фонового парсинга это SQL инъекции.Например когда пользователь вводит пароль , введите '''' ' или 1=1'', таким образом, когда фоновая программа анализирует, составленный оператор SQL может быть таким: выберите count(1) на вкладке, где user=userinput и pass=' ' или 1 = 1; см. это Вы можете знать, что после синтаксического анализа пользователь не ввел пароль, и было добавлено условие идентификации 1 = 1. Таким образом, при выполнении этого SQL возвращаемое значение счетчика должно быть больше чем 1. Если логика программы не добавляет слишком много суждений, так что вы можете войти в систему с именем пользователя userinput, без необходимости ввода пароля. Чтобы предотвратить внедрение SQL, сначала отфильтруйте одинарные кавычки при вводе пароля, а затем добавьте другие логические суждения или не используйте такое динамическое написание SQL.
о # { }
1. #{} представляет собой символ места, эквивалентный
jdbc
середина?символ #{} реализует установку значений параметров в подготовленном операторе в prepareStatement.#{} в операторе sql представляет собой заполнитель, который есть?
2. #{} обрабатывает входящие данные как строку и добавляет двойные кавычки к автоматически входящим данным. как:
select * from user where id= #{user_id}
, если входящее значение равно 11, то значение при анализе в sql равноwhere id="11"
,
3, если только оператор sql
一个参数
, имя параметра может быть随意定义
Если оператор sql имеетмногиеимя параметра должно быть [имя атрибута класса сущностей] или [ключевое слово коллекции карт], связанное с текущей таблицей,Нельзя писать невзначай, должны соответствовать! Как показано ниже
около $ {}
1, {user_id}
,如果传入的值是11,那么解析成sql时的值为
where id=11`
2,
$ {value}
серединаvalue
Значение ограничено и может быть записано только соответствующее значение, потому что значение не может быть записано случайно, потому что${}
Преобразование типа jdbc не выполняется автоматически.
3. Проще говоря, в
JDBC
Если заполнители не поддерживаются, их можно использовать${}
Разница между #{} и ${} в Mybatis
Просто разница в том,
Метод #{} может в значительной степени предотвратить внедрение SQL (безопасность), а метод ${} не может предотвратить внедрение SQL.
существует
JDBC
Там, где можно использовать заполнители, лучше использовать их в первую очередь.#{}
существует
JDBC
Если использование заполнителей не поддерживается, их можно использовать только${}
, типичный случайДинамические параметры
Например, есть две таблицы, которыеemp_2017
иemp_2018
При необходимости в запросеДинамически укажите имя таблицы, вы можете использовать только ${}
<select>
select * from emp_ ${year}
<select>
Другой пример — MyBatis.используется при сортировкеorder by
Динамические параметры, в настоящее время вы можете использовать только ${}
<select>
select * from dept order by ${name}
</select>
Кодовый регистр
Как правило, #{} и ${} в основном используются в нечетком запросе, так что здесь случай нечеткого запроса
Случаи применения
1. Файл сопоставления
Добавьте следующее в файл конфигурации пользователя .xml:
<!-- 如果返回多个结果,mybatis会自动把返回的结果放在list容器中 -->
<!-- resultType的配置和返回一个结果的配置一样 -->
<select id="queryUserByUsername1" parameterType="string"
resultType="cn.itcast.mybatis.pojo.User">
SELECT * FROM `user` WHERE username LIKE #{username}
</select>
2. Процедура испытаний
Метод тестирования, добавленный в MybatisTest, выглядит следующим образом:
@Test
public void testQueryUserByUsername1() throws Exception {
// 4. 创建SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
// 5. 执行SqlSession对象执行查询,获取结果User
// 查询多条数据使用selectList方法
List<Object> list = sqlSession.selectList("queryUserByUsername1", "%王%");
// 6. 打印结果
for (Object user : list) {
System.out.println(user);
}
// 7. 释放资源
sqlSession.close();
}
Эффект теста следующий:
Используйте регистр ${}
1. Файл сопоставления:
Добавьте следующее в файл конфигурации User.xml:
<!-- 如果传入的参数是简单数据类型,${}里面必须写value -->
<select id="queryUserByUsername2" parameterType="string"
resultType="cn.itcast.mybatis.pojo.User">
SELECT * FROM `user` WHERE username LIKE '%${value}%'
</select>
2. Процедура проверки:Метод тестирования, добавленный в MybatisTest, выглядит следующим образом:
@Test
public void testQueryUserByUsername2() throws Exception {
// 4. 创建SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
// 5. 执行SqlSession对象执行查询,获取结果User
// 查询多条数据使用selectList方法
List<Object> list = sqlSession.selectList("queryUserByUsername2", "王");
// 6. 打印结果
for (Object user : list) {
System.out.println(user);
}
// 7. 释放资源
sqlSession.close();
}
Конечно, оба случая имеют одинаковый эффект!
Если эта статья хоть немного поможет вам, то, пожалуйста, поставьте лайк, спасибо~
Наконец, если есть какие-либо недостатки или неточности, добро пожаловать на исправления и критику, большое спасибо! Если у вас есть какие-либо вопросы, пожалуйста, оставьте сообщение и ответьте как можно скорее!
Приглашаю всех обратить внимание на мою официальную учетную запись, обсудить технологии вместе, тосковать по технологиям, заниматься технологиями, и вы станете другом, когда согласитесь...