Статьи

Разговор с MySQL: ваш первый взгляд на JDBC

Чтобы создать приложение To-Do List, которое мы будем использовать для изучения множества доступных технологий веб-разработки на Java, начнем с основы приложения: набора классов, которые подключаются к базе данных MySQL для извлечения, моделирования и обновить список дел.

Прежде чем идти дальше, вам понадобятся практические знания Java как языка программирования. По крайней мере, вы должны понимать основные концепции объектно-ориентированного программирования : классы, объекты, методы, свойства и конструкторы. Обзор этих концепций и необходимых основ программирования на Java см. В моих статьях: Начало работы с Java , Основы языка Java и Объектно-ориентированные концепции в Java (часть первая и вторая ).

Поскольку мы подключаемся к базе данных, мы будем использовать классы Java Database Connectivity (JDBC) , которые являются частью платформы Java 2 Enterprise Edition (J2EE), поддерживаемой всеми веб-серверами с поддержкой Java. Эти классы предоставляют общий набор классов для подключения к любому серверу базы данных.

Чтобы подключиться к MySQL через JDBC, нам нужно получить копию MySQL Connector / J , драйвера JDBC для MySQL. После указания Java загрузить драйвер, мы можем попросить его подключиться к базе данных MySQL, и все стандартные классы JDBC будут знать, как работать с этим соединением.

Загрузите и распакуйте архив MySQL Connector / J. Внутри вы найдете файл mysql-connector-java- version -bin.jar (версия 3.0.15 на момент написания), который является библиотекой драйверов. Проигнорируйте остальную часть пуха и скопируйте файл JAR в рабочий каталог, где вы планируете создать Java-приложение списка дел.

Прежде всего, давайте ToDoList класс ToDoList , который будет представлять список дел, хранящийся в базе данных, и позволит нам получать доступ и изменять его записи. Мы поместим этот класс в пакет Java (или пространство имен) с именем com.sitepoint, поэтому в вашем рабочем каталоге создайте каталог с именем com с подкаталогом с именем sitepoint , и в нем создайте файл с именем ToDoList.java . Запустите файл с требуемой декларацией пакета:

 package com.sitepoint; 

В этом классе мы будем использовать классы JDBC из java.sql и классы коллекции из java.util , поэтому давайте импортируем их:

 import java.util.*; import java.sql.*; 

