ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 11.12.2023
Просмотров: 16
Скачиваний: 1
ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
[Вопросы для собеседования](README.md)
# JDBC
+ [Что такое _JDBC_?](#Что-такое-jdbc)
+ [В чем заключаются преимущества использования JDBC?](#В-чем-заключаются-преимущества-использования-jdbc)
+ [Что из себя представляет JDBC URL?](#Что-из-себя-представляет-jdbc-url)
+ [Из каких частей стоит JDBC?](#Из-каких-частей-стоит-jdbc)
+ [Перечислите-основные-классы-и-интерфейсы-jdbc](#Перечислите-основные-классы-и-интерфейсы-jdbc)
+ [Опишите основные этапы работы с базой данных с использованием JDBC.](#Опишите-основные-этапы-работы-с-базой-данных-при-использовании-jdbc)
+ [Перечислите основные типы данных используемые в JDBC. Как они связаны с типами Java?](#Перечислите-основные-типы-данных-используемые-в-JDBC.-Как-они-связаны-с-типами-Java)
+ [Как зарегистрировать драйвер JDBC?](#Как-зарегистрировать-драйвер-jdbc)
+ [Как установить соединение с базой данных?](#Как-установить-соединение-с-базой-данных)
+ [Какие уровни изоляции транзакций поддерживаются в JDBC?](#Какие-уровни-изоляции-транзакций-поддерживаются-в-jdbc)
+ [При помощи чего формируются запросы к базе данных?](#При-помощи-чего-формируются-запросы-к-базе-данных)
+ [Чем отличается Statement от PreparedStatement?](#Чем-отличается-statement-от-preparedstatement)
+ [Как осуществляется запрос к базе данных и обработка результатов?](#Как-осуществляется-запрос-к-базе-данных-и-обработка-результатов)
+ [Как вызвать хранимую процедуру?](#Как-вызвать-хранимую-процедуру)
+ [Как закрыть соединение с базой данных?](#Как-закрыть-соединение-с-базой-данных)
## Что такое _JDBC_?
__JDBC, Java DataBase Connectivity (соединение с базами данных на Java)__ — промышленный стандарт взаимодействия Java-приложений с различными СУБД. Реализован в виде пакета `java.sql`, входящего в состав Java SE.
JDBC основан на концепции драйверов, которые позволяют получать соединение с базой данных по специально описанному URL. При загрузке драйвер регистрирует себя в системе и в дальнейшем автоматически вызывается, когда программа требует URL, содержащий протокол, за который этот драйвер отвечает.
В чем заключаются преимущества использования JDBC?
Преимуществами JDBC считают:
+ Лёгкость разработки: разработчик может не знать специфики базы данных, с которой работает;
+ Код практически не меняется, если компания переходит на другую базу данных (количество изменений зависит исключительно от различий между диалектами SQL);
+ Не нужно дополнительно устанавливать клиентскую программу;
+ К любой базе данных можно подсоединиться через легко описываемый URL.
Что из себя представляет JDBC URL?
JDBC URL состоит из:
+ `
:` (протокола) - всегда `jdbc:`.
+ `
+ `
/
Из каких частей стоит JDBC?
JDBC состоит из двух частей:
+ JDBC API, который содержит набор классов и интерфейсов, определяющих доступ к базам данных. Эти классы и методы объявлены в двух пакетах - `java.sql` и `javax.sql`;
+ JDBC-драйвер, компонент, специфичный для каждой базы данных.
JDBC превращает вызовы уровня API в «родные» команды того или иного сервера баз данных.
Перечислите основные классы и интерфейсы JDBC.
+ `java.sql.DriverManager` - позволяет загрузить и зарегистрировать необходимый JDBC-драйвер, а затем получить соединение с базой данных.
+ `javax.sql.DataSource` - решает те же задачи, что и _DriverManager_, но более удобным и универсальным образом. Существуют также `javax.sql.ConnectionPoolDataSource` и `javax.sq1.XADataSource` задача которых - обеспечение поддержки пула соединений.
+ `java.sql.Connection` - обеспечивает формирование запросов к источнику данных и управление транзакциями. Также предусмотрены интерфейсы `javax.sql.PooledConnection` и `javax.sql.XAConnection`.
+ `java.sql.Statement` , `java.sql.PreparedStatement` и `java.sql.CallableStatement` - эти интерфейсы позволяют отправить запрос к источнику данных.
+ `java.sql.ResultSet` - объявляет методы, которые позволяют перемещаться по набору данных и считывать значения отдельных полей в текущей записи.
+ `java.sql.ResultSetMetaData` - позволяет получить информацию о структуре набора данных.
+ `java.sql.DatabaseMetaData` - позволяет получить информацию о структуре источника данных.
Перечислите основные типы данных используемые в JDBC. Как они связаны с типами Java?
JDBC Type | Java Object Type |
CHAR | String |
VARCHAR | String |
LONGVARCHAR | String |
NUMERIC | java.math.BigDecimal |
DECIMAL | java.math.BigDecimal |
BIT | Boolean |
TINYINT | Integer |
SMALLINT | Integer |
INTEGER | Integer |
BIGINT | Long |
REAL | Float |
FLOAT | Double |
DOUBLE | Double |
BINARY | byte[] |
VARBINARY | byte[] |
LONGVARBINARY | byte[] |
DATE | java.sql.Date |
TIME | java.sql.Time |
TIMESTAMP | java.sql.Timestamp |
CLOB | Clob |
BLOB | Blob |
ARRAY | Array |
STRUCT | Struct |
REF | Ref |
DISTINCT | сопоставление базового типа |
JAVA_OBJECT | базовый класс Java |
Опишите основные этапы работы с базой данных при использовании JDBC.
+ Регистрация драйверов;
+ Установление соединения с базой данных;
+ Создание запроса(ов) к базе данных;
+ Выполнение запроса(ов) к базе данных;
+ Обработка результата(ов);
+ Закрытие соединения с базой данных.
Как зарегистрировать драйвер JDBC?
Регистрацию драйвера можно осуществить несколькими способами:
+ `java.sql.DriverManager.registerDriver(%объект класса драйвера%)`.
+ `Class.forName(«полное имя класса драйвера»).newInstance()`.
+ `Class.forName(«полное имя класса драйвера»)`;
Как установить соединение с базой данных?
Для установки соединения с базой данных используется статический вызов `java.sql.DriverManager.getConnection(...)` .
В качестве параметра может передаваться:
+ URL базы данных
java static Connection getConnection(String url);
+ URL базы данных и набор свойств для инициализации
java static Connection getConnection(String url, Properties info)
+ URL базы данных, имя пользователя и пароль
java static Connection getConnection(String url, String user, String password)
В результате вызова будет установлено соединение с базой данных и создан объект класса `java.sql.Connection` - своеобразная «сессия», внутри контекста которой и будет происходить дальнейшая работа с базой данных.
Какие уровни изоляции транзакций поддерживаются в JDBC?
- Уровень изолированности транзакций — значение, определяющее уровень, при котором в транзакции допускаются несогласованные данные, то есть степень изолированности одной транзакции от другой. Более высокий уровень изолированности повышает точность данных, но при этом может снижаться количество параллельно выполняемых транзакций. С другой стороны, более низкий уровень изолированности позволяет выполнять больше параллельных транзакций, но снижает точность данных.
Во время использования транзакций, для обеспечения целостности данных, СУБД использует блокировки, чтобы заблокировать доступ других обращений к данным, участвующим в транзакции. Такие блокировки необходимы, чтобы предотвратить:
+ «грязное» чтение (dirty read) — чтение данных, добавленных или изменённых транзакцией, которая впоследствии не подтвердится (откатится);
+ неповторяющееся чтение (non-repeatable read) — при повторном чтении в рамках одной транзакции ранее прочитанные данные оказываются изменёнными;
+ фантомное чтение (phantom reads) — ситуация, когда при повторном чтении в рамках одной транзакции одна и та же выборка дает разные множества строк.
Уровни изоляции транзакций определены в виде констант интерфейса `java.sql.Connection`:
+ `TRANSACTION_NONE` – драйвер не поддерживает транзакции;
+ `TRANSACTION_READ_UNCOMMITTED` – позволяет транзакциям видеть несохраненные изменения данных: разрешает грязное, непроверяющееся и фантомное чтения;
+ `TRANSACTION_READ_COMMITTED` – любое изменение, сделанное в транзакции, не видно вне неё, пока она не сохранена: предотвращает грязное чтение, но разрешает непроверяющееся и фантомное;
+ `TRANSACTION_REPEATABLE_READ` – запрещает грязное и непроверяющееся, фантомное чтение разрешено;
+ `TRANSACTION_SERIALIZABLE` – грязное, непроверяющееся и фантомное чтения запрещены.
> __NB!__ Сервер базы данных может не поддерживать все уровни изоляции. Интерфейс `java.sql.DatabaseMetaData` предоставляет информацию об уровнях изолированности транзакций, которые поддерживаются данной СУБД.
Уровень изоляции транзакции используемый СУБД можно задать с помощью метода `setTransactionIsolation()` объекта `java.sql.Connection`. Получить информацию о применяемом уровне изоляции поможет метод `getTransactionIsolation()`.
[к оглавлению](#jdbc)
## При помощи чего формируются запросы к базе данных?
Для выполнения запросов к базе данных в Java используются три интерфейса:
+ `java.sql.Statement` - для операторов SQL без параметров;
+ `java.sql.PreparedStatement` - для операторов SQL с параметрами и часто выполняемых операторов;
+ `java.sql.CallableStatement` - для исполнения хранимых в базе процедур.
Объекты-носители интерфейсов создаются при помощи методов объекта `java.sql.Connection`:
+ `java.sql.createStatement()` возвращает объект _Statement_;
+ `java.sql.prepareStatement()` возвращает объект _PreparedStatement_;
+ `java.sql.prepareCall()` возвращает объект _CallableStatement_;
[к оглавлению](#jdbc)
## Чем отличается Statement от PreparedStatement?
+ __Statement__: используется для простых случаев запроса без параметров.
+ __PreparedStatement__: предварительно компилирует запрос, который может содержать входные параметры и выполняться несколько раз с разным набором этих параметров.
Перед выполнением СУБД разбирает каждый запрос, оптимизирует его и создает «план» (query plan) его выполнения. Если один и тот же запрос выполняется несколько раз, то СУБД в состоянии кэшировать план его выполнения и не производить этапов разборки и оптимизации повторно. Благодаря этому запрос выполняется быстрее.
Суммируя: _PreparedStatement_ выгодно отличается от _Statement_ тем, что при повторном использовании с одним или несколькими наборами параметров позволяет получить преимущества заранее прекомпилированного и кэшированного запроса, помогая при этом избежать SQL Injection.
[к оглавлению](#jdbc)
## Как осуществляется запрос к базе данных и обработка результатов?
Выполнение запросов осуществляется при помощи вызова методов объекта, реализующего интерфейс `java.sql.Statement`:
+ __`executeQuery()`__ - для запросов, результатом которых является один набор значений, например запросов `SELECT`. Результатом выполнения является объект класса `java.sql.ResultSet`;
+ __`executeUpdate()`__ - для выполнения операторов `INSERT`, `UPDATE` или `DELETE`, а также для операторов _DDL (Data Definition Language)_. Метод возвращает целое число, показывающее, сколько записей было модифицировано;
+ __`execute()`__ – исполняет SQL-команды, которые могут возвращать различные результаты. Например, может использоваться для операции `CREATE TABLE`. Возвращает `true`, если первый результат содержит _ResultSet_ и `false`, если первый результат - это количество модифицированных записей или результат отсутствует. Чтобы получить первый результат необходимо вызвать метод `getResultSet()` или `getUpdateCount()`. Остальные результаты доступны через вызов `getMoreResults()`, который при необходимости может быть произведён многократно.
Объект с интерфейсом `java.sql.ResultSet` хранит в себе результат запроса к базе данных - некий набор данных, внутри которого есть курсор, указывающий на один из элементов набора данных - текущую запись.
Используя курсор можно перемещаться по набору данных при помощи метода `next()`.
> __NB!__ Сразу после получения набора данных его курсор находится перед первой записью и чтобы сделать её текущей необходимо вызвать метод `next()`.
Содержание полей текущей записи доступно через вызовы методов `getInt()`, `getFloat()`, `getString()`, `getDate()` и им подобных.
[к оглавлению](#jdbc)
## Как вызвать хранимую процедуру?
__Хранимые процедуры__ – это именованный набор операторов SQL хранящийся на сервере. Такую процедуру можно вызвать из Java-класса с помощью вызова методов объекта реализующего интерфейс `java.sql.Statement`.
Выбор объекта зависит от характеристик хранимой процедуры:
+ без параметров → `Statement`
+ с входными параметрами → `PreparedStatement`
+ с входными и выходными параметрами → `CallableStatement`
> Если неизвестно, как была определена хранимая процедура, для получения информации о хранимой процедуре (например, имен и типов параметров) можно использовать методы `java.sql.DatabaseMetaData` позволяющие получить информацию о структуре источника данных.
Пример вызова хранимой процедуры с входными и выходными параметрами:
```java
public vois runStoredProcedure(final Connection connection) throws Exception {
// описываем хранимую процедуру
String procedure = "{ call procedureExample(?, ?, ?) }";
// подготавливаем запрос
CallableStatement cs = connection.prepareCall(procedure);
// устанавливаем входные параметры
cs.setString(1, "abcd");
cs.setBoolean(2, true);
cs.setInt(3, 10);
// описываем выходные параметры
cs.registerOutParameter(1, java.sql.Types.VARCHAR);
cs.registerOutParameter(2, java.sql.Types.INTEGER);
// запускаем выполнение хранимой процедуры
cs.execute();
// получаем результаты
String parameter1 = cs.getString(1);
int parameter2 = cs.getInt(2);
// заканчиваем работу с запросом
cs.close();
}
```
[к оглавлению](#jdbc)
## Как закрыть соединение с базой данных?
Соединение с базой данной закрывается вызовом метода `close()` у соответствующего объекта `java.sql.Connection` или посредством использования механизма try-with-resources при создании такого объекта, появившегося в Java 7.
> __NB!__ Предварительно необходимо закрыть все запросы созданные этим соединением.
[к оглавлению](#jdbc)
# Источники
+ [Википедия - JDBC](https://ru.wikipedia.org/wiki/Java_Database_Connectivity)
+ [IBM developerWorks®](http://www.ibm.com/developerworks/ru/library/dm-1209storedprocedures/)
+ [Документация к пакету java.sql](https://docs.oracle.com/javase/7/docs/api/java/sql/package-summary.html)
+ [Википедия - Уровень изолированности транзакции](https://ru.wikipedia.org/wiki/Уровень_изолированности_транзакций)
[Вопросы для собеседования](README.md)