Студенческий отдел кадров
Пособие по JAVA-технологиям
(с) AntonSaburov

База данных

Получив некоторое представление, что существуют такие замечательные структуры как коллекции, Вы наверняка задумались: «Возможно все это здорово, только все эти данные существуют временно — а когда программа завершится, то все исчезнет. Ну и зачем такая нужна ?»
И это замечание вполне справедливо. Конечно же, коллекции для такого рода задач подходят слабо. Так что же делать дальше ? Конечно, большинство из вас знает, что существуют базы данных. Давайте попробуем посмотреть, как можно усовершенствовать нашу систему, используя их.

Прекрасно понимая, что работа с базами данных на сегодня является первостепенной задачей разработчики Java создали специальную технологию — JDBC (Java Database Connectivity). Она позволяет однообразно получать доступ к различным базам данных. Фактически для каждой базы данных существует специальный драйвер, который загружается и используется приложением на Java для доступа к конкретной базе. Но что самое интересное — для программиста работа с различными драйверами практически полностью одинакова, что для MS SQL Server, что для Oracle. В нашем мире хоть какой-то островок стабильности — это уже большое счастье.

Для запуска наших примеров я установил MySQL — он свободен для доступа: MySQL 5.0
Драйвер JDBC для работы вы можете взять здесь: Download Connector/J 3.1
О нем мы обязательно поговорим несколько позже.

Рекомендуем: Вам надо ознакомиться с общими понятиями баз данных и SQL (Structured Query Language) для понимания этой части. Для самого простого уровня достаточно воспринимать базы данных, как набор таблиц, у которых есть фиксированный набор столбцов и любой количество строк. А SQL — это язык, который позволяет получать данные из этих таблиц и модифицировать данные в этих таблицах. Наверняка вы все видели какие-то ведомости, даже расписывались в них. И заметили, что у них обычно есть столбцы с какими либо наименованиями и дальше разлинованные строки, в которые вписываются реальные данные. Так же с точки зрения прикладного программиста (т.е. большинства из нас) выглядят и таблицы в базе данных. Только строки можно добавлять, удалять и модифицировать не зачеркивая — думаю, что многие из вас работали с Excel — так и воспринимайте таблицы в базе данных. Кроме этого учтите, что каждый столбец в базе имеет определенный тип данных. Чаще всего это строки определенной длины, числа (целые, вещественные), даты. В общем-то и все.
Бестселлер по SQL — это книга Мартина Грубера «Понимание SQL». Скачать ее похоже можно уже во многих местах сети:
http://lib.babr.ru/index.php?book=327
http://zipsites.ru/books/ponimanie_sql/
http://bookz.ru/authors/martin-gruber/gruber01.html
Также на форуме Vingrad существует несколько статей по этому вопросу:
http://vingrad.ru/DB-DB-003022
http://vingrad.ru/DB-DB-000133

 

 

Здесь мы рассмотрим очень простые команды SQL — чтобы просто понимать о чем буджет идти речь в дальнейшем.

Добавление записи
Выполняется с помощью оператора INSERT.

Думаю, что вы уже догадались что есть что.

  • <имя_таблицы> — имя таблицы в базе данных
  • <имя_поля_1> — по сути это заголовок столбца (его имя)
  • <величина_поля_1> — это реальное значение поля для новой записи

 

Причем заметим, что порядок полей не важен — главное, чтобы было соответствие между порядком в обоих списках полей и величин. Т.е. если я что-то хочу вставить в поле (например STUDENT_NAME), которое идет вторым, то и реальная величина должна быть второй.
Также вы можете перечислять не все поля. Те поля, которых нет в списке будут установлены по умолчанию. Это может быть NULL(не путайте с 0 — это другое совсем. NULL означает отсутствие величины вообще). Также база данных может иметь правила для установки значений полей. Это может быть поле с автоматическим увеличением (счетчик), может быть даже какая-то формула или функция.
Для примера если я хочу добавить новую группу в таблицу STUDENT_GROUP

Редактирование записи
Выполняется с помощью оператора UPDATE.

Думаю, что комментарии по именам особо не нужны. Важно отметить вот что — оператор в такой форме произведет изменения ПО ВСЕМ СТРОКАМ в таблице. Конечно же нам такого не хочется — мы хотим делать изменения только для какой-то одной записи. Давайте рассмотрим поначалу синтаксис оператора удаления и после него вернемся к нашей проблеме.

Удаление записи
Выполняется с помощью оператора DELETE.

И здесь мы натолкнемся на похожую проблему — удаление будет сделано ДЛЯ ВСЕХ ЗАПИСЕЙ таблицы. Т.е. таким опертором мы удалим все данные. Для решения возникшей проблемы нам потребуется рассмотреть два понятия:

