1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/wizardforcel-thinking-in-java-zh

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
В этом репозитории не указан файл с открытой лицензией (LICENSE). При использовании обратитесь к конкретному описанию проекта и его зависимостям в коде.
Клонировать/Скачать
15.7 用JDBC连接数据库.md 36 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
Отправлено 11.03.2025 09:15 d56454c

15.7 Подключение к базе данных с помощью JDBC

По оценкам, около половины всех проектов разработки программного обеспечения включает клиент/серверные операции. Java гарантирует отличную способность создавать платформенно-независимые приложения клиент/сервер с использованием баз данных. В Java 1.1 эта возможность была реализована через Java Database Connectivity (JDBC).

Одним из главных проблем с базами данных является борьба между компаниями за доминирование в стандартах. Хотя существует "стандарт" языка запросов к базам данных, известного как Structured Query Language (SQL-92), обычно требуется точно знать, с какой компанией баз данных вы работаете, чтобы избежать проблем, даже если используется так называемый "стандарт". JDBC ориентирован на независимость от платформы, поэтому при программировании нет необходимости заботиться о том, какой именно продукт базы данных используется. Однако всё ещё возможно вызывать специфичные для некоторых компаний баз данных функции из JDBC, поэтому следует действовать осторожно.

Как и многие API в Java, JDBC стремится к простоте использования. Вызовы методов, которые мы делаем, соответствуют обычной процедуре получения данных из базы данных: соединение с базой данных, создание запроса и его выполнение, а затем работа с набором результатов.Для реализации этой "платформенно-независимости", JDBC предоставляет "управление драйверами", которое может динамически управлять всеми объектами драйверов, необходимыми для выполнения запросов к базе данных. Поэтому, если вам нужно подключаться к различным типам баз данных, разработанным тремя разными компаниями, вам потребуются три отдельных объекта драйверов. Объекты драйверов регистрируются автоматически при загрузке "управления драйверами" и могут быть загружены принудительно с помощью Class.forName().

Чтобы открыть базу данных, необходимо создать "URL базы данных", который должен указывать на следующие три аспекта:

(1) Использование jdbc, чтобы указать использование JDBC.

