Connection
представляет собой соединение с БД.
Сессия соединения включает в себя выполняемые SQL-запросы и возвращаемые
через соединение результаты.
Приложение может открыть одно или более соединений с одной или несколькими БД.
DriverManager.getConnection
. Этому методу передается
строка, содержащая т.н. "URL". Класс
DriverManager
, представляющий собой уровень управления в JDBC,
пытается найти драйвер, который может соединиться к БД с помощью данного URL.
Класс DriverManager
содержит список зарегистрированных классов
Driver
, и при вызове метода
getConnection
он проверяет каждый драйвер и ищет среди них тот,
который "умеет" соединятся с БД, указанной в URL.
Метод connect
драйвера использует этот URL для установления соединения.
Пользователь может пропустить этот управляющий уровень JDBC и вызывать
непосредственно методы класса
Driver
для открытия соединения. Это может быть нужным в тех редких случаях, когда два
или более драйвера могут обслужить заданный URL, но пользователь хочет выбрать
конкретный из них. Тем не менее, намного проще возложить эту работу на класс
DriverManager
.
Следующий код демонстрирует открытие соединенияс БД, находящейся по URL
"jdbc:odbc:wombat"
, с именем пользователя "oboy"
и паролем "12Java"
:
String url = "jdbc:odbc:wombat"; Connection con = DriverManager.getConnection(url, "oboy", "12Java");
URL (Uniform Resource Locator) представляет собой информацию для адресации ресурса в Интернет. Другими словами, это адрес ресурса.
Первая часть URL задает протокол, используемый для доступа к информации, и всегда заканчивается знаком ":". Среди протоколов наиболее популярны "ftp" ("file transfer protocol" - протокол передачи файлов), и "http" ("hypertext transfer protocol" - протокол передачи гипертекста). Протокол "file" означает, что ресурс находится в локальной файловой системе, а не в Интернет. Примеры URL:
ftp://javasoft.com/docs/JDK-1_apidocs.zip http://java.sun.com/products/JDK/CurrentRelease file:/home/haroldw/docs/tutorial.htmlОстальная часть URL, - то, что после первого двоеточия, - это то место, где находится источник данных. В случае протокола "
file
" оставшаяся часть URL - это путь к файлу. Для протоколов
ftp
и http
оставшаяся часть URL идентифицирует хост (имя сервера)
и необязательный путь к конкретном сайту или файлу. Например, ниже приведен
URL домашней страницы фирмы JavaSoft. Этот URL указывает только имя хоста:
http://www.javasoft.com
Так как JDBC-URL используются с различными драйверами, то они должны неизбежно быть
очень гибкими. Во-первых, они допускают использование различными драйверами
различных схем именования баз данных. Например, подпротокол
odbc
позволяет использовать значения атрибутов в URL.
Во-вторых, JDBC-URL дают возможность разработчикам jdbc-драйверов кодировать всю нужную для соединения информацию в URL.
В-третьих, с помощью JDBC-URL принципиально возможно осуществить "перенаправление": JDBC-URL может ссылаться на логический хост или имя БД, которое динамически транслируется в настоящее имя с помощью сетевой службы имен. Таким образом можно избежать непосредственного назначения хоста в JDBC URL. Существует несколько сетевых сервисов имен (DNS, NIS, and DCE).
Стандартный синтаксис JDBC URL показан ниже. Он имеет три части, разделенных двоеточием:
jdbc:<subprotocol>:<subname>JDBC URL состоит из:
jdbc
- протокола. Протокол, используемый в JDBC URL - всегда jdbc
.
<subprotocol> (подпротокола)
- это имя драйвера или имя механизма
соединения с БД. Подпротокол может поддерживаться одним или несколькими драйверами.
Лежащий на поверхности пример подпротокола - это
"odbc", отведенный для URL, обозначающих имя источника данных ODBC.
Например, для доступа к БД через мост
JDBC-ODBC нужно использовать URL такого вида:
jdbc:odbc:fredВ этом примере подпротокол задан как "odbc", а подимя "fred" является локальным источником данных.
Если кому-то захочется использовать сервис имен (т.е. имя БД в JDBC-URL не будет действительным именем БД), то подпротоколом может быть сервис имен:
jdbc:dcenaming:accounts-payableВ этом примере URL указывает локальный сервис имен DCE, который должен разрешить имя БД "accounts-payable" в более определенное имя, которое далее будет использоваться для подключения к БД.
<subname> (подимени)
- это идентификатор БД. Значение
подимени может менятся в зависимости от подпротокола, и может также иметь
подподимя с синтаксисом, определяемым разработчиком драйвера. Назначение
подимени - это предоставление всей информации, необходимой для поиска БД.
В предыдущем примере достаточно строки "fred", так как
оставшуюся часть информации предоставляет ODBC. Однако удаленная БД требует
дополнительную информацию. Например, если БД находится в Интернет, то в состав
подимени JDBC-URL должен быть включен сетевой адрес, подчиняющийся следующим
соглашениям:
//hostname:port/subsubnameПредполагая, что "dbnet" - это протокол соединения к хосту в Интернет, JDBC-URL может выглядеть так:
jdbc:dbnet://wombat:356/fred
odbc
зарезервирован для URL, которые определяют
имена источников данных (DSN) ODBC и имеют специальную возможность
задавать некоторое количество значений атрибутов после подимени (имени
источника данных, DSN). Полный синтаксис подпротокола ODBC - следующий:
jdbc:odbc:<data-source-name
>[;<attribute-name>
=<attribute-value
>]*
Примеры корректных JDBC-URL для подпротокола odbc приведены ниже:
jdbc:odbc:qeor7 jdbc:odbc:wombat jdbc:odbc:wombat;CacheSize=20;ExtensionCase=LOWER jdbc:odbc:qeora;UID=kgh;PWD=fooey
DriverManager
"показывает" это имя своему списку зарегистрированных
драйверов, и тот драйвер, который отвечает за этот подпротокол, должен "откликнуться"
и установит соединение с БД. Например,
odbc
зарезервирован за рассмотренным выше
мостом JDBC-ODBC. Кто-нибудь другой, например, Miracle Corporation, может
зарегистрировать в качестве подпротокола "miracle" для jdbc-драйвера,
который соединяется с СУБД Miracle. При этом никто другой уже не сможет использовать
это имя.
Организация JavaSoft служит в качестве информационного реестра имен JDBC-подпротоколов. Чтобы зарегистрировать подпротокол, надо послать письмо по адресу:
jdbc@wombat.eng.sun.com
В JDBC есть три класса для посылки SQL-запросов в БД и три метода в интерфейсе
Connection
создают экземпляры этих классов. Эти классы и методы,
которые их создают, перечислены ниже:
Statement
- создается методом createStatement
.
Объект Statement
используется при простых SQL-запросах.
PreparedStatement
- создается методом prepareStatement
.
Объект PreparedStatement
используется в SQL-запросах с одним или более
входными параметрами (IN parameters).
PreparedStatement
содержит группу методов, устанавливающих
значения входных параметров, которые отсылаются в БД при выполнении запроса.
Экземпляры класса PreparedStatement
расширяют (наследуются от) Statement
и, таким образом, включают методы Statement
.
Объект PreparedStatement
потенциально может быть более эффективным,
чем
Statement
, так как он прекомпилируется и сохраняется для будущего
использования.
CallableStatement
- создается методом
prepareCall
.
Объекты CallableStatement
используются для выполнения т.н.
хранимых процедур - именованных групп SQL-запросов, наподобие вызова подпрограммы.
Объект CallableStatement
наследует методы обработки входных (IN)
параметров из
PreparedStatement
, а также добавляет методы для обработки
выходных (OUT) и входных-выходных (INOUT) параметров.
Connection
лучше использовать для создания различных SQL-запросов:
Метод createStatement
используется для
Метод prepareStatement
используется для
Метод prepareCall
используется для
commit
или
rollback
текущая транзацкия заканчивается и начинается другая.
Каждое новое соединение по умолчанию находится в режиме автофиксации (auto-commit),
что означает автоматическую фиксацию (commit) транзакции после каждого запроса.
В этом случае транзакция состоит из одного запроса. Если auto-commit запрещен,
транзакция не заканчивается вплоть до явного вызова
commit
или rollback
, включая, таким образом, все выражения,
выполненные с момента последнего вызова
commit
или rollback
. В этом случае все SQL-запросы
в транзакции фиксируются или откатываются группой.
Метод фиксации commit
делает окончательными все изменения в БД,
проделанные SQL-выражением, и снимает также все блокировки, установленные транзакцией.
Метод rollback
проигнорирует, "отбракует" эти изменения.
Иногда пользователю нужно, чтобы какое-либо изменение не вступило в силу до тех пор,
пока не вступит в силу предыдущее изменение. Этого можно достичь запрещением auto-commit
и группировкой обоих запросов в одну транзакцию. Если оба изменения произошли
успешно, то вызывается метод commit
, который переносит эффект от
этих изменений в БД; если одно или оба запроса не прошли, то вызывается метод
rollback
, который возвращает прежнее состояние БД.
Большинство JDBC-драйверов поддерживают транзакции. На самом деле драйвер,
соответствующий спецификации JDBC, обязан поддерживать их.
Интерфейс DatabaseMetaData
предоставляет информацию
об уровнях изолированности транзакций, которые поддерживаются данной СУБД.
con.setTransactionIsolation(TRANSACTION_READ_UNCOMMITTED);Чем выше уровень изолированности транзакций, тем больше внимания СУБД уделяет устранению конфликтов. Интерфейс
Connection
определяет пять
таких уровней. Минимальный из них соответствует случаю, когда транзакции
не поддерживаются вовсе, а максимальный - невозможности существования более
одной транзакции в любой момент времени. Обычно, чем выше уровень изолированности,
тем медленнее выполняется приложение (из-за избыточной блокировки и уменьшенной
конкурентности пользователей). При выборе конкретного уровня
изолированности разработчик должен найти золотую середину
между потребностями в производительности и требованиями к целостности данных.
Очевидно, что реально поддерживаемые уровни зависят от возможностей используемой СУБД.
При создании объекта Connection
его уровень изолированности
зависит от драйвера или БД. Пользователь может вызвать метод
setIsolationLevel
, чтобы изменить уровень изолированности транзакций,
и новое значение уровня будет установлено до конца сессии.
Чтобы установить уровень изолированности только для одной транзакции,
надо установить его перед выполнением транзакции и восстановить прежнее значение после
ее завершения. Изменение уровня изолированности во время самой транзакции нежелательно,
так как произойдет автоматический вызов
commit
, что повлечет за собой фиксацию изменений.