Java Database Connectivity (JDBC)
Приблизительно было подсчитано, что половина всего программного обеспечения использует клиент/серверные операции. Многообещающей возможностью Java была способность строить платформонезависимые клиент/серверные прилажения для работы с базами данных. Это стало возможным благодаря Java DataBase Connectivity (JDBC).
Одна из основных проблемм при работе с базами данных - это война особенностей между компаниями, разрабатывающими базы данных. Есть “стандартный” язык базы данных, Structured Query Language (SQL-92), но вы обычно должны знать с базой данных какого производителя вы работаете, несмотря на стандарт. JDBC предназначена для независимости от платформы, так что вам нет необходимости заботится о том, какую базу данных вы используете при программировании. Однако все еще возможно делать зависимые от производителя вызовы из JDBC, так что вы не ограничены тем, что вы должны делать.
В одном месте программистам может понадобиться использовать SQL имена типов в SQL выражении TABLE CREATE, когда они создают новую таблицу данных и определяют SQL тип для каждой колонки. К сожалению существуют значительные различия между SQL типами, поддерживаемыми различными продуктами баз данных. Различные базы данных, поддерживающие SQL типы с одинаковой семантикой и структурой, могут иметь различные имена типов. Большинство наиболее известных баз данных поддерживают типы данных SQL для больших бинарных значений: в Oracle этот тип называется LONG RAW, Sybase называет его IMAGE, Informix называет его BYTE, а DB2 называет го LONG VARCHAR FOR BIT DATA. Поэтому, если переносимость между базами данных является вашей целью, вы должны попробовать обойтись только основными идентификаторами SQL типов.
Переносимость - это такая возможность при написании книги, при которой читатели могут проверить примеры в любом неизвестном хранилище данных. Я попробовал написать такие примеры настолько переносимыми, насколько это возможно. Также вы должны иметь в виду, что специфичный для базы данных код был изолирован, чтобы можно было централизовать все изменения, которые вам необходимо будет выполнить, чтобы примеры заработали в вашей среде.
JDBC, как и многие API в Java, предназначен для упрощения. Вызовы методов, которые вы делаете, соответствует логическим операциям, которые вы думаете выполнить для сбора данных из базы данных: подключиться к базе данных, создать выражение и выполнить запрос, затем посмотреть результирующую выборку.
Для получения платформонезависимости, JDBC предоставляет менеджер драйверов (driver manager) который динамически использует все объекты драйверов, которые необходимы для опроса вашей базы данных. Так что если у вас есть базы данных от трех производителей, к которым вы хотите подсоединиться, вам нужно три различных объекта драйверов. Объекты драйверов регистрируют себя с помощью менеджера драйверов вл время загрузки, а вы можете принудительно выполнить загрузку, используя Class.forName( ).
Для открытия базы данных вы должны создать “URL базы данных”, котрый указывает:
Вся эта информация комбинируется в одну строку: “URL базы даных”. Например, для подключения черед подлежащий протокол ODBC к базе данных с идентификатором “people”, URL базы данных может быть:
String dbUrl = "jdbc:odbc:people";
Если вы подключаетесь по сети, URL базы данных будет содержать информацию для подключения, идентифицирующую удаленную машину и может быть немного пугающим. Вот пример работы с базой данных CloudScape, которую вызывает удаленных клиент, использующий RMI:
jdbc:rmi://192.168.170.27:1099/jdbc:cloudscape:db
Этот URL базы данных на самом деле содержит два jdbc вызова в одном. Первая часть “jdbc:rmi://192.168.170.27:1099/” использует RMI для создания соединения с удаленной машиной баз данных, следящей за портом 1099 по IP адресу 192.168.170.27. Вторая часть URL, “jdbc:cloudscape:db” передает более привычные установки, используя подлежащий протокол и имя базы данных, но это произойдет только после того, как первая секция установит соединение с удаленной машиной через RMI.
Когда вы готовы присоединиться к базе данных, вызовите статический (static) метод DriverManager.getConnection( ) и передайте ему URL базы данных и пароль для входа в базу данных. Обратно вы получите объект Connection, который затем вы можете использовать для опроса и манипуляций с базой данных.
Следующий пример открывает контактную информацию базы данных и ищет имя человека, переданное из командной строки. Он выбирает только имена людей, имеющий электронные адреса, затем печатает те из них, имя которых совпадает с заданным:
//: c15:jdbc:Lookup.java
// Поиск электронных адресов в
// локальной базе данных с помощью JDBC.
import java.sql.*;
public class Lookup { public static void main(String[] args) throws SQLException, ClassNotFoundException { String dbUrl = "jdbc:odbc:people"; String user = ""; String password = ""; // Загружаем драйвер (регистрируем себя)
Class.forName( "sun.jdbc.odbc.JdbcOdbcDriver"); Connection c = DriverManager.getConnection( dbUrl, user, password); Statement s = c.createStatement(); // SQL код:
ResultSet r = s.executeQuery( "SELECT FIRST, LAST, EMAIL " + "FROM people.csv people " + "WHERE " + "(LAST='" + args[0] + "') " + " AND (EMAIL Is Not Null) " + "ORDER BY FIRST"); while(r.next()) { // Регистр не имеет значения:
System.out.println( r.getString("Last") + ", " + r.getString("fIRST") + ": " + r.getString("EMAIL") ); } s.close(); // Закрываем ResultSet
} } ///:~
Вы можете увидеть создание URL базы данных, как это описано выше. В этом примере нет защитного пароля для базы данных, поэтому имя пользователя и пароль представлены пустыми строками.
Как только соединение установлено с помощью DriverManager.getConnection( ), вы можете использовать полученный объект Connection для создания объекта Statement, используя метод createStatement( ). С помощью Statement вы можете вызвать executeQuery( ), передав в него строку, содержащую SQL выражение стандарта SQL-92. (Скоро вы увидите как вы можете генерировать это выражение автоматически, так что вам не нужно много знать об SQL.)
Метод executeQuery( ) возвращает объект ResultSet, который является итератором: метод next( ) перемещает итератор на следующую запись в выражении или возвращает false, если достигнут конец результирующего множества. Вы всегда получите назад объект ResultSet от executeQuery( ), даже если результатом запроса является пустое множество (если так, исключение не возникает). Обратите внимание, чтовы должны вызвать next( ) прежде, чем попробовать прочесть любую запись. Если результирующее множество - пустое, этот первый вызов next( ) вернет false. Для каждой записи результирующего множества вы можете выбрать поля, используя (наряду с другими подходами) имя поля, как строку. Также обратите внимание, что регистр в имени поля игнорируется — это не так с базой SQL данных. Вы определяете тип, который получите, вызвав getInt( ), getString( ), getFloat( ) и т.д. В этом месте вы получаете данные из вашей базы данных в родном формате Java и можете делать с ними все, что хотите, используя обычный Java код.