Статьи

Азбука JDBC, часть 3 — API JDBC

В этой серии статей из нашей серии часто задаваемых вопросов о JDBC мы рассмотрим развитие API JDBC от версии 2.0 до 4.0 и рассмотрим, как выполнять некоторые распространенные задачи, такие как программная вставка и удаление строк, вставка необработанных данных (таких как изображения) в базы данных и настройки свойств драйвера JDBC.

Прочитайте другие части в серии часто задаваемых вопросов JDBC DZone :

Что нового в API JDBC 2.0?           

JDBC 2.0 представлял разделение JDBC API на основной пакет и стандартное расширение. С базовым пакетом JDBC, выполняющим функциональные возможности, присутствующие в JDBC 1.2 — который предшествовал JDBC 2.0 — гарантирует обратную совместимость и стандартный пакет расширений, содержащий новые функциональные возможности, распространяемые отдельно от JDK.

Новая функциональность стандартного пакета расширений, размещенного в пространстве имен Java javax.sql, включает: поддержку JNDI для источников данных JDBC, пул соединений, наборы строк и распределенные транзакции.

Что нового в API JDBC 3.0?

JDBC 3.0 представлял собой включение стандартного пакета расширений (то есть javax.sql) в сам JDK, а также дополнительные улучшения в общей функциональности API.

Среди улучшений, представленных в JDBC 3.0 по сравнению с JDBC 2.0: улучшенная организация пула соединений, расширенная поддержка функций SQL99 — последнее из которых является отраслевым стандартом баз данных — обновленные API метаданных, именованные параметры в операторах Callable для поддержки имен параметров в хранимые процедуры, а также новые и обновленные типы данных.

Новые функции JDBC 3.0 включают: получение автоматически сгенерированных ключей, поддержку интеграции для архитектуры Java Connector Architecture (JCA), возможность удержания ResultSet, пул PreparedStatement, а также точки сохранения для транзакций.

Что нового в API JDBC 4.0?

JDBC 4.0 представляет последнюю версию API JDBC и является частью JDK 6.0 (то есть Java SE 6).

Среди улучшений, представленных в JDBC 4.0 по сравнению с JDBC 3.0: улучшенное управление драйверами и соединениями, расширенная поддержка функций SQL2003 — последний из которых является отраслевым стандартом баз данных и преемником SQL99 — улучшенная обработка исключений, а также новые и обновленные типы данных.

Новые функции JDBC 4.0 включают: поддержку SQLXML и XML, а также поддержку преобразования национальных наборов символов — поддерживаются с помощью SQL2003.

Что возвращает Class.forName?              

Он возвращает объект Class, связанный с классом или интерфейсом с заданным именем строки. Class.forName позволяет динамически загружать код класса без необходимости знать фактическое имя класса до времени выполнения. В контексте JDBC Class.forName обычно используется для загрузки класса, соответствующего конкретному драйверу JDBC, что позволяет динамически загружать основной класс драйвера JDBC (например, Class.forName («com.mysql.jdbc.Driver»)) ,

Обратите внимание, что Class.forName является конструкцией, используемой при выполнении соединения через DriverManager, и его функциональность больше не требуется, если используется драйвер, совместимый с API JDBC 4.0 (т. Е. JDBC 4.0 автоматически выполняет обязанности Class.forName).

Какие объекты JDBC генерируют SQLWarnings?              

SQLWarnings генерируется из объектов Connection, Statement и ResultSet. Доступ к SQLWarnings обеспечивается методами Connection.getWarnings (), Statement.getWarnings (), ResultSet.getWarnings () соответственно.

Каковы общие задачи JDBC?              

Общие задачи JDBC:

  •  Выполнение соединения с базой данных — через объект Connection.
  •  Выполнение операции с базой данных (т.е. создание, чтение, обновление, удаление) — через объект Statement.
  • Получение результатов операции над базой данных — через объект ResultSet.

