Ранее в статьях данной серии различные понятия баз данных были представлены на примерах применения
инструмента ij для подключения и взаимодействия с базой данных Apache Derby.
Хотя, возможно, в настоящий момент это не очевидно, но использовалось Java-приложение, в котором
интерфейс прикладного программирования (API) JDBC применялся для подключения и взаимодействия со встроенной
базой данных Apache Derby. В следующих нескольких статьях будет показано, как повторно создать базовые
функции инструмента ij при создании собственного Java-приложения.
В этой статье описывается подключение к базе данных и обработка возможных ошибок и предупреждений
базы данных.
Прежде чем приступить к созданию Java-кода, возможно, окажутся интересными некоторые сведения о сущности JDBC API.
JDBC представляет собой официальный Java Database Connectivity API и применяется, начиная с версии 1.1
Java Development Kit. JDBC API включен в пакет java.sql. Если посмотреть внимательно, можно заметить, что API
представляет собой в основном интерфейсы. В результате JDBC драйвер баз данных фактически
создается разрабочиками базы данных (или сторонними разработчиками), которые должны предоставить
Java-классы, реализующие эти интерфейсы. Дополнительные функциональные возможности содержатся в расширениях JDBC
API, доступных в пакете javax.sql. В следующих нескольких статьях в основном будет описываться стандартный пакет
JDBC, расширения будут рассмотрены позднее.
И последнее о JDBC: Соединение между Java-приложением и базой данных управляется драйвером JDBC. Изначально имелось четыре типа драйверов JDBC, различаемых по номеру: 1, 2, 3 или 4. Эти типы соответствуют различным методам взаимодействия Java-приложения с базой данных. Сегодня большинство драйверов, включая драйверы, используемые для подключения к базе данных Derby, представляют собой драйверы типа 4, то есть они написаны полностью на языке Java и преобразуют JDBC API непосредственно в протокол базы данных, заданный производителем. Для базы данных Derby это процесс несколько упрощается, поскольку пакет Derby также написан на языке Java!
Теперь, когда имеется представление об основах JDBC, можно приступить к подключению к встроенной базе данных Apache Derby при помощи языка программирования Java. Но сначала необходимо установить программное обеспечение базы данных Apache Derby, как это обсуждалось в первой статье данной серии. Если этот важный шаг еще не выполнен, просмотрите первую статью, загрузите и установите ПО Derby. После установки системы баз данных Derby для подключения к базе данных Derby можно воспользоваться примером программы, прилагаемой к данной статье, как это показано в листинге 1.
Листинг 1. Выполнение примера программы
rb$ mkdir derbyWork
rb$ cd derbyWork/
rb$ unzip ../derby9.zip
Archive: ../derby9.zip
inflating: FirstConnect.java
rb$ ls
FirstConnect.java
rb$ javac FirstConnect.java
rb$ java FirstConnect
----------------------------------------------------
Database Name = Apache Derby
Database Version = 10.1.2.1
Driver Name = Apache Derby Embedded JDBC Driver
Driver Version = 10.1.2.1
Database URL = jdbc:derby:test
----------------------------------------------------
rb$ java FirstConnect
SQLWarning: State=01J01, Severity = 10000
Database 'test' not created, connection made to existing database instead.
----------------------------------------------------
Database Name = Apache Derby
Database Version = 10.1.2.1
Driver Name = Apache Derby Embedded JDBC Driver
Driver Version = 10.1.2.1
Database URL = jdbc:derby:test
----------------------------------------------------
rb$ ls
FirstConnect.class derby.log
FirstConnect.java test
|
В первом примере создайте пустое рабочее пространство для разработки и выполнения
кода приложения базы данных. Сначала создайте новую папку и разверните в нее исходный файл,
прилагаемый к данной статье. Перед компиляцией используйте команду ls
для проверки, что в папке имеется только исходный код Java, описываемый
в данной статье.
Далее при помощи компилятора Java создайте файл байткода Java, который будет исполняться
Java Virtual Machine (JVM) на следующем этапе. Если исходный код скомпилирован успешно, байткод
можно выполнить в JVM. Код вызывает метод main
для класса FirstConnect, создающий выходные данные,
аналогично представленному коду; если возникают проблемы, см. вкладку "Что делать, если программа
не запускается?". Этот Java-код сначала создает базу данных test, а затем -- подключение к этой базе данных при помощи драйвера JDBC пакета Apache Derby. Для демонстрации возможности кода по правильной обработке ошибок и предупреждений SQL, можно
еще раз выполнить код. При этом выводится предупреждение, что база данных
не создана (посколько она уже существует), и стандартные сведения о базе данных
и драйвере JDBC, которые отображались ранее.
Данный пример завершается еще одним отображением содержимого рабочей папки, показывая как скомпилированные файлы Java-классов, так и новые файлы базы данных. Последнее является важным: При использовании Apache Derby в качестве встроенной базы данных, по умолчанию файлы базы данных находятся в той же папке, что и код. Если требуется разместить их в другой папке, необходимо изменить JDBC URL для задания папки, в которой будут создаваться файлы базы данных. Этот вопрос в данной статье не рассматривается. Просмотрите руководство Derby Developer's Guide, доступное по ссылке в интерактивных руководствах, приведенной в разделе Ресурсы.
Подключение Java-приложения в базе данных Derby
Java-код, выполнение которого было показано в предыдущем разделе, является простым и подробно описан в оставшейся части статьи. В производственной среде разработка Java-приложений баз данных может оказаться сложной. Вместо их подробного описания, которое будет сделано в следующих статьях, в данной статье рассматривается один из основных способов установления подключения Java-приложения к встроенной базе данных Apache Derby. Как видно из листинга 2, для этого метода требуется драйвер JDBC, реализующий протоколы подключения.
Листинг 2. Использование JDBC для подключения к базе данных Derby
private static final String driver = "org.apache.derby.jdbc.EmbeddedDriver" ;
private static final String url = "jdbc:derby:test;create=true" ;
public static void main(String[] args) {
Connection con = null ;
DatabaseMetaData dbmd = null ;
try {
Class.forName(driver) ;
con = DriverManager.getConnection(url);
// Use the database connection somehow.
} catch (SQLException se) {
printSQLException(se) ;
} catch(ClassNotFoundException e){
System.out.println("JDBC Driver " + driver + " not found in CLASSPATH") ;
}finally {
if(con != null){
try{
con.close() ;
} catch(SQLException se){
printSQLException(se) ;
}
}
}
} |
В коде примера сначала определяются две константы, содержащие имя Java-класса для встроенного в Apache
Derby драйвера JDBC и URL-адреса JDBC подключения к базе данных. Этот URL-адрес подключения должен уже быть
знакомым, он использовался в предыдущих статьях с командой connect инструмента ij. Значение,
назначенное driver, представляет собой полное имя
класса встроенного драйвера.
Остальной код содержится в методе main
; в нем загрузчик классов по умолчанию в JVM используется для поиска и
обработки ранее созданного класса driver, выполняемого при
помощи метода Class.forname. Этот метод выполняет поиск файла класса для
встроенного в Derby драйвера, который должен находиться в папке, указанной в CLASSPATH, а затем загружает этот файл в JVM. В процессе загрузки
обрабатывается статический раздел класса, регистрирующий драйвер в JDBC объекте DriverManager.
DriverManager действует в качестве объекта-фабрики. Предоставляя URL-адрес базы данных,
DriverManager возвращает подключение к базе данных при помощи соответстующего драйвера JDBC. Этот шаг
выполняется в следующей строке кода, где при помощи ранее определенного URL-адреса запрашивается JDBC connection в DriverManager.
Несомненно, уже замечено, что запрос на подключение содержится в блоке try ... catch, и что метод close для подключения вызывается в блоке finally. Оба эти вопроса будут рассмотрены далее в этой
статье в разделе "Если что-то не получается". Учитывая ограничения на объем,
в данной статье невозможно полностью рассмотреть различные способы установления подключения к базе данных при помощи JDBC. Например,
в данном примере не используется информация, связанная с безопасностью, такая как имя пользователя или
пароль. В следующих статьях будут рассмотрены другие методы подключения к базе данных (см.,
например, врезку "Как насчет DataSource?"). Если нет возможности ждать выхода этих статей,
просмотрите руководство разработчика Derby Developer's Guide, ссылка на которое находится в разделе Ресурсы данной
статьи.
Если нет опыта работы с метаданными, это понятие может показаться странным. На самом деле все
просто: Метаданные -- это данные, описывающие данные. Относительно базы данных метаданные
описывают определенную базу данных, например, имя базы данных, номер версии или
имя драйвера JDBC, используемого для подключения. Доступ к метаданным базы данных в JDBC выполняется
при помощи вызова соответствующего метода из объекта DatabaseMetaData, как
это показано в листинге 3.
Листинг 3. Работа с метаданными базы данных
DatabaseMetaData dbmd = null ;
dbmd = con.getMetaData() ;
System.out.println("\n----------------------------------------------------") ;
System.out.println("Database Name = " + dbmd.getDatabaseProductName()) ;
System.out.println("Database Version = " + dbmd.getDatabaseProductVersion()) ;
System.out.println("Driver Name = " + dbmd.getDriverName()) ;
System.out.println("Driver Version = " + dbmd.getDriverVersion()) ;
System.out.println("Database URL = " + dbmd.getURL()) ;
System.out.println("----------------------------------------------------") ;
|
Для доступа к соответствующим метаданным сначала из текущего JDBC Connection создается новый объект DatabaseMetaData, как это показано в предыдущем примере. Затем можно вызвать одну
из многих функций
метаданных, предоставляемых драйвером JDBC пакета Apache Derby (полный листинг см. в спецификкации
JDBC, ссылка на которую имеется в разделе Ресурсы статьи). В данном примере извлекается
имя и номер версии программы для базы данных, к которой выполняется доступ, имя драйвера
JDBC и номер версии, используемой для доступа к базе данных, и полный URL-адрес JDBC,
определяющий базу данных, к которой установлено подключение. Метаданные базы данных особенно
полезны при разработке приложения баз данных, взаимодействующего с
различными базами данных или драйверами JDBC. В этом случае метаданные можно использовать для
определения функций отдельной базы данных и драйвера JDBC во время выполнения.
Поскольку используется база данных Apache Derby, либо из предыдущих статей данной серии, либо созданную пользователем, то, несомненно, отображались предупреждения базы данных и ошибки базы данных. Учитывая важность информации, хранимой в базе данных, соответствующая обработка ошибок и предупреждений базы данных может оказаться необходимой для бизнеса. К счастью, выполняя упражнения так, как это описано в данном разделе, такая обработка выполняется просто. Первым шагом будет показано, как просмотреть информацию, предоставляемую приложению об ошибке в базе данных, как это показано в листинге 4.
Листинг 4. Код обработки ошибок
private static void printSQLException(SQLException se) {
while(se != null) {
System.out.print("SQLException: State: " + se.getSQLState());
System.out.println("Severity: " + se.getErrorCode());
System.out.println(se.getMessage());
se = se.getNextException();
}
}
private static void printSQLWarning(SQLWarning sw) {
while(sw != null) {
System.out.print("SQLWarning: State=" + sw.getSQLState()) ;
System.out.println(", Severity = " + sw.getErrorCode()) ;
System.out.println(sw.getMessage());
sw = sw.getNextWarning();
}
} |
Как показано в листинге 4, обработка SQL-исключений и предупреждений SQL выполняется аналогично. Класс SQLWarning наследуется из класса SQLException; но предупреждение SQL менее серьезно,
чем SQL-исключение, поэтому лучше обрабатывать их раздельно. Эти две
функции объявляются как private static, что позволяет вызывать их
из метода main, а не из других классов. В
рабочем коде это можно изменить в соответствии с требованиями программы.
В обеих функциях выполняется цикл по предупреждениям и исключениям. Это может показаться странным с точки зрения нормальной обработки ошибок, но когда дело доходит до программирования баз данных, приходится ожидать сюрпризов. Причина последовательности проста: События зачастую связаны в базе данных. Например, если при вставке нескольких строк в базу данных происходит сбой, обусловленный несоответствием типов данных столбцов или имен, то возможно получить несколько ошибок. Для правильной обработки всех этих ошибок необходимо иметь возможность связать исключения так, чтобы уведомлять код вызова обо всех проблемах в базе данных. В целях упрощения Apache Derby всегда размещает важные исключения в начале цепочки исключений.
Внутри цикла выполняется вывод информации об ошибках или предупреждениях. SQL-состояние представляет собой строку из пяти символов,
соответствующих "Спецификации среды прикладного программирования (CAE) X/OPEN,
Управление данными: SQL, спецификация SQL версии 2 или стандартные преобразования SQL99", позволяющую
программе восстанавливать из определенной базы данных состояния ошибок. Первые два символа The
SQL-состояния представляют собой значение класса, последние три -- значение подкласса. SQL-состояние со значением
00000 соответствует успешному выполнению, тогда как значение класса
01 указывает на состояния предупреждений, например, усечение данных.
Код SQL представляет собой значение, соответствующее определенной базе данных.
Обработка SQL-исключений выполняется просто. В качестве контейнера для вызовов методов JDBC используется стандартный механизм Java
try ... catch, как это показано в листинге 5.
Листинг 5. Перехват SQL-исключенийexceptions
try{
// Execute a JDBC operation
} catch (SQLException se) {
printSQLException(se) ;
} |
Как показано в этом примере кода, обработка исключений SQL выполняется с помощью передачи объекта
SQLException в ранее определенный метод
printSQLException, обрабатывающий все отчеты об
ошибках. Основная сложность обработки SQL-исключений заключается в соответствующем восстановлении
ресурсов базы данных, например, подключения к базе данных. Эти ресурсы, например,
подключение или курсоры базы данных, могут управляться вне JVM, выполняющей
код базы данных приложений, поэтому приложение должно закрывать их в явном виде. Метод close
объекта Connection может
вызывать SQLException, поэтому разместите этот метод в
блоке finally, гарантирующем, что Java-приложение будет выполнять попытки
закрыть подключение к базе данных даже при возникновении ошибок.
С другой стороны, необходимо явно проверить все предупреждения SQL, поскольку они не распространяются
при помощи стандартных механизмов обработки исключений. Для этого вызовите соответствующий метод
getWarnings для объекта JDBC, как это показано в листинге 6.
Листинг 6. Проверка предупреждений SQL
SQLWarning swarn = con.getWarnings() ;
if(swarn != null){
printSQLWarning(swarn) ;
} |
Как было показано ранее, предупреждения SQL обрабатываются методом printSQLWarning
. Перед вызовом метода сначала убедитесь, что имеется хотя бы одно предупреждение SQL. Если это так, то передайте
первый объект SQLWarning в соответствующий метод. В следующих статьях
будут описаны различные объекты JDBC, которые могут создавать предупреждения SQL, поэтому инкапсуляция кода обработки ошибок
и предупреждений может упростить задачу разработки и обслуживания кода приложения базы
данных.
До настоящего момента в данной статье обсуждались различные компоненты, необходимые для установления подключения к базе данных при помощи JDBC API из Apache Derby. Совместно эти компоненты предоставляют большую часть всех необходимых функций, как это можно увидеть в завершенном примере подключения, показанном в листинге 7.
Листинг 7. Завершенный пример кода
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.DatabaseMetaData;
public class FirstConnect {
private static final String driver = "org.apache.derby.jdbc.EmbeddedDriver" ;
private static final String url = "jdbc:derby:test;create=true" ;
static void printSQLException(SQLException se) {
while(se != null) {
System.out.print("SQLException: State: " + se.getSQLState());
System.out.println("Severity: " + se.getErrorCode());
System.out.println(se.getMessage());
se = se.getNextException();
}
}
static void printSQLWarning(SQLWarning sw) {
while(sw != null) {
System.out.print("SQLWarning: State=" + sw.getSQLState()) ;
System.out.println(", Severity = " + sw.getErrorCode()) ;
System.out.println(sw.getMessage());
sw = sw.getNextWarning();
}
}
public static void main(String[] args) {
Connection con = null ;
DatabaseMetaData dbmd = null ;
try {
Class.forName(driver) ;
con = DriverManager.getConnection(url);
SQLWarning swarn = con. getWarnings() ;
if(swarn != null){
printSQLWarning(swarn) ;
}
dbmd = con.getMetaData() ;
System.out.println("\n----------------------------------------------------") ;
System.out.println("Database Name = " + dbmd.getDatabaseProductName()) ;
System.out.println("Database Version = " + dbmd.getDatabaseProductVersion()) ;
System.out.println("Driver Name = " + dbmd.getDriverName()) ;
System.out.println("Driver Version = " + dbmd.getDriverVersion()) ;
System.out.println("Database URL = " + dbmd.getURL()) ;
System.out.println("----------------------------------------------------") ;
} catch (SQLException se) {
printSQLException(se) ;
} catch(ClassNotFoundException e){
System.out.println("JDBC Driver " + driver + " not found in CLASSPATH") ;
}
finally {
if(con != null){
try{
con.close() ;
} catch(SQLException se){
printSQLException(se) ;
}
}
}
}
}
|
Этот класс -- все, что требуется для установления подключения при помощи JDBC к встроенной
базе данных Apache Derby, и именно это представлено в примере программы, откомпилированной и выполненной
в начале этой статьи. В основном новый код представляет собой включение пяти предложений
импорта в верхней части кода программы. Хотя можно использовать файлы
import java.sql.*, отдельный листинг для каждого предложения
импорта четко представляет JDBC-объекты, используемые
в приложении.
Это приложение включает функции обработки ошибок, показанные в листинге 4. Все
операции с базой данных включены в отдельный блок try ... catch,
включая операции с метаданными базы данных, представленные в листинге 3. Во многих приложениях баз данных
такая тесная связь между кодом приложения базы данных и самой базой данных избегается для упрощения управления и обслуживания приложения и базы данных. С учетом встроенных функций базы данных Apache Derby связь между
приложением и базой данных размыта, такое разделение не требуется задавать в жестком виде.
В этой статье было показано, как создать Java-приложение, подключенное к встроенной базе данных Apache Derby. В этом процессе для подключения к базе данных используется драйвер JDBC типа 4 из проекта Apache Derby, затем из базы данных извлекаются метаданные и подключение к базе данных закрывается. Также был описан способ обработки в Java-приложении предупреждений SQL и SQL-исключений, которые могут создаваться Derby. Следующие статьи будут основаны на методах, представленных в данной статье, и посвящены выполнению запросов к базе данных Derby и обработке результатов в Java-приложении.
| Описание | Имя | Размер | Метод загрузки |
|---|---|---|---|
| Derby SQL script for this article | derby9.zip | 1KB | HTTP |
Научиться
-
Оригинал статьи: Developing with Apache Derby -- Hitting the Trifecta: Java database development with Apache Derby, Part 1;
- Просмотрите другие статьи данной серии:
- В первой статье данной серии описана база данных Apache Derby и основы различных тем серии;
- Во второй статье серии описан инструмент
ijи показано, как его использовать для подключения к базе данных Apache Derby.
- Просмотрите различные интерактивные руководства проекта
Apache Derby, в которых содержится более подробная информация об использовании базы данных Derby;
- Просмотрите учебное руководство проекта Apache Derby, в котором подробно описано, как
загрузить и установить Apache Derby;
- Просмотрите различную документацию проекта Apache Derby, которая может оказаться более полезной для большинства начинающих разработчиков Java-приложений, использующих базу данных Apache Derby;
- Просмотрите официальный Web-сайт JDBC, содержащий множество сведений о правильном использовании
JDBC API;
- Просмотрите на сайте developerWorks в разделе проекта Apache Derby статьи, учебные руководства и другие ресурсы, которые помогут начать пользоваться Derby уже сегодня;
- Просмотрите подробную информацию о базе данных IBM® Cloudscape™
, созданную с использованием базового кода Apache Derby;
- Посетите раздел Open source сайта developerWorks, в котором размещено множество справочной информации, инструментальные средства и обновления проекта, позволяющие выполнять разработку приложений с помощью технологий с открытым исходным кодом и использовать их с продуктами IBM;
- Просмотрите все статьи по Apache и бесплатные учебные пособия, доступные в разделе Open source сайта developerWorks;
- Просмотрите книги по этой и другим техническим темам в книжном магазине Safari;
- Следите за техническими событиями и новыми материалами на Web-сайте developerWorks.
Получить продукты и технологии
-
Загрузите Apache Derby;
- Добавьте новизны в ваши следующие проекты разработки при помощи пробного ПО IBM, доступного в виде файлов для загрузки и на DVD.
Обсудить
- Примите участие в обсуждении материала на форуме.
- Примите участие в форуме по Open Source;
- Присоединяйтесь к сообществу developerWorks и участвуйте в блогах developerWorks.
Роберт Дж. Бруннер (Robert J. Brunner) занимается научными исследованиями в Национальном центре по приложениям для суперкомпьютеров и является старшим преподавателем астрономии в университете штата Иллинойс, город Урбана-Шампейн. Автор нескольких книг и множества статей и практических руководств на различные темы.