- •Раздел 16. Многоуровневые и многослойные приложения. Шаблон проектирования Модель-Представление-Контроллер
- •16.1. Многоуровневые приложения
- •16.2. Многослойные приложения
- •16.3. Шаблон проектирования Модель-Представление-Контроллер
- •16.4. Реализация шаблона Модель-Представление-Контроллер в веб-приложениях
- •Раздел 17. Базы данных в веб-приложениях
- •17.1. Основные понятия баз данных
- •17.2. Системы управления базами данных
- •17.3. Язык запросов sql
- •Транзакции
- •17.4. Доступ к базам данных из Java
- •Пример: база данных студентов
- •Поддержка транзакций
- •17.5. Объектно-реляционная проекция
- •Лекция 18. Безопасность Интернет-приложений
- •18.1. Аутентификация и авторизация
- •18.2. Понятие безопасности Интернет-приложений
- •18.3. Классы атак сетевого уровня Сниффинг пакетов
- •Подмена ip-адреса
- •Отказ в обслуживании
- •Сетевая разведка
- •18.4. Криптографические технологии
- •18.5. Уязвимости уровня приложений
- •Уязвимости системы аутентификации
- •Уязвимости системы авторизации
- •Атаки на стороне клиента
- •Выполнение кода на сервере
- •Разглашение информации
- •Злоупотребление функциональными возможностями
- •Наиболее распространенные уязвимости
- •18.6. Резюме
Транзакции
Транзакция — последовательность изменений в базе данных, которые либо все успешно выполнены, либо все не выполнены, т. е. не может быть такого, что часть изменений успешно сохранена, а часть нет.
В SQL поддержка транзакций реализована операторами COMMIT и ROLLBACK. COMMIT успешно завершает транзакцию и сохраняет изменения в базе, ROLLBACK наоборот, все изменения отменяет. Оба оператора по завершении начинают новую транзакцию.
Транзакции поддерживаются различными СУБД по-разному, некоторые простые СУБД вообще не поддерживают работу транзакций.
17.4. Доступ к базам данных из Java
Java Database Connectivity (JDBC) — технология взаимодействия языка Java с базами данных, включает в себя API для разработки клиентских приложений и для разработки драйверов баз данных (специализированных библиотек для работы с конкретной СУБД).
JDBC API состоит из пакетов java.sql и javax.sql, в данном параграфе рассматривается только пакет java.sql. На схеме ниже изображена архитектура взаимодействия с базой данных через JDBC:
Таким образом, код работы с базой данных из приложения становится универсальным, а для перехода на базу данных другого производителя требуется лишь заменить драйвер (если не брать во внимание возможные нестыковки в SQL-запросах, о чем говорилось выше).
Некоторые важные классы пакета java.sql:
-
DriverManager — менеджер доступных драйверов базы данных.
-
Connection — представляет собой соединение к базе данных.
-
Statement — представляет собой SQL-оператор.
-
PreparedStatement — представляет собой подготовленный SQL-оператор с параметрами. «Подготовленный» означает, что сначала в СУБД выполняется синтаксический разбор оператора и строится план выполнения, после этого при каждом выполнении используется уже «откомпилированный» SQL-оператор, что повышает производительность.
-
ResultSet — представляет собой набор строк, возвращаемых по запросу SELECT.
-
SQLException — класс, инкапсулирующий ошибку, возникшую на стороне базы данных.
Общая схема работы с базой данных через JDBC следующая:
1. Загрузка драйвера
Загружается драйвер базы данных, т. е. принудительно вызывается загрузка класса драйвера в память Java-машины (класс для этого должен быть «виден» Java):
// загружаем драйвер MySQL Connector/J
Class.forName("com.mysql.jdbc.Driver");
Он самостоятельно регистрируется в списке доступных драйверов посредством вызова метода DriverManager.registerDriver и после этого может быть использован для установления соединения.
2. Соединение с СУБД
Устанавливается соединение к базе данных, для чего вызывается метод getConnection класса DriverManager с параметрами соединения:
Connection con = DriverManager.getConnection(URL, USER, PASSWORD);
URL — строка соединения, конкретный вид которой зависит от используемого драйвера и может быть найден в документации к нему. Например, строка соединения для драйвера MySQL Connector/J имеет вид: "jdbc:mysql://example.org:3306/test" (означает, что сервер базы данных запущен на машине с доменным именем example.org, на порту 3306, а имя базы данных — test).
USER — имя пользователя, который имеет права на доступ к базе.
PASSWORD — пароль пользователя.
3. Создание объекта-запроса
Инициализируется объект-запрос, для чего используется соответствующий метод createStatement или prepareStatement класса Connection:
PreparedStatement st = con.prepareStatement(
"insert into student (last_name, first_name) values (?, ?)");
Метод prepareStatement принимает строку с SQL-оператором. Знаки вопроса означают параметры, которые необходимо установить перед выполнением оператора.
4. Инициализация параметров запроса
Устанавливаются параметры, если этого требует SQL-оператор:
st.setInt(1, "Иванов");
st.setString(2, "Иван");
5. Выполнение оператора
Если SQL-оператор не предполагает возвращение результата, вызывается метод executeUpdate:
st.executeUpdate();
Если SQL-оператор возвращает набор строк (оператор SELECT), используется метод executeQuery:
ResultSet rs = st.executeQuery();
Объект rs содержит полученные данные и различные методы для доступа к ним, например:
while (rs.next()) { // переходим на следующую запись
Integer i = rs.getInt(1); // получаем первое значение
String s = rs.getString(2); // получаем второе значение
}
6. Завершение работы с СУБД
Все объекты, создаваемые для работы с базой данных, закрываются.
st.close();
con.close();
Это требуется для того, чтобы освободить используемые ресурсы. Например, база данных может иметь ограничение на число одновременных соединений, и если они не будут вовремя закрыты, в определенный момент клиент получит отказ в установлении нового соединения.
Все вышеперечисленные операции могут вызвать исключение SQLException, поэтому для грамотной обработки иключительных ситуаций они помещаются в блок try-catch.