Каковы два основных компонента JDBC?              

  •  API JDBC, используемый разработчиками приложений для подключения к постоянной системе хранения.
  •  JDBC SPI (интерфейс поставщика услуг), используемый постоянными производителями хранилищ для обеспечения подключения к JDBC (т. Е. Посредством создания драйверов JDBC).

Что такое источник данных JDBC?

Источник данных JDBC — это объект, используемый для установления соединения с постоянной системой хранения. Это предпочтительный способ установки соединения вместо более старого подхода DriverManager.

Какие типы объектов DataSource указаны в дополнительном пакете?

  •   Basic — Предоставляет стандартный объект подключения.
  •   Pooled — предоставляет пул соединений и возвращает соединение, управляемое пулом.
  •   Распределенный — обеспечивает соединение, которое может участвовать в распределенных транзакциях.

Обратите внимание, что дополнительный пакет является частью API JDBC 2.0, в более поздних версиях — JDBC 3.0 и JDBC 4.0 — дополнительный пакет является частью основного API JDBC (т.е. JDK Java)

Как вставить и удалить строку программно?              

Чтобы вставить или удалить строку программным путем, сначала необходимо получить набор строк, для которых вы хотите удалить конкретную строку или вставить новую строку.

Для этой цели используется объект ResultSet, используемый в сочетании со стандартным оператором JDBC, как показано ниже:

    Connection conn = ds.getConnection();
Statement stmt = conn.createStatement();
ResultSet rset = stmt.executeQuery("SELECT * FROM NOTES");

В этом случае объект ResultSet представляет запрос для всех строк, принадлежащих таблице NOTES.

Для программного удаления строки используются два метода, принадлежащих объекту ResultSet: absolute () и deleterow (). Метод absolute () используется для перемещения курсора ResultSet () в определенную позицию, а deleteterow () — для удаления строки выбранного курсора. Например, следующий фрагмент удаляет вторую строку ResultSet, а также строку из базы данных:

     rset.absolute(2);
rset.deleteRow();

Чтобы добавить строку программно, используются методы moveToInsertRow () и insertRow (), а также методы updateXXX — все они принадлежат объекту ResultSet и где XXX представляют типы данных (например, String, BigDecimal, Int и т. Д.). Например, следующий фрагмент добавляет строку к объекту ResultSet, а также к базе данных.

     rset.moveToInsertRow(); 
rset.updateInt(1, 7777);
rset.updateString(2, "JDBC tips");
rset.updateString(3, "D.Rubio");
rset.insertRow();

 

MoverToInsertRow () — это метод, который перемещает курсор ResultSet в специальную строку, предназначенную для вставки строк. Когда курсор находится в этой позиции (т.е. вставьте строку), поля строки заполняются значениями вставки. UpdateInt (1, 777) указывает на заполнение первых столбцов строки целым числом 777, updateString указывает на заполнение второго столбца строки строкой «JDBC tips» и т. Д. В полях специальной строки (т.е. строки вставки) заполняется метод insertRow () для фиксации строки как в объекте ResultSet, так и в базе данных.

Как вставить файл изображения (или другие необработанные данные) в базу данных? (То же, что и: Как вставить .jpg в базу данных mySQL?) 

Чтобы вставить файл изображения или любой другой тип необработанных данных (например, двоичные данные), сначала необходимо убедиться, что база данных способна хранить данные этого типа. Для этой цели большинство коммерческих баз данных поддерживают тип данных BLOB (большой двоичный объект). Таким образом, гарантируя наличие таблицы базы данных со столбцом BLOB, следующий фрагмент кода иллюстрирует процесс вставки:

     // Connection object defined 
PreparedStatement pstmt = conn.prepareStatement("INSERT INTO logos VALUES (?,?)");
pstmt.setInt(1,1000);
File fBlob = new File("logo.jpg");
FileInputStream is = new FileInputStream(fBlob);
pstmt.setBinaryStream (2,is,(int)fBlob.length());
pstmt.execute();