И, наконец, мы объявим наш класс:

 public class ToDoList { 

Чтобы сохранить класс как можно более независимым от базы данных, мы спроектируем его конструктор так, чтобы он принимал имя драйвера JDBC и строку соединения JDBC , которые вместе дают ему все необходимое для подключения к базе данных через JDBC. Конструктор немедленно загрузит класс драйвера, а затем сохранит строку соединения JDBC в закрытое свойство, чтобы объект мог использовать его для подключения к базе данных, когда это необходимо.

  private String jdbcConnectionString; public ToDoList(String jdbcDriver, String jdbcConnectionString) { this.jdbcConnectionString = jdbcConnectionString; // Load the driver try { Class.forName(jdbcDriver).newInstance(); } catch (Exception ex) { System.err.println("Error loading database driver " + jdbcDriver + ":n" + ex.getMessage()); } } 
  Class.forName() получает ссылку на класс драйвера JDBC, а вызов его метода newInstance() обеспечивает его загрузку.  Мы ловим любые исключения, которые могут быть сгенерированы в случае, если класс драйвера недоступен (если вы забудете это сделать, компилятор напомнит вам).

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

  private List list = new ArrayList(); private boolean staleList = true; 

Переменная list будет хранить список, полученный из базы данных, а вторая будет отслеживать, когда этот список нуждается в обновлении (то есть, когда он «устарел»). Мы начнем с пустого ArrayList (стандартного списка классов Java из пакета java.util ), который, как предполагается, нуждается в обновлении.

Теперь, хочет ли программа фактический список дел или просто хочет узнать, сколько их существует, нам нужно будет извлечь список из базы данных. Итак, давайте напишем один закрытый метод, который проверяет, является ли сохраненный список (в свойстве list ) устаревшим, и загружает список из базы данных, если необходимо:

  private void refreshList() { if (staleList) { // Load list from the database... staleList = false; } } 

Загрузка списка из базы данных - это то, где приходит JDBC. Сначала мы используем строку соединения JDBC (сохраненную конструктором в jdbcConnectionString ) для подключения к базе данных. Поскольку это трудоемкая операция, мы сохраним соединение в другом частном свойстве с именем conn , и создадим новое соединение, только когда оно пустое:

  if (conn == null) { conn = DriverManager.getConnection(jdbcConnectionString); } 

Затем мы создаем объект Statement из соединения и используем его для выполнения запроса SELECT и получения результирующего ResultSet :

  Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("SELECT todoid, todo FROM todo"); 

ToDoItem результаты, мы сохраняем новый пустой ArrayList в свойстве list и заполняем его объектами ToDoItem созданными из содержимого набора результатов:

  list = new ArrayList(); while (rs.next()) { list.add(new ToDoItem(rs.getInt(1), rs.getString(2))); } 

Это может быть немного запутанным кодом по нескольким причинам. Во-первых, мы используем цикл while для просмотра набора результатов. Вызов метода next() из результирующего набора переводит его на следующую запись или возвращает false если не осталось записей - таким образом завершается цикл while.

В цикле мы используем метод add() класса ArrayList для добавления элементов в список. Но что именно мы добавляем? Новые экземпляры класса ToDoItem .

  ToDoItem - это простой простой маленький класс, который отслеживает идентификатор (идентификатор базы данных элемента списка дел) и строку (текст для этого элемента).  Эти два значения доступны только для чтения, так как не существует методов для их изменения.  Подобные объекты, которые представляют записи в базе данных, называются объектами данных .  Создайте этот класс, вставив следующий код в файл с именем ToDoItem.java вместе с файлом ToDoItem.java над ToDoList.java вы уже работаете:

 package com.sitepoint; public class ToDoItem { private int id; private String item; ToDoItem(int id, String item) { this.id = id; this.item = item; } public int getId() { return id; } public String getItem() { return item; } public String toString() { return getItem(); } } 

Единственная деталь, заслуживающая внимания в этом простом классе, заключается в том, что конструктор не объявляется общедоступным, а вместо этого остается закрытым пакетом, поэтому только классы в пакете com.sitepoint могут создавать объекты ToDoItem .

Возвращаясь к ToDoList , конструктор ToDoItem ожидает получения идентификатора и текстовых значений для элемента. Мы можем извлечь эти значения из текущей строки набора результатов, используя getInt(1) для извлечения целочисленного значения из первого столбца ( todoid ) и getString(2) чтобы получить строковое значение из второго столбца ( todo ).

Это все для заполнения списка, за исключением того, что для обработки ошибок базы данных из всего этого мы много ловим любые SQLException которые могут быть выброшены (опять же, компилятор напомнит вам, если вы забудете). Вот завершенный refreshList() и delcaration для свойства conn:

  private Connection conn; private void refreshList() { if (staleList) { try { if (conn == null) { conn = DriverManager.getConnection(jdbcConnectionString); } Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("SELECT todoid, todo FROM todo"); list = new ArrayList(); while (rs.next()) { list.add(new ToDoItem(rs.getInt(1), rs.getString(2))); } } catch (SQLException ex) { System.err.println( "Error retrieving to-do list items from the database:n" + ex.getMessage()); } staleList = false; } } 

С тяжелой работой, проделанной в refreshList() , реализация getToDoItems() и getItemCount() , чтобы получить элементы списка дел и количество таких элементов соответственно, является подпоркой:

  public Iterator getToDoItems() { refreshList(); return list.iterator(); } public int getItemCount() { refreshList(); return list.size(); } 

Метод iterator() списочных классов Java возвращает Iterator , объект, очень похожий на результирующий набор базы данных, с которым мы только что работали, который позволяет запрашивающему объекту шагать по списку. size() тем временем говорит сам за себя.

addItem() и deleteItem() работают так же, как и refreshList() , за исключением того, что они используют PreparedStatement вместо простого Statement . Рассмотрим этот код из addItem :

  PreparedStatement stmt = conn.prepareStatement( "INSERT INTO todo (todo) VALUES (?)"); stmt.setString(1, item); stmt.executeUpdate(); 

Обратите внимание на вопросительный знак в запросе INSERT . Это указывает место, где к запросу будет добавлено неизвестное значение (в данном случае текст для нового элемента списка дел). Последующий setString(1, item) присваивает строковое значение (в данном случае предоставляемое переменной item ) первой точке в запросе. Другие методы, такие как setInt() позволяют использовать значения других типов. Внедрение значений в ваши запросы к базе данных таким образом аккуратно обходит любой символ, избегая проблем, которые часто вступают в игру с другими языками.

Вот полный код для addItem() и deleteItem() , таким образом завершая наш класс ToDoList :

  public void addItem(String item) { try { if (conn == null) { conn = DriverManager.getConnection(jdbcConnectionString); } PreparedStatement stmt = conn.prepareStatement( "INSERT INTO todo (todo) VALUES (?)"); stmt.setString(1, item); stmt.executeUpdate(); } catch (SQLException ex) { System.err.println( "Error adding a to-do list item to the database:n" + ex.getMessage()); } staleList = true; } public void deleteItem(int id) { try { if (conn == null) { conn = DriverManager.getConnection(jdbcConnectionString); } PreparedStatement stmt = conn.prepareStatement( "DELETE FROM todo WHERE todoid=?"); stmt.setInt(1, id); stmt.executeUpdate(); } catch (SQLException ex) { System.err.println( "Error deleting a to-do list item from the database:n" + ex.getMessage()); } staleList = true; } 

Обратите внимание, что каждый из этих методов устанавливает значение staleList в значение true только оно выполнит свою работу, так что при следующей попытке прочитать список refreshList снова refreshList его из базы данных.

Все, что нам сейчас нужно, это класс для проверки работы, которую мы проделали до сих пор Вот класс с именем ToDoTest который сделает ToDoTest дело. Поместите ToDoTest.java вместе с другими вашими файлами:

 package com.sitepoint; import java.util.*; public class ToDoTest { public static void main(String[] args) { ToDoList list = new ToDoList("com.mysql.jdbc.Driver", "jdbc:mysql://localhost/ todo ?user= root &password= password "); System.out.println("The to-do list contains " + list.getItemCount() + "items:"); Iterator it = list.getToDoItems(); while (it.hasNext()) { System.out.println(" - " + it.next()); } list.addItem("Another todo item."); list.addItem("And yet another."); System.out.println("The to-do list contains " + list.getItemCount() + " items:"); it = list.getToDoItems(); while (it.hasNext()) { System.out.println(" - " + it.next()); } } } 

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

Скомпилируйте ваши три класса из рабочего каталога верхнего уровня:

  javac com / sitepoint / ToDoList.java com / sitepoint / ToDoItem.java 
 ком / SitePoint / ToDoTest.java

Затем запустите ToDoTest , добавив драйвер JDBC MySQL к пути к классам:

  java -classpath.; mysql-connector-java-3.0.15-ga-bin.jar 
 com.sitepoint.ToDoTest 

Вы должны увидеть список элементов списка дел до и после добавления двух новых элементов в список, что-то вроде этого:

  Список дел содержит 2 элемента:
  - Еще один предмет todo.
  - и еще один.
 Список дел состоит из 4 пунктов:
  - Еще один предмет todo.
  - и еще один.
  - Еще один предмет todo.
  - и еще один. 

Это оно! Мы готовы построить веб-приложение на основе этих классов.

Скачать исходный код (5 КБ)