(2) "Подпротокол": имя драйвера или название механизма подключения к базе данных. Поскольку дизайн JDBC был вдохновлен ODBC, первым возможным подпротоколом является "jdbc-odbc мост", который можно указать ключевым словом odbc.(3) Идентификатор базы данных: меняется в зависимости от используемого драйвера базы данных, но обычно предоставляется логическое имя, которое базовое программное обеспечение управления базами данных отображает (соответствует) к физическому каталогу, содержащему таблицы данных. Чтобы ваш идентификатор базы данных имел какой-либо смысл, он должен быть зарегистрирован с помощью вашего программного обеспечения управления базами данных, и процесс регистрации зависит от используемой платформы. Все эти данные объединены в одну строку, называемую «строкой подключения к базе данных». Например, если требуется подключиться к базе данных с именем people через протокол ODBC, строка подключения может выглядеть следующим образом:```java String dbUrl = "jdbc:odbc:people";


Если соединение осуществляется через сеть, то строка подключения должна также содержать информацию, которая позволяет идентифицировать удаленную машину.

После подготовки строки подключения можно вызвать статический метод `DriverManager.getConnection()`, передав ему строку подключения, имя пользователя и пароль для доступа к базе данных. Возвращаемым значением будет объект типа `Connection`, который используется для выполнения запросов и манипулирования данными в базе данных.

Например, этот код открывает базу данных с контактной информацией и выполняет запрос для получения фамилии (Last Name) указанного человека на основе аргументов командной строки. Он выбирает только те записи, где есть адрес электронной почты, и выводит все найденные записи:

```java
//: Lookup.java
// Поиск адресов электронной почты в локальной базе данных с помощью JDBC
import java.sql.*;
``````java
public class Lookup {
  public static void main(String[] args) {
    String dbUrl = "jdbc:odbc:people";
    String user = "";
    String password = "";
    try {
      // Загрузка драйвера (регистрация происходит автоматически)
      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
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}
///:~

```Как видно, процесс создания строки подключения полностью аналогичен тому, что был описан ранее. В данном примере база данных не защищена паролями, поэтому имя пользователя и пароль являются пустыми строками. После того как соединение создано с помощью DriverManager.getConnection(), можно создать объект `Statement` (выражение) с использованием метода `createStatement()`. Затем с этим объектом `Statement` можно вызвать метод `executeQuery()`, передав ему строку, содержащую SQL-запрос в соответствии с стандартом SQL-92 (вскоре вы узнаете, как автоматически создавать такие запросы, поэтому нет необходимости знать больше о SQL здесь). Метод `executeQuery()` возвращает объект типа `ResultSet`, который очень похож на итератор: метод `next()` перемещает итератор к следующей записи в запросе; если конец набора записей достигнут, то возвращается значение `null`. Мы можем быть уверены, что метод `executeQuery()` вернет объект типа `ResultSet`, даже если результат запроса пуст (то есть, не будет выброшено исключение). Важно отметить, что перед попыткой считывания данных записей следует вызвать метод `next()`. Если набор записей пуст, первый вызов метода `next()` вернет значение `false`. Для каждой записи в наборе можно использовать имя поля как строки (хотя существуют и другие способы выбора полей); также стоит заметить, что регистр букв в названии полей значения не имеет — SQL базы данных не различают регистр символов.Чтобы определить тип возвращаемого значения, можно использовать методы `getString()`, `getFloat()` и так далее. На этом этапе мы уже получили данные нашей базы данных в примитивном формате Java, и теперь можем использовать Java-код для выполнения любых действий, которые нам необходимы.## 15.7.1 Как запустить пример

Что касается JDBC, сам код довольно легко понять. Самое сложное заключается в том, чтобы сделать его работоспособным на вашей конкретной системе. Это может быть запутано из-за необходимости знать, как правильно загрузить JDBC-драйвер, а также как настроить базу данных с помощью вашего программного обеспечения управления базами данных.

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

Шаг 1: Найти JDBC-драйвер

Приведённый выше код содержит следующую строку:

Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
```Эта строка может создать впечатление наличия определённой структуры каталогов, но не позволяйте себе быть обманутым этим. В моём установочном образце JDK 1.1 нет файла `JdbcOdbcDriver.class`. Поэтому, если вы попробуете найти этот файл после просмотра этого примера, вы просто потратите время зря. Другие примеры используют псевдонимы, такие как `myDriver.ClassName`, но они не помогают пользователям. В действительности, данная строка для загрузки JDBC-ODBC драйвера (на самом деле, единственный драйвер, предоставляемый вместе с JDK 1.1) встречается во многих местах в онлайн-документации (особенно на странице, помеченной как "JDBC-ODBC Bridge Driver"). Если эта загрузка не работает, возможно, название было изменено при выпуске новых версий Java; тогда следует поискать новое описание в онлайн-документации. Если загрузка драйвера выполнена с ошибками, будет выброшено исключение. Для проверки корректной работы команды загрузки драйвера временно закомментируйте все строки от этой команды до блока `catch`. Если при запуске программы исключений не возникает, значит загрузка драйвера прошла успешно.### Шаг 2: Настройка базы данных

Аналогично, мы ограничиваемся работой в окружении Windows 32-bit; вам может потребоваться исследовать вашу собственную операционную систему, чтобы найти подходящий метод конфигурации для вашего платформенного окружения.

Сначала откройте панель управления. В ней могут находиться два значка, содержащих слово "ODBC". Вам следует выбрать "32-bit ODBC", так как другой вариант предназначен для обратной совместимости с программами 16-bit и никак не влияет на работу JDBC. После двойного щелчка на значке "32-bit ODBC" вы должны видеть диалоговое окно со вкладками, где каждая вкладка представляет собой различные типы источников данных, такие как "User DSN", "System DSN", "File DSN" и т.д. Здесь "DSN" означает "DataSource Name". Все они связаны с мостом JDBC-ODBC, но наиболее важным местом для настройки базы данных является "System DSN". Тем не менее, для тестирования своей конфигурации и создания запросов также требуется настроить "File DSN". Это позволяет инструменту Microsoft Query (предназначенному для использования вместе с Microsoft Office) правильно находить ваши базы данных. Обратите внимание, что некоторые компании также создали свои собственные инструменты для запросов.Наиболее интересной базой данных является та, которую мы уже использовали ранее. Основная поддержка ODBC включает множество различных форматов файлов, в том числе специализированные форматы, используемые различными компаниями, такими как dBASE. Однако она также поддерживает простой "CSV" (comma-separated values) формат, который практически любой инструмент для работы с данными может генерировать. В данном примере я выбрал свой файл базы данных `people`. Это база данных, которую я поддерживаю годами, используя различные средства управления контактами. Я экспортировал её в CSV-файл (обычно имеющий расширение `.csv`, то же самое можно сделать при экспорте адресной книги Outlook Express). В разделе "File DSN" я нажимаю кнопку "Add", выбираю текстовый драйвер (Microsoft Text Driver), предназначенный для управления CSV-файлами, а затем отключаю опцию "Use current directory", чтобы иметь возможность указывать директорию при экспорте файла данных. При выполнении этих задач фактический файл не указывается, а лишь директория. Это связано с тем, что база данных обычно состоит из нескольких файлов в одной директории (хотя могут использоваться и другие формы). Каждый файл обычно содержит отдельную "таблицу данных", и SQL-запросы могут выдавать результаты, объединяющие данные из нескольких таблиц (это называется "объединением" или `JOIN`).База данных, содержащая только одну таблицу (как в данном случае), часто называется "плоской базой данных". Для большинства задач, если простое хранение и получение данных становится недостаточным, требуется использование нескольких таблиц данных. Объединяя эти таблицы, можно получить желаемый результат. Такие базы данных называются "относительными" базами данных. ### Шаг 3: Тестирование конфигурацииДля тестирования конфигурации необходимо проверить, может ли программа "видеть" базу данных. Конечно, можно просто запустить вышеупомянутую демонстрационную JDBC-программу и добавить следующие строки:

```java
Connection c = DriverManager.getConnection(dbUrl, user, password);

Если возникает исключение, это указывает на ошибку в вашей конфигурации.

Однако сейчас очень важно использовать автоматический генератор запросов. Я использую Microsoft Query, который прилагается к Microsoft Office, но вы можете выбрать любой другой. Генератор запросов должен знать местоположение базы данных, а Microsoft Query требует от меня зайти в ODBC Administrator и создать новый пункт в разделе "File DSN". Также следует указать текстовый драйвер и каталог, где хранится база данных. Хотя этот пункт можно назвать любым образом, лучше всего использовать ту же самую название, что и в "System DSN".

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

Шаг 4: Создание своего SQL-запросаСозданный мной с помощью Microsoft Query запрос показывает, что целевая база данных существует и правильно организована, а также автоматически генерирует SQL-код для его вставки в мой Java-программ. Я хочу, чтобы этот запрос проверял наличие записи с тем же "фамилией" (Last Name), которую я ввожу в командной строке при запуске программы Java. В качестве начальной точки я ищу свою фамилию Эккель. Кроме того, я хочу видеть только те записи, которые имеют соответствующий адрес электронной почты. Шаги создания этого запроса следующие:(1) Начните новый запрос и используйте помощник по созданию запросов (Query Wizard). Выберите базу данных people (эквивалентно открытию соединения с базой данных с помощью подходящего URL).

(2) Выберите таблицу people в базе данных. Из этой таблицы выберите столбцы FIRST, LAST и EMAIL.

(3) В разделе "Фильтрация данных" (Filter Data) выберите LAST и установите значение равно (equals) с параметром Eckel. Установите флажок "И" (And).

(4) Выберите EMAIL и установите значение "не равно пустому значению" (not null).

(5) В разделе "Сортировка по" (Sort By) выберите FIRST.

Результат запроса покажет вам, получаете ли вы то, что ожидали. Теперь нажмите кнопку SQL. Без вашего участия правильный SQL-код сразу появится, и вы сможете скопировать и вставить его. Для данного запроса соответствующий SQL-код выглядит так:

SELECT people.FIRST, people.LAST, people.EMAIL
FROM people.csv AS people
WHERE (people.LAST = 'Eckel') AND
(people.EMAIL IS NOT NULL)
ORDER BY people.FIRST

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

Шаг 5: Изменение и вставка запросаОбратите внимание, что приведённый выше код отличается от используемого в программе. Это связано с тем, что инструмент для создания запросов ограничивает все имена столбцов, даже если используется всего одна таблица (если бы использовались несколько таблиц, эти ограничения помогли бы избежать конфликта между одноимёнными столбцами из разных таблиц). Поскольку этот запрос требует использования только одной таблицы, можно удалить ограничители "people" из большинства имен, как показано ниже:```sql

SELECT FIRST, LAST, EMAIL FROM people.csv AS people WHERE (LAST = 'Eckel') AND (EMAIL IS NOT NULL) ORDER BY FIRST


Кроме того, мы не хотим "жестко закодировать" это имя, чтобы программа могла искать любое указанное имя, а не только конкретное. Поэтому следует сделать необходимые изменения и преобразовать SQL-запрос в динамически создаваемую строку. Пример такого запроса представлен ниже:

```java
"SELECT FIRST, LAST, EMAIL " +
"FROM people.csv AS people " +
"WHERE " +
"(LAST = '" + args[0] + "') " +
"AND (EMAIL IS NOT NULL) " +
"ORDER BY FIRST";

SQL также позволяет вставлять значения в запрос через процедуры (Procedures), что делает выполнение запроса более эффективным. Однако для наших экспериментальных операций с базами данных и некоторых начальных приложений использование Java для создания строк запросов уже является хорошим решением.

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

15.7.2 Графический интерфейс для программы поиска

Лучшим подходом будет постоянное поддержание программы в активном состоянии, так что для поиска чего-либо достаточно просто переключиться на неё и ввести нужное имя. Ниже представлена программа, которая представляет собой "приложение/апплет", содержащее функцию автозаполнения имени, поэтому полное указание фамилии не требуется для получения информации:```java //: VLookup.java // Графическая версия Lookup.java import java.awt.; import java.awt.event.; import java.applet.Applet; import java.sql.*;


```markdown
публичный класс VLookup расширяет Applet {
    строка dbUrl = "jdbc:odbc:people";
    строка user = "";
    строка password = "";
    Утверждение s;
    Поле для ввода текста searchFor = новое поле для ввода текста(20);
    метка completion =
        новая метка("                        ");
    Область для текста results = новая область для текста(40, 20);
    публичный void init() {
        searchFor.addTextListener(новый SearchForL());
        панель p = новая панель();
        p.add(новую метку("Фамилия для поиска:"));
        p.add(searchFor);
        p.add(completion);
        установить макет(new BorderLayout());
        добавить(p, BorderLayout.NORTH);
        добавить(results, BorderLayout.CENTER);
        попробуй {
            // Загрузите драйвер (зарегистрирован сам)
            Класс.forName(
                "sun.jdbc.odbc.JdbcOdbcDriver");
            Соединение c = DriverManager.getConnection(
                dbUrl, user, password);
            s = c.createStatement();
        } catch(Исключение e) {
            results.setText(e.getMessage());
        }
    }
    внутренний класс SearchForL реализует TextListener {
        публичный void textValueChanged(Текстовое событие te) {
            Результат выполнения запроса r;
            если(длина строки searchFor.getText()) == 0) {
                completion.setText("");
                results.setText("");
                вернуть;
            }
            попробовать {
                // Дополнение имени:
                r = s.executeQuery(
                    "SELECT LAST FROM people.csv people WHERE (LAST Like '" + 
                    searchFor.getText() + "%') ORDER BY LAST");
                если(r.next())
                    completion.setText(r.getString("LAST") + " ");
                результаты.setText("Найдено: " + r.getRowCount() + "\n");
                while(r.next())
                    результаты.append(r.getString("FIRST") + " " + r.getString("LAST") + "\n");
            } catch(Исключение e) {
                результаты.setText(e.getMessage());
            }
        }
    }
}
setText(
        r.getString("last")
);
r = s.executeQuery(
    "SELECT FIRST, LAST, EMAIL FROM people.csv people WHERE (LAST='" 
    + completion.getText() + "') AND (EMAIL IS NOT NULL) ORDER BY FIRST"
);
} catch(Exception e) {
    results.setText(
        searchFor.getText() + "\n"
    );
    results.append(e.getMessage());
    return;
}
results.setText("");
try {
    while(r.next()) {
        results.append(
            r.getString("Last") + ", " 
            + r.getString("fIRST") + ": " 
            + r.getString("EMAIL") + "\n"
        );
    }
} catch(Exception e) {
    results.setText(e.getMessage());
}
}
public static void main(String[] args) {
    VLookup applet = new VLookup();
    Window aFrame = new Window("Search Email");
    aFrame.addWindowListener(
        new WindowAdapter() {
            public void windowClosing(WindowEvent e) {

Пожалуйста, обратите внимание, что данное преобразование было сделано с учётом правил перевода, где текстовый контент был переведён на русский язык, а все элементы кода остались без изменений.

System.exit(0);
}
});
aFrame.add(applet, BorderLayout.CENTER);
aFrame.setSize(500, 200);
applet.init();
applet.start();
aFrame.setVisible(true);
}
}

///:~
Многие логические аспекты баз данных одинаковы, но здесь был добавлен слушатель `TextListener`, который отслеживает ввод в поле `TextField`. Поэтому при каждом новом нажатии клавиш программа сначала пытается найти "фамилию" в базе данных и вывести первую совпадающую запись (вставить её в метку `completion Label` как текст для поиска). Таким образом, стоит лишь ввести достаточно символов, чтобы программа нашла единственную подходящую запись, можно прекратить ввод.

## 15.7.3 Почему API JDBC так сложен

При чтении онлайн справочной информации по JDBC часто возникает чувство затруднений. Особенно это относится к интерфейсу `DatabaseMetaData`, который отличается от большинства других интерфейсов в Java тем, что имеет огромное количество методов, таких как `dataDefinitionCausesTransactionCommit()`, `getMaxColumnNameLength()`, `getMaxStatementLength()`, `storesMixedCaseQuotedIdentifiers()`, `supportsANSI92IntermediateSQL()`, `supportsLimitedOuterJoins()` и многих других. Но зачем они нужны?

Теперь текст полностью переведён на русский язык, сохранив исходное форматирование и структуру.Как было указано ранее, базы данных изначально находились в хаотическом состоянии, главным образом из-за различных требований, предъявляемых различными базами данных. Это привело к тому, что инструменты для работы с базами данных стали очень "мощными", другими словами, "большими". Лишь недавно появились общие языки SQL (и многие другие языки для работы с базами данных). Однако даже такой "стандарт", как SQL, существует в бесчисленном количестве вариаций, поэтому JDBC должен предоставить большой интерфейс DatabaseMetaData, чтобы наши программы могли эффективно использовать возможности конкретной реализации SQL. Вкратце, мы можем писать простые и переносимые запросы SQL, но если требуется оптимизация производительности, то нам придется адаптироваться к особенностям каждой конкретной базы данных, что усложняет задачу.Конечно, это не является недостатком Java. Различия между продуктами баз данных — это реальность, которую мы и JDBC должны принимать. Тем не менее, если можно писать универсальные запросы, не заботясь слишком сильно о производительности, задача значительно упрощается. Даж即您的文本已经是俄语,并且格式正确,无需进一步翻译或修改。以下是原文的复述:

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

В выпусках Java 1.1 Sun также предоставил ряд электронных документов, содержащих более подробную информацию о JDBC. Кроме того, книга Hamilton Cattell и Fisher, опубликованная Addison-Wesley в 1997 году под названием "JDBC Database Access with Java", содержит множество полезных материалов по этой теме. Также в продаже есть несколько новых книг по JDBC.

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/wizardforcel-thinking-in-java-zh.git
git@api.gitlife.ru:oschina-mirror/wizardforcel-thinking-in-java-zh.git
oschina-mirror
wizardforcel-thinking-in-java-zh
wizardforcel-thinking-in-java-zh
master