Первая строка создает объект JDBC PreparedStatement для вставки строки в таблицу с именем logos, причем два столбца таблицы представляют целое число и BLOB. Обратите внимание на использование синтаксиса «?» в качестве заполнителя для каждого значения. Далее вы можете наблюдать вызов метода setInt (), который принадлежит объекту PreparedStatement, указывающего на вставку целочисленного значения 1000 в позицию 1.

Затем, чтобы вставить файл изображения или любой другой тип необработанных данных (например, двоичные данные), вам нужно создать поток из его содержимого. Для этого вы полагаетесь на класс Java File для чтения файла из файловой системы (например, новый файл («logo.jpg»)), после чтения вы используете класс FileInputStream для генерации фактического потока из объекта File. Когда это сделано, вызывается метод setBinaryStream (), принадлежащий объекту PreparedStatement, чтобы назначить поток в качестве параметра вставки. Значения, передаваемые setBinaryStream в этом случае: «2» представляет позицию 2, «is» представляет двоичный поток, а длина двоичного потока — «fBlob.length ()» — взята из родительского объекта File.

Наконец, вызывается оператор execute () класса PreparedStatement, чтобы зафиксировать вставку в базу данных.

Как записать греческие (или другие символы, не входящие в ASCII / 8859-1) в базу данных?              

Чтобы вставить греческие (или другие символы, отличные от ASCII / 8859-1), сначала необходимо убедиться, что база данных способна хранить символы этого типа. После установки создается база данных с поддержкой символов этого типа (т. Е. Языков), это делается потому, что поддержка специальных символов может привести к накладным расходам как с точки зрения дискового пространства, так и обработки.

Если у вас есть база данных, которая поддерживает греческие (или другие символы, не входящие в ASCII / 8859-1), вы выполнили единственное требование для вставки закодированных символов в базу данных. Преобразование символов из стандартной кодировки Java String в кодировку базы данных полностью выполняется драйвером JDBC независимо от кодировки JVM или самого объекта String.

Как запретить значения NULL в таблице?              

Запрещение пустых значений в таблице не особенно подходит для JDBC, поскольку включает в себя проверку значений вставки. Поэтому запрещение пустых значений лучше всего делать либо до попытки вызова JDBC — с использованием кода Java и отклонения нулевого значения до вставки (то есть на уровне приложения) — либо после попытки вызова JDBC — применения ненулевого ограничения на таблица базы данных (т.е. на уровне базы данных путем создания столбца как NOT NULL)

Как извлечь операторы SQL, необходимые для перемещения всех таблиц и представлений из существующей базы данных в другую базу данных?              

 Структуры таблиц и представлений от поставщиков баз данных очень специфичны, поэтому не существует стандартного способа их получения через JDBC. Однако процесс получения всех данных из базы данных является обычной процедурой, часто называемой «дампом», которая может быть достигнута с использованием стандартных запросов JDBC. Например, MySQL поддерживает оператор «SHOW CREATE TABLE», который выводит SQL-операторы, необходимые для перестройки таблицы, Oracle, с другой стороны, имеет таблицы метаданных, которые содержат информацию, которую можно использовать для перестройки таблиц и представлений. Эти подходы, специфичные для каждого поставщика, могут быть выполнены с использованием стандартных запросов JDBC.

Одним из элементов функциональности, который обсуждался экспертной группой JDBC, является идея массовой загрузки. Некоторые поставщики драйверов уже включают механизмы массовой загрузки в свой набор драйверов JDBC, так что вы можете легко и быстро перемещать таблицы из одной базы данных в другую, что значительно улучшит перемещение всей базы данных.

Проект, который вы, возможно, захотите посмотреть, если ваши таблицы и представления для переноса данных от одного поставщика базы данных к другому — это плагин DBCopy, доступный по адресу http://dbcopyplugin.sourceforge.net/.

Как пользовательский RowSetReader вызывается из CachedRowSet?              

 RowSetReader должен быть зарегистрирован в CachedRowSet следующим образом:

     CachedRowSet.setReader(javax.sql.RowSetReader reader)

 