Первое — это возможность добавлять условия в наши операторы. Условия позволяют указать нам то множество записей, которые мы хотим удалить или отредактировать. Также условия позволяет нам получить ограниченный набор записей, а не все. Чуть позже мы посмотрим синтаксис получения данных. Для удаления и редактирования выглядит это так:

После ключевого слово WHERE можно поставить какие-либо условия, которые указывают какие именно записи надо изменить/удалить. Условия могут записываться с помощью достаточно понятных выражений — >, <, =, >=, <=, <> (больше, меньше, равно, больши или равно, меньше или равно, не равно). Также Вы можете использовать неколько условия, соединяя их операторами AND, OR (и, или).

Второе — первичный ключ. Это поле или набор полей, которое (который) уникален для каждой записи. Чаще всего это поле, которое имеет автоматическое увеличение. Кроме того на такое поле накладывается условия уникальности. Т.е. две записи не могут иметь одинаковое значение первичного поля. Много копий сломано в попытках доказать, насколько нужны искусственное введение такого рода полей, но подавляющее большинство программистов используют их. И автор советует делать тоже самое.
И именно эти сображения породили у наших классов Student и Group поля — studentId и groupId. В них мы будем хранить уникальные идентификаторы. Теперь, если мы захотим изменить данные какого-либо студента, то будет это выглядеть так:

Здесь мы для студента с идентификатором 10 установили группу 2 и год обучения в этой группе 2007. Для удаления студента используется такой синтаксис:

Как Вы наверно уже догадались можно делать групповые изменения в таблице. Например мы можем удалить всех студентов и группы с ИД 2 и годом обучения 2006.

Также можно одним оператором перевести студентов из группы с ИД 1 и с годом 2006 в группу 2 с годом 2007

Выборка записей
Выполянется с помощью оператора SELECT. Синтаксис следующий:

Если Вы хотите получить все записи из таблицы, то можно вместо списка полей использовать знак «*».

Поля в принципе могут идти в любом порядке. Хотя чаще всего они передаются в том порядке, в котором они идут в описании таблицы. Но рассчитывать на это не рекомендуется. Для примера получения списка студентов для группы с ИД 1 и годом обучения 2006 мы можем сделать выборку таким образом:

Также хотелось бы отметить, что одновременно с получением данных Вы можете их отсортировать с помощью команды ORDER BY. ORDER BY может сортировать как в возрастающем так и в убывающем порядке. Для этого используется модификатор DESC.

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

Тестовые данные и установка MySQL

Для установки MySQL не надо предпринимать каких-то очень сложных действий. После запуска инсталляции надо только обратить внимание на следующие моменты:

  • Когда установка предложит Вам завести нового пользователя — можно это сделать, но надо запомнить введенные параметры. В принципе нам этот пользователь не понадобится. Можете выбрать «Skip Sign-Up»
  • Далее Вы можете выбрать все установки по умолчанию. НО НАДО остановиться на экране, где Вас попросят установить поддержку языка. Установите второй пункт из трех — поддержка UTF-8
  • И наконец на экране смены пароля для администратора поставьте пароль root. Все примеры работы с базой рассчитаны на него. Хотя если вам захочется другой — будет повод повозиться еще

После установки MySQL вы можете запустить sql-скрипт, который предназначен для создания таблиц и заполнения их тестовыми данными. Сделать это просто — скопируйте приведенный код в файл students.sql, после этого зайдите в каталог<MySQL_DIR>/bin. И запустите команду. Само собой файл student.sql нужно положить туда же — на время. Хотя я часто прописываю путь в переменной PATH до MySQL — это удобно. Что и Вам советую.

 

mysql -u root -p < students.sql

Как видите в конце мы использовали операторы вставки для заполнения нашей базы данных некоторыми данными. В первой части мы создавали таблицы с помощью команд CREATE TABLE. Первая строка DROP DATABASE IF EXISTS studentsуничтожит базу данных students, если такая существует. Здесь хотелось бы обратить внимание на строки

Поля для ИД групп и студентов содержат понятие auto_increment. Это значит, что данные поля не подлежат редактированию и, что очень важно, при вставке новой записи они будут увеличивать свое значение автоматически. Т.е. каждый новый студент или группа получат ИД без наших усилий. Что очень удобно.
ВАЖНО!!! Не забивайте себе голову вопросами — «если я удалю какое-то поле, то как бы мне использовать пробелы (дырки) между ИД». Это не стоит Вашего внимания. Пусть будут провалы в нумерации. В этом ничего страшного нет. Думайте об этом как о случайном числе. Ведь если бы число генерилось вообще случайно в диапазоне от 0 до 4 млрд нам было бы не важно, что есть пробелы. Так вот и не заморачивайтесь.
Если Вы хотите что-то поменять сами, то запустите клиентское приложение mysql.exe — с его помощью Вы сможете выполнять различные запросы.

