Разница между #{} и ${} в Mybatis

MyBatis

предисловие

При использовании 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,{}将传入的数据<font color=red>直接显示生成</font>在sql中。如:`select * from user where id= {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();
}

Конечно, оба случая имеют одинаковый эффект!

Если эта статья хоть немного поможет вам, то, пожалуйста, поставьте лайк, спасибо~

Наконец, если есть какие-либо недостатки или неточности, добро пожаловать на исправления и критику, большое спасибо! Если у вас есть какие-либо вопросы, пожалуйста, оставьте сообщение и ответьте как можно скорее!

Приглашаю всех обратить внимание на мою официальную учетную запись, обсудить технологии вместе, тосковать по технологиям, заниматься технологиями, и вы станете другом, когда согласитесь...

在这里插入图片描述