После назначения вызов CachedRowSet.execute () вызовет RowSetReader.

Каков синтаксис JDBC для использования литерала даты или переменной в стандартном операторе?              

Во-первых, имейте в виду, что использование PreparedStatement — вместо Statement — защищает вас от ряда синтаксических ошибок, включающих литералы даты и переменные. Однако, если вы предпочитаете вставлять литералы даты, используя объект Statement, вы можете использовать следующий синтаксис: {d ‘yyyy-mm-dd’}.

Используя объекты Statement с литералами даты или переменными, единственное, о чем вам нужно быть осторожным, это смешивать одинарные кавычки (‘) с двойными кавычками («). Например, следующий оператор иллюстрирует строку запроса JDBC, содержащую литерал даты: 

      String sqlQuery= "SELECT * FROM articles WHERE  publishingdate = {d '2001-10-21'}" 

Следующий оператор иллюстрирует строку запроса JDBC, содержащую переменную даты:

     java.sql.Date pDate; 
// Set date
String sqlQuery = "SELECT * FROM articles WHERE publishingdate = {d '" + pDate + "'}"

Когда оператор выбора SQL не возвращает никаких строк, генерируется ли SQLException?              

Нет. Результаты оператора выбора SQL присваиваются объекту ResultSet, который может содержать или не содержать строки. Чтобы определить, не возвращает ли оператор SQL SQL какие-либо строки, вам нужно полагаться на вспомогательные методы ResultSet (например, next ()).

Какие скалярные функции можно ожидать от поддержки JDBC?              

Хотя спецификация JDBC определяет базовый набор скалярных функций — с использованием escape-синтаксиса в виде {fn имя_функции (аргументы)} (например, {fn concat («JDBC», «Tipos»)}) — поддержка этих типов функций в значительной степени зависит от используемого вами драйвера JDBC. Вы должны проконсультироваться с драйвером JDBC для получения полного списка поддерживаемых скалярных функций.

Почему JDBC не принимает URL вместо строки URL?              

JDBC использует специальный синтаксис для указания URL-адресов подключения, который отличается от стандартных URL-адресов (т. Е. Интернет-адресов). Синтаксис JDBC следующий: jdbc: [тип_драйвера]: [имя пользователя / пароль] / [имя_базы_данных], где [тип_драйвера] и [ имя пользователя / пароль] являются необязательными параметрами. Например, чтобы подключиться к базе данных Oracle с помощью ее тонкого драйвера, вы должны использовать следующий синтаксис: jdbc: oracle: thin: @database_name. Другой пример, состоящий из использования базы данных MySQL, будет использовать следующий синтаксис: jdbc: mysql: // localhost: 3306 / database_name. Как вы можете заметить, синтаксис зависит от производителя базы данных и драйвера, в дополнение к отличным стандартным URL-адресам (то есть интернет-адресам), состоящим из [protcol]: // [host] / [path].

Где я могу найти информацию, рамки и пример источника для написания драйвера JDBC?              

Место для начала — спецификация JDBC . Как только вы это сделаете, я рекомендую исследовать конкретного поставщика базы данных, для которого вы хотите реализовать драйвер JDBC, для документации по собственным библиотекам и API для взаимодействия с их продуктом. Наконец, детальный взгляд на интерфейс поставщика услуг (SPI) JDBC, который детализирует требования к отображению между JDBC и интерфейсом базы данных.

Как установить свойства для драйвера JDBC и где хранятся свойства?           

Свойства JDBC могут быть установлены во многих местах. Для начала, они могут быть жестко закодированы как String внутри класса приложения, а затем использованы для установления соединения с базой данных. Однако в целях обслуживания они также могут быть определены в текстовом файле (то есть в одном месте) и считаны из различных классов приложений с использованием стандартного класса свойств Java. Кроме того, другой вариант определения свойств драйвера JDBC находится внутри файлов конфигурации веб-контейнера (например, web.xml), последний из которых является почти нормой для приложений Java EE.