Работа с драйвером JDBC

Каждая база данных должна отдавать свои данные наружу — пользователям. Передача данных от сервера клиентскому приложению производится по определенным правилам (определенному протоколу), который для каждого производителя может быть свой. Для того, чтобы программисту не влезать во все эти дебри производитель базы данных разрабатывает драйвера для общения со свой базой данных. Для Java это JDBC-драйвера. Самое главное, что для Java-программиста НЕ ВАЖНО, к какому серверу он подключается. Работа с драйвером будет всегда одинакова. Таким образом единственное, что может помешать легкому перенесению базы данных с SQL-сервера одного производителя на другой — это особенности самих SQL-запросов. Если же они у вас не очень сложные и подчиняются стандартам, то скорее всего перенос не будет проблематичным. Рассмотрим простой пример взаимодействия с базой данных.

Давайте подробно рассмотрим, что же мы делаем.
Во-первых обратите внимание, что большинство операций для работы с базой данных вызывают исключения, поэтому мы используем конструкцию try … catch. Более верно было бы обрабатывать не все исключения в одном catch, а обработать каждое конкретное исключение отдельно. Кроме этого мы использовали блок finally для закрытия соеденений к базе данных. Если это не делать, то может возникнуть неприятная ситуация, когда коннектов больше получить не удастся. Так что будьте внимательны.
Итак: В первой строке мы загружаем класс драйвера — Class.forName(«com.mysql.jdbc.Driver»). Вторая строка — задаем URL который описывает «путь» до базы данных. Первая часть строки задает тип драйвера JDBC и сервер базы данных. Потом идет хост и порт (в нашем случае это локальный сервер на нашей машине и порт для MySQL по умолчанию) и имя базы данных, к которой мы подключаемся. Для другого сервера (например для Oracle) строка будет иной (для более подробной информации о формате URL для конкретного сервера баз данных Вам надо обратиться к документации по конкретному JDBC).
Далее мы осуществляем подключение к базе данных, указывая URL, имя пользователя и пароль. В нашем случае заходим пользователем root (что не является хорошим правилом — лучше всегда заводить другого пользователя и давать ему определенные права). Этой строкой мы «открыли дверь» в наш сервер. Теперь мы можем посылать ему команды и получать результат исполнения.

Эта строка создает запрос, который мы будем посылать на сервер
Statement stmt = con.createStatement();

ResultSet rs = stmt.executeQuery(«SELECT * FROM students»);
Эта строка выполняет наш запрос получая в ответ таблицу (набор строк и столбцов). Объект класса ResultSet позволяет пройти по всему возвращенному набору и распечатать. Для этого мы используем цикл в котором проверяем с помощью вызова rs.next()есть ли еще записи. Если они там еще есть — печатаем. Если кончились, то цикл завершается.
После этого мы закрываем набор данных ResultSet и запрос — тем самым освобождая ресурсы. Если Вы выполняете один запрос, после которого закрываете коннект к базе, то закрывать ResultSet и Statement не обязательно — они закроются автоматически. Но если Вы делаете много запросов внутри одного коннекта — закрывайте обязательно. Ну и в конце мы закрываем непосредственно сам коннект к базе. Все достаточно просто.

Мы рассмотрели пример, когда нам необходимо получить данные. В случае, если нам надо просто произвести изменения, то для этого существует вызов executeUpdate. Подробнее о вызовах можно посмотреть в документации по Java API. Сборка данного примера не требует дополнительных библиотек и можно его собрать командой

javac TestJDBC.java

А вот для запуска на потребуется подключить драйвер. Обычно драйвер JDBC представляет из себя набор классов в JAR (Java Archive), который надо просто подключить через CLASSPATH. Например, если драйвер находится в файле mysql-connector-java-3.1.13-bin.jar, то командная строка для запуска будет выглядеть вот так

java -cp .;mysql-connector-java-3.1.13-bin.jar TestJDBC

Теперь мы с вами изменим нашу систему получения данных — ManagementSystem. Т.к. коннект к базе нам будет нужен постоянно, то создадим его один раз и будем использовать везде. Все остальные команды рассмотрим прямо в коде нашего класса ManagementSystem. Прошу обратить внимание, что у нас появились дополнения во многих методах — теперь они порождают исключение SQLException.
Наверняка Вы обратите внимание на класс PreparedStatement. Этот класс является расширением обычного Statement, но добавляет возможности задавать параметры. Т.е. вы задаете запрос, в котором можете изменять какие-либо величины. Это бывает удобно, когда запрос должен выполняться много раз. В этом случае запрос уже предварительно готовится к выполнению, что ускоряет процесс. Мы также изменили класс Student.java. В нем появился конструктор, который запоняет поля из ResultSet. Это просто удобно. И еще мы добавили обработку ошибки при получении списков в классе StudentsFrame. А теперь все классы, которые у нас теперь есть

Student.java

Group.java

ManagementSystem.java

StudentsFrame.java

ВНИМАНИЕ!!! Теперь для запуска нашего приложения нам потребуется драйвер. Поместите его в корневой каталог нашего приложения. Теперь структура нашего каталога выглядит так:

Для сборки нам потребуется команда

javac students/frame/*.java students/logic/*.java
Для сборки примера
javac -encoding UTF-8 students/frame/*.java students/logic/*.java

Для запуска нам надо указать в CLASSPATH файл mysqlJDBC-3.1.13-bin.jar

java -cp .;mysql-connector-java-3.1.13-bin.jar students.frame.StudentsFrame

Теперь мы можем сосредоточить наши усилия на совершенствовании нашего пользовательского интерфейса — Часть 4 — GUI, предварительные знания

Архив с исходными кодами: Исходный код

15 comments to База данных

  • Григорий  says:

    Глупый вопрос быть может, но я не понимаю, как мне запустить этот скрипт в винде. При попытке выполнить его вылазит запрос пароля и потом сообщение Can’t connect to MySQL server on ‘localhost’ (10061).

    • admin  says:

      Как я понял, не получается выполнить команду «mysql -u root -p < students.sql". Так это нормально - там указан ключик "-p" для ввода пароля. А вот какой пароль вы ввели при установке MySQL - такой и надо использовать. Если же пароль не подходит - попробуйте переустановить MySQL и убедится, что пароль введен правильно. Или воспользуйтесь административной консолью для смены пароля. К сожалению примеры писались достаточно давно,кода MySQL бы попроще, чем сейчас.

      • Григорий  says:

        Да, оказалось, что не поднялся SQL сервер у меня. Говорят, из за соседства с Visual Studio. Попробую все удалить и поставить по новой

        • admin  says:

          Я сейчас установил бы PostgreSQL — он проще выглядит. Идея все равно остается такая же — только JDBC-driver надо скачать для него. И создание таблиц несколько отличается — вместо AUTO_INCREMENT поставить SERIAL

          • Григорий  says:

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

  • admin  says:

    Спасибо. Исправил.

  • Влад  says:

    прямо в коде нашего классаManagementSystem
    прямо в коде нашего класса ManagementSystem

  • Влад  says:

    в классе Student.java забыли добавить пустой конструктор
    public Student () {}

  • Александр  says:

    Здравствуйте, как я понимаю, таблицы логически связаны друг с другом через поле group_id в таблице students, но не прописан внешний ключ. Могли бы вы вкратце прокомментировать такой подход? Так следует делать, можно делать на выбор или это ни на что не влияет? Спасибо.

    • admin  says:

      Я на тот момент полагал, что лишний код скрывает мысль, потому и не сделал ключ. Может был не прав.

  • Вадим  says:

    Здравствуйте. Статья для меня оказалась интересной но хотелось добавить несколько моментов. Удивило отсутствие комментариев в коде (все таки приручился). И если возможно добавите ссылку http://www.javaportal.ru/java/tutorial/tutorialJDBC/index.html. Просто сам SQL много где довольно детально расписан а вот сам JDBC в учебниках почему то стараются описать чем поменьше и оказывается что некоторые вещи в коде в первый раз вижу.

  • Виктория  says:

    Здравствуйте! Большое спасибо за статью! Хотелось бы обратить внимание на опечатку в разделе Выборка данных — в названии таблицы STUDENTS.

    • admin  says:

      Спасибо за добрый слова. Можно уточнить, где именно опечатка ? Я с ними пытаюсь бороться, но не очень получается пока 🙂

      • Виктория  says:

        Опечатка в разделе База данных, подзаголовок Выборка записей, там где идет описание оператора SELECT. В двух последних примерах.

        • admin  says:

          Спасибо — нашел. Лучше приводить кусок того, что написано с комментарием, что там неправильно (если не очевидная ошибка). Иначе искать сложновато. Но все равно — спасибо большое.

Leave a reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">

Лимит времени истёк. Пожалуйста, перезагрузите CAPTCHA.