![]() |
![]() |
![]() |
Использование JDBC В этом разделе рассматриваются основные принципы использования JDBC, некоторые технические аспекты, потенциальные проблемы и т. д. За дополнительными сведениями обращайтесь на сайт JDBC (http://java.sun.com/products/jdbc/), на котором всегда приводится самая свежая информация и имеются ссылки на множество полезных ресурсов. Подробные описания конкретных классов, методов и полей приведены в документации API, входящей в комплект поставки JDK. Обращайтесь к пакету java.sql. Классы JDBC представляют основные компоненты взаимодействия программы с SQL. У всех основных классов JDBC — Connection, Statement, ResultSet, Blob и Clob — имеются прямые аналоги в SQL. Кроме того, в JDBC включены вспомогательные классы — например, классы ResultsSetMetaData и DatabaseMetaData предназначены для работы с метаданными. В частности, они используются для получения информации о возможностях базы данных, для проверки типа результата запроса, в процессе отладки и просто в ситуациях, когда вы не располагаете информацией о данных, с которыми работаете. Интерфейс JDBC в PostgreSQL также содержит классы для работы с нестандартными расширениями PostgreSQL. К их числу относятся Fastpath, геометрические типы, большие объекты и классы, упрощающие сериализацию объектов Java в базе данных. Принципы использования JDBC В листинге 12.2 приведен пример использования объекта Connection, представляющего физическое подключение к базе данных. Объект Connection требуется для создания объектов Statement, при помощи которых в JDBC базе данных передаются команды SQL. Существует три разновидности объектов Statement: базовый класс Statement, классы PreparedStatement и CallableStatement. Объект Statement создается методом createStatement (листинг 12.3). Листинг 12.3. Создание объекта Statement Statement s = c.createStatement(): В листинге 12.3 создается объект класса Statement с именем s для объекта Connecti on с именем с. Далее созданный объект Statement может использоваться для выполнения запросов и обновлений базы данных. В классе Statement особенно важны два метода. Первый, executeQuery, получает один аргумент (код выполняемой команды SQL) и возвращает объект класса ResultSet, о котором речь пойдет ниже. Метод executeQuery предназначен для выполнения команд, возвращающих наборы данных, например запросов SELECT. Возвращаемый объект ResultSet представляет данные, полученные в ходе запроса. Пример выборки данных из базы booktown приведен в листинге 12.4. Листинг 12.4. Простая выборка в JDBC Statement s = nul 1: try { s = c.createStatementO; } catch (SQLException se) { System.out.printlnC'We got an exception while creating a statement:" + "that probably means we're no longer connected."): se.printStackTrace(); System, exit(l); } ResultSet rs = null: try { rs = s.executeQuery("SELECT * FROM books"); } catch (SQLException se) { System.out.printlnC'We got an exception while executing our query:" + "that probably means our SQL is invalid"): se.pnntStackTrace(): System.exit(l): } int index = 0: try { while (rs.nextO) { System.out.printlnC'Here's the result of row " + index++ + ":"): System.out.pri ntln(rs.getStri ng(1)): } } catch (SQLException se) { System.out.pnntlnC'We got an exception while getting a result:this " + "shouldn't happen: we've done something really bad."); se.pnntStackTrace(); System.exit(l): } Сначала мы создаем объект Statement, а затем используем метод executeQuery этого объекта для выполнения запроса SELECT * FROM books. Возвращенный запросом объект ResultSet используется для вывода полученной информации. Объект Resul tSet предоставляет основной интерфейс выборки из базы данных. Он обладает двумя основными возможностями: возможностью последовательного перебора полученных записей и возможностью возвращения значения заданного поля текущей записи. Принцип перебора такой же, как в стандартных перечислениях Java: вы начинаете перебор в позиции перед первым элементом и последовательно переходите к следующему элементу методом next. Метод next возвращает true в том случае, если объект ResultSet успешно перешел к следующей записи (то есть в итоговом наборе еще остались необработанные записи). Цикл whi I e в листинге 12.4 выводит значение первого поля каждой из возвращаемых записей. Если итоговый набор не содержит ни одной записи, первый же вызов next вернет fal se и программа ничего не выведет. Класс ResultSet может возвращать значения различных типов; в листинге 12.4 первое поле интерпретируется как строка (Stri ng). К счастью, все стандартные типы данных SQL могут быть представлены в строковом виде, поэтому независимо от типа данных вы всегда сможете получить значение первого поля и вывести его. Класс ResultSet содержит множество других методов, включая методы выборки для всех типов данных SQL и преобразования их к типам Java. За дополнительной информацией обращайтесь к описанию ResultSet в документации API. Другой важный метод, executeUpdate, тоже вызывается с одним аргументом — выполняемой командой SQL Различие между executeQuery и executeUpdate состоит в том, что метод executeUpdate предназначен для выполнения команд, изменяющих состояние данных в базе. Например, при вызове executeUpdate для команды CREATE, INSERT или UPDATE возвращается число типа int, определяющее количество модифицированных записей. В листинге 12.5 метод executeUpdate используется для вставки новой записи в таблицу books. Листинг 12.5. Простая вставка в JDBC Statement s - null: try { s = c.createStatement(): } catch (SQLException se) { System.out.printlnC'We got an exception while creating a statement:" + "that probably means we're no longer connected."): se.printStackTrace(); System.exlt(1): } int m = 0; try { m = s.executeUpdateC1 INSERT INTO books VALUES " + "(41472. 'Practical PostgreSGl'. 1212. 4)"): > } catch (SQLException se) { System.out.println("We got an exception while executing our query:" + "that probably means our SQL is invalid"): > se.printStackTrace(): System.exit(l): } System.out.println("Successfully modified " + m + " rows.\n"): Нетривиальные возможности JDBC Как упоминалось выше , кроме базового объекта Statement в JDBC существует два других типа объектов для представления команд: PreparedStatement и Cal lableStatement. Они будут описаны ниже. В данном подразделе также будет рассказано об объектах ResultsSetMetaData и DatabaseMetaData. С их помощью можно запросить у JDBC описание результатов запроса или базы данных. Возможность получения такой информации на стадии выполнения программы позволяет динамически выполнять команды SQL — даже такие, параметры которых были неизвестны на момент написания программы. Объект CallableStatement Объект CallableStatement позволяет выполнять хранимые процедуры в JDBC-co-вместимых базах данных. Лучшим источником информации по этому вопросу является сайт Sun Javasoft (http://java.sun.com/products/jdbc/), поскольку стандарт вызываемых команд (callable statements) изменяется и развивается и его практические применения зависят от версии Java и JDBC. Объект PreparedStatement Объект PreparedStatement представляет подготовленные (prepared) команды SQL, многократно выполняемые с разными исходными данными — например, если вам потребовалось вставить в таблицу несколько записей, одну за другой. Главное преимущество PreparedStatement заключается в том, что команда проходит предварительную компиляцию, что избавляет от затрат на повторную обработку команд SQL при каждом выполнении. Пример использования объекта PreparedStatement приведен в листинге 12.6. Листинг 12.6. Использование подготовленных команд в JDBC PreparedStatement ps = null: try { ps = c.prepareStatementC'INSERT INTO authors VALUES (?. ?. ?)"); ps.setlntd. 495): ps.setString(2. "Light-Williams"): ps.setStringO. "Corwin"): } catch (SQLException se) { System.out.printlnC"We got an exception while preparing a statement:" + "Probably bad SQL."): se.printStackTrace(); System.exit(l); } try { ps.executeUpdate(): } catch (SQLException se) { System.out.printlnC'We got an exception while executing an update:" + "possibly bad SQL. or check the connection."): se.pnntStackTrace(): System.exit(l): } Как видно из листинга, подготовленная команда выглядит вполне привычно, разве что все переменные величины заменяются в ней вопросительными знаками (?). Присваивание выполняется методами класса PreparedStatement (setlnt, setString и т. д.). Выбор метода для каждого поля зависит от типа данных этого поля. Объекты PreparedStatement удобны тем, что они обеспечивают автоматическое преобразование типов данных Java в типы SQL. Например, при переходе к типу text вам не нужно беспокоиться об экранировании символов или кавычках. Обратите внимание: первый аргумент метода set идентифицирует номер позиции переменной (вопросительного знака), которой присваивается значение. Единица означает первый вопросительный знак, двойка — второй и т. д. Другая сильная сторона PreparedStatement связана с тем, что объект можно снова и снова использовать с новыми данными, не создавая нового объекта Statement для каждого набора параметров. Конечно, такой подход более эффективен, поскольку он ограничивается созданием одного объекта, а новые значения переменных задаются методами set. ResultSetMetaData У JDBC можно запросить подробную информацию об итоговом наборе запроса. Класс Resul tsSetMetaData возвращает описание объекта Resul tSet, полученного при вызове executeQuery. В нем содержится информация о количестве полей, типе данных, именах полей и т. д. Из всех методов класса ResultSetMetaData чаще всего используются методы getCol umnName и getCol umnTypeName. Они возвращают соответственно имя поля и имя его типа данных в виде значения типа String. ПРИМЕЧАНИЕ Не путайте метод getCol umnType с методом getCol umnTypeName. Метод getCol umnType возвращает значение типа int, соответствующее внутреннему идентификатору типа данных в JDBC, тогда как getCol umnTypeName возвращает имя типа в формате String. Использование JDBC 363 В листинге 12.7 класс ResultSetMetaData используется для получения имени и типа данных первого поля объекта ResultSet с именем rs. Программа является логическим продолжением листинга 12.4, в котором был создан объект rs. Даже если отвлечься от соображений эффективности, механизм PreparedStatement гораздо надежнее подготовки нескольких команд в объектах Statement. Листинг 12.7. Использование объекта ResultSetMetaData ResultSetMetaData rsmd - null: try { rsmd = rs.getMetaData(): } catch (SQLException se) { System.out.printlnC'We got an exception while getting the metadata:" + "check the connection."): se.printStackTrace(); System.exit(l): } String columnName = null. columnType = null: try { columnName = rsmd.getColumnName(1): columnType - rsmd.getColumnTypeName(l): } catch (SQLException se) { System.out.printlnC'We got an exception while getting the column name:" + "check the connection."): se.printStackTrace(): System.exit(l): } System.out.printC'The name of the first column is: '"): System.out.print(columnName); System.out.printlrK.....): System.out.printC'The data type of the first column is: "): System.out.println(columnType): Класс ResultSetMetaData содержит много других полезных методов. Описания приведены в документации JDK API. DatabaseMetaData Наконец, класс DatabaseMetaData предназначен для получения информации о базе данных, с которой вы работаете. В частности, он позволяет получить ответ па перечисленные ниже вопросы.
В листинге 12.8 объект DatabaseMetaData используется для получения у драйвера JDBC имени пользователя, с которым было создано подключение, и URL-адреса базы данных. Листинг 12.8. Использование объекта DatabaseMetaData DatabaseMetaData dbmd = null: try { dbmd = c.getMetaData(): } catch (SQLException se) { System.out.printlnC'We got an exception while getting the metadata:" + " check the connection."): se.printStackTrace(): System.exit(l): } String username = null: try { username = dbmd.getUserName(): } catch (SQLException se) { System.out.printlnC'We got an exception while getting the username:" + "check the connection."); se.printStackTraceO; System.exit(l): } String url = null; try { url = dbmd.getURLO; } catch (SQLException se) { System.out.printlnC'We got an exception while getting the URL:" + "check the connection."); se.printStackTrace(); System.exit(l): } System.out.printlnC'You are connected to '" + url + '" with user name '" + username + .....); Как было сказано выше, лучшим источником информации о других методах DatabaseMetaData является документация JDK API. |
![]() |
![]() |
![]() |