Полезное для программистов:

Фриланс
Новости
Статьи
   
Рубрики:


Часть 3 - Базы данных

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

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

Для запуска наших примеров я установил MySQL - он свободен для доступа:
http://dev.mysql.com/downloads/mysql/5.0.html
Драйвер JDBC для работы вы можете взять здесь:
http://dev.mysql.com/downloads/connector/j/3.1.html
О нем мы обязательно поговорим несколько позже.
 
Рекомендуем: Вам надо ознакомиться с общими понятиями баз данных и 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.

Код

INSERT INTO <имя_таблицы> (<имя_поля_1>, <имя_поля_2>, <имя_поля_3>, ...) 
VALUES (<величина_поля_1>, <величина_поля_1>, <величина_поля_3>, <величина_поля_3>, ...)

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

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

Для примера если я хочу добавить новую группу в таблицу STIDENT_GROUP
Код

INSERT INTO STUDENT_GROUP (GROUP_NAME, CURATOR, SPECIALITY)
VALUES ("Первая", "Доктор Борменталь", "Делание человеков из собачек")


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

Код

UPDATE <имя_таблицы> SET <имя_поля_1>=<величина_поля_1>, <имя_поля_2>=<величина_поля_2> ...

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

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

Код

DELETE FROM <имя_таблицы>

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

Код

UPDATE <имя_таблицы> SET <имя_поля_1>=<величина_поля_1>, <имя_поля_2>=<величина_поля_2> ...
WHERE <условия>

DELETE FROM <имя_таблицы> WHERE <условия>

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

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

И именно эти сображения породили у наших классов Student и Group поля - studentId и groupId. В них мы будем хранить уникальные идентификаторы.
Теперь, если мы захотим изменить данные какого-либо студента, то будет это выглядеть так
Код

UPDATE STUDENTS SET group_id=2, educationYear=2007 WHERE student_id=10

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

DELETE FROM STUDENTS WHERE student_id=10

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

DELETE FROM STUDENTS WHERE group_id=2 AND educationYear=2006

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

UPDATE STUDENTS SET group_id=2, educationYear=2007 WHERE group_id=1 AND educationYear=2006


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

SELECT <имя_поля_1>, <имя_поля_2>, ... FROM <таблица> WHERE <условия>

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

SELECT * FROM <таблица> WHERE <условия>

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

Для примера получения списка студентов для группы с ИД 1 и годом обучения 2006 мы можем сделать выборку таким образом
Код

SELECT * FROM STIDENTS WHERE group_id=1 AND educationYear=2006


Также хотелось бы отметить, что одновременно с получением данных Вы можете их отсортировать с помощью команды ORDER BY
Код

SELECT * FROM STIDENTS WHERE group_id=1 AND educationYear=2006 ORDER BY group_id

ORDER BY может сортировать как в возрастающем так и возрастающем порядке. Для этого используется модификатор DESC.
Код

SELECT * FROM STIDENTS WHERE group_id=1 AND educationYear=2006 ORDER BY group_id DESC


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

Тестовые данные и установка MySQL
Для установки MySQL не надо предпринимать каких-то очень сложных действий. После запуска инсталляции надо только обратить внимание на следующие моменты:
- Когда установка предложит Вам завести нового пользователя - можно это сделать, но надо запомнить введенные параметры. В принципе нам этот пользователь не понадобится. Можете выбрать "Skip Sign-Up"
- Далее Вы можете выбрать все установки по умолчанию. НО НАДО остановиться на экране, где Вас попросят установить поддержку языка. Установите второй пункт из трех - поддержка UTF-8
- И наконец на экране смены пароля для администратора снимите галочку Modify Security Settings. Тогда пароль останется пустой. Хотя если Вам это будет не сложно - введите новый пароль. Но все примеры работы с базой рассчитаны на пустой пароль.

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

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

mysql -u root < students.sql


Код sql-скрипта
Код

--DROP DATABASE students;

CREATE DATABASE students
    DEFAULT CHARACTER SET 'cp1251';

USE students;

create table groups
(
  group_id int unsigned not null auto_increment,
  groupName varchar(255) not null,
  curator varchar(255) not null,
  speciality varchar(255) not null,
  primary key (group_id)
) engine=InnoDB;

create table students
(
  student_id int unsigned not null auto_increment,
  firstName varchar(255) not null,
  surName varchar(255) not null,
  patronymic varchar(255) not null,
  dateOfBirth date not null,
  sex char(1),
  group_id int not null,
  educationYear int not null,
  primary key (student_id)
) engine=InnoDB;

set names 'cp1251';

insert into groups (groupName, curator, speciality) values ('Первая', 'Доктор Борменталь', 'Создание собачек из человеков');
insert into groups (groupName, curator, speciality) values ('Вторая', 'Профессор Преображенский', 'Создание человеков из собачек');

insert into students (firstName, patronymic, surName, sex, dateOfBirth, group_id, educationYear)
values ('Иван', 'Сергеевич', 'Степанов', 'М', '1990-03-20', 1, 2006);

insert into students (firstName, patronymic, surName, sex, dateOfBirth, group_id, educationYear)
values ('Наталья', 'Андреевна', 'Чичикова', 'Ж', '1990-06-10', 1, 2006);

insert into students (firstName, patronymic, surName, sex, dateOfBirth, group_id, educationYear)
values ('Виктор', 'Сидорович', 'Белов', 'М', '1990-01-10', 1, 2006);

insert into students (firstName, patronymic, surName, sex, dateOfBirth, group_id, educationYear)
values ('Петр', 'Викторович', 'Сушкин', 'М', '1991-03-12', 2, 2006);

insert into students (firstName, patronymic, surName, sex, dateOfBirth, group_id, educationYear)
values ('Вероника', 'Сергеевна', 'Ковалева', 'Ж', '1991-07-19', 2, 2006);

insert into students (firstName, patronymic, surName, sex, dateOfBirth, group_id, educationYear)
values ('Ирина', 'Федоровна', 'Истомина', 'Ж', '1991-04-29', 2, 2006);


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

Здесь хотелось бы отметит следующее: обратите внимание на строки
Код

create table groups
(
  group_id int unsigned not null auto_increment,

  ...

create table students
(
  student_id int unsigned not null auto_increment,

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

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

Если Вы хотите что-то поменять сами, то запустите клиентское приложение mysql.exe - с его помощью Вы сможете выполнять различные запросы. 

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

Рассмотрим простой пример взаимодействия с базой данных.

Код

import java.sql.*;

public class TestJDBC
{
  public static void main(String args[])
  {
    System.out.println("Copyright 2006, Anton Saburov");
    try {
      Class.forName("com.mysql.jdbc.Driver");
      String url = "jdbc:mysql://localhost/students";
      Connection con = DriverManager.getConnection(url,"root", "");
      System.out.println("URL: " + url);
      System.out.println("Connection: " + con);
      Statement stmt = con.createStatement();
      ResultSet rs = stmt.executeQuery("SELECT * FROM students");      
      while(rs.next()) {
        String str = rs.getString(1) + ":" + rs.getString(2);
        System.out.println(str);
      }
      rs.close();
      stmt.close();
      con.close();
    }
    catch( Exception e ) {
      e.printStackTrace();
    }
  }
}

Давайте подробно рассмотрим, что же мы делаем.

Во-первых обратите внимание, что большинство операция для работы с базой данных вызывают исключения, поэтому мы используем конструкцию try ... catch. Более верно было бы обрабатывать не все исключения в одном catch, а обработать каждое конкретное исключение отдельно.
Итак:
В первой строке мы загружаем класс драйвера - Class.forName("com.mysql.jdbc.Driver")
Вторая строка - задаем URL который описывает "путь" до базы данных. Первая часть строки задает тип драйвера JDBC и сервер базы данных. Помто идет хост (в нашем случае это локальный сервер на нашей машине) и имя базы данных, к котрой мы подключаемся. Для другого сервера (например для 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
Код

package students.logic;

import java.text.DateFormat;
import java.util.Date;
import java.sql.ResultSet;
import java.sql.SQLException;

public class Student implements Comparable
{
    private int studentId;
    private String firstName;
    private String surName;
    private String patronymic;
    private Date dateOfBirth;
    private char sex;
    private int groupId;
    private int educationYear;

    public Student(ResultSet rs) throws SQLException
    {
      setStudentId(rs.getInt("student_id"));
      setFirstName(rs.getString("firstName"));
      setPatronymic(rs.getString("surName"));
      setSurName(rs.getString("patronymic"));
      setSex(rs.getString("sex").charAt(0));
      setDateOfBirth(rs.getDate("dateOfBirth"));
      setGroupId(rs.getInt("group_id"));
      setEducationYear(rs.getInt("educationYear"));
    }

    public Date getDateOfBirth()
    {
      return dateOfBirth;
    }

    public void setDateOfBirth(Date dateOfBirth)
    {
      this.dateOfBirth = dateOfBirth;
    }

    public int getEducationYear()
    {
      return educationYear;
    }

    public void setEducationYear(int educationYear)
    {
      this.educationYear = educationYear;
    }

    public int getGroupId()
    {
      return groupId;
    }

    public void setGroupId(int groupId)
    {
      this.groupId = groupId;
    }

    public int getStudentId()
    {
      return studentId;
    }

    public void setStudentId(int studentId)
    {
      this.studentId = studentId;
    }

    public String getFirstName()
    {
      return firstName;
    }

    public void setFirstName(String firstName)
    {
      this.firstName = firstName;
    }

    public String getPatronymic()
    {
      return patronymic;
    }

    public void setPatronymic(String patronymic)
    {
      this.patronymic = patronymic;
    }

    public String getSurName()
    {
      return surName;
    }

    public void setSurName(String surName)
    {
      this.surName = surName;
    }

    public char getSex()
    {
      return sex;
    }

    public void setSex(char sex)
    {
      this.sex = sex;
    }

    public String toString()
    {
      return surName
        + " "
        + firstName
        + " "
        + patronymic
        + ", "
        + DateFormat.getDateInstance(DateFormat.SHORT).format(
          dateOfBirth) + ", Группа ИД=" + groupId+ " Год:"+educationYear;
    }

    public int compareTo(Object obj)
    {
      return this.toString().compareTo(obj.toString());
    }
}


Group.java
Код

package students.logic;

public class Group
{
    private int groupId;
    private String nameGroup;
    private String curator;
    private String speciality;

    public String getCurator()
    {
      return curator;
    }

    public void setCurator(String curator)
    {
      this.curator = curator;
    }

    public int getGroupId()
    {
      return groupId;
    }

    public void setGroupId(int groupId)
    {
      this.groupId = groupId;
    }

    public String getNameGroup()
    {
      return nameGroup;
    }

    public void setNameGroup(String nameGroup)
    {
      this.nameGroup = nameGroup;
    }

    public String getSpeciality()
    {
      return speciality;
    }

    public void setSpeciality(String speciality)
    {
      this.speciality = speciality;
    }

    public String toString()
    {
      return nameGroup;
    }
}


ManagementSystem.java
Код

package students.logic;

import java.sql.Connection;
import java.sql.Date;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class ManagementSystem
{
  private static Connection con; 
  private static ManagementSystem instance;

  private ManagementSystem() {
    try {
      Class.forName("com.mysql.jdbc.Driver");
      String url = "jdbc:mysql://localhost/students";
      con = DriverManager.getConnection(url,"root", "");
    } catch (ClassNotFoundException e1) {
      e1.printStackTrace();
    } catch (SQLException e) {
      e.printStackTrace();
    }
  }

  public static synchronized ManagementSystem getInstance()
  {
    if (instance == null) {
      instance = new ManagementSystem();
    }
    return instance;
  }

  public List getGroups() throws SQLException
  {
    List groups = new ArrayList();
    
    Statement stmt = con.createStatement();
    ResultSet rs = stmt.executeQuery("SELECT group_id, groupName, curator, speciality FROM groups");
    while(rs.next()) {
      Group gr = new Group();
      gr.setGroupId(rs.getInt(1));
      gr.setNameGroup(rs.getString(2));
      gr.setCurator(rs.getString(3));
      gr.setSpeciality(rs.getString(4));

      groups.add(gr);
    }
    rs.close();
    stmt.close();
    
    return groups;
  }
    
  public Collection getAllStudents() throws SQLException
  {
    Collection students = new ArrayList();

    Statement stmt = con.createStatement();
    ResultSet rs = stmt.executeQuery(
        "SELECT student_id, firstName, patronymic, surName, "+
        "sex, dateOfBirth, group_id, educationYear FROM students ORDER BY surName, firstName, patronymic");
    while(rs.next()) {
      Student st = new Student(rs);
      students.add(st);
    }
    rs.close();
    stmt.close();

    return students;
  }

  public Collection getStudentsFromGroup(Group group, int year) throws SQLException 
  {
    Collection students = new ArrayList();

    PreparedStatement stmt = con.prepareStatement(
        "SELECT student_id, firstName, patronymic, surName, "+
        "sex, dateOfBirth, group_id, educationYear FROM students " +
        "WHERE group_id=? AND educationYear=? "+
        "ORDER BY surName, firstName, patronymic");
    stmt.setInt(1, group.getGroupId());
    stmt.setInt(2, year);
    ResultSet rs = stmt.executeQuery();
    while(rs.next()) {
      Student st = new Student(rs);
    
      students.add(st);
    }
    rs.close();
    stmt.close();
    
    return students;
  }

  public void moveStudentsToGroup(Group oldGroup, int oldYear, Group newGroup, int newYear) throws SQLException
  {
    PreparedStatement stmt = con.prepareStatement(
        "UPDATE students SET group_id=?, educationYear=? " +
        "WHERE group_id=? AND educationYear=?");
    stmt.setInt(1, newGroup.getGroupId());
    stmt.setInt(2, newYear);
    stmt.setInt(3, oldGroup.getGroupId());
    stmt.setInt(4, oldYear);
    stmt.execute();
  }
    
  public void removeStudentsFromGroup(Group group, int year) throws SQLException
  {
    PreparedStatement stmt = con.prepareStatement(
        "DELETE FROM students WHERE group_id=? AND educationYear=?");
    stmt.setInt(1, group.getGroupId());
    stmt.setInt(2, year);
    stmt.execute();
  }

  public void insertStudent(Student student) throws SQLException
  {
    PreparedStatement stmt = con.prepareStatement(
        "INSERT INTO students "+
        "(firstName, patronymic, surName, sex, dateOfBirth, group_id, educationYear) " +
        "VALUES (?, ?, ?, ?, ?, ?, ?)");
    stmt.setString(1, student.getFirstName());
    stmt.setString(2, student.getPatronymic());
    stmt.setString(3, student.getSurName());
    stmt.setString(4, new String(new char[] {student.getSex()} ));
    stmt.setDate(5, new Date(student.getDateOfBirth().getTime()));
    stmt.setInt(6, student.getGroupId());
    stmt.setInt(7, student.getEducationYear());

    stmt.execute();
  }
    
  public void updateStudent(Student student) throws SQLException
  {
    PreparedStatement stmt = con.prepareStatement(
        "UPDATE students SET "+
        "firstName=?, patronymic=?, surName=?, "+
        "sex=?, dateOfBirth=?, group_id=?, educationYear=? " +
        "WHERE student_id=?");
    stmt.setString(1, student.getFirstName());
    stmt.setString(2, student.getPatronymic());
    stmt.setString(3, student.getSurName());
    stmt.setString(4, new String(new char[] {student.getSex()} ));
    stmt.setDate(5, new Date(student.getDateOfBirth().getTime()));
    stmt.setInt(6, student.getGroupId());
    stmt.setInt(7, student.getEducationYear());
    stmt.setInt(8, student.getStudentId());
  
    stmt.execute();
  }
    
  public void deleteStudent(Student student) throws SQLException
  {
    PreparedStatement stmt = con.prepareStatement(
      "DELETE FROM students WHERE student_id=?");
    stmt.setInt(1, student.getStudentId());
    stmt.execute();
  }
}


StudentsFrame.java
Код

package students.frame;

import java.sql.SQLException;
import java.util.Vector;

import java.awt.FlowLayout;
import java.awt.BorderLayout;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

import javax.swing.JSpinner;
import javax.swing.SpinnerModel;
import javax.swing.SpinnerNumberModel;
import javax.swing.border.BevelBorder;

import students.logic.ManagementSystem;



public class StudentsFrame extends JFrame
{
  ManagementSystem ms = ManagementSystem.getInstance();
  private JList grpList;
  private JList stdList;
  private JSpinner spYear;

  public StudentsFrame()
  {
    // Устанавливаем layout для всей клиентской части формы
    getContentPane().setLayout(new BorderLayout());


    // Создаем верхнюю панел, где будет поле для ввода года
    JPanel top = new JPanel();
    // Устанавливаем для нее layout
    top.setLayout(new FlowLayout(FlowLayout.LEFT));

    // Вставляем пояснительную надпись
    top.add(new JLabel("Год обучения:"));
    // Делаем спин-поле 
    //   1. Задаем модель поведения - только цифры
    //   2. Вставляем в панель
    SpinnerModel sm = new SpinnerNumberModel(2006, 1900, 2100, 1);
    spYear = new JSpinner(sm);
    top.add(spYear);


    // Создаем нижнюю панель и задаем ей layout
    JPanel bot = new JPanel();
    bot.setLayout(new BorderLayout());

    // Создаем левую панель для вывода списка групп
    JPanel left = new JPanel();
    // Задаем layout и задаем "бордюр" вокруг панели
    left.setLayout(new BorderLayout());
    left.setBorder(new BevelBorder(BevelBorder.RAISED));

    // Нам необходимо обработать ошику при обращении к базе данных
    Vector gr=null;
    Vector st=null;
    try {
      // Получаем список групп
      gr=new Vector(ms.getGroups());
      // Получаем список студентов
      st=new Vector(ms.getAllStudents());
    } catch(SQLException e) {
      e.printStackTrace();
    }
    // Создаем надпись
    left.add(new JLabel("Группы:"), BorderLayout.NORTH);
    // Создаем визуальный список и вставляем его в скроллируемую
    // панель, которую в свою очередь уже кладем на панель left
    grpList = new JList(gr);
    left.add(new JScrollPane(grpList), BorderLayout.CENTER);

    // Создаем правую панель для вывода списка студентов
    JPanel right = new JPanel();
    // Задаем layout и задаем "бордюр" вокруг панели
    right.setLayout(new BorderLayout());
    right.setBorder(new BevelBorder(BevelBorder.RAISED));

    // Создаем надпись
    right.add(new JLabel("Студенты:"), BorderLayout.NORTH);
    // Создаем визуальный список и вставляем его в скроллируемую
    // панель, которую в свою очередь уже кладем на панель right
    stdList = new JList(st);
    right.add(new JScrollPane(stdList), BorderLayout.CENTER);

    // Вставляем панели со списками групп и студентов в нижнюю панель 
    bot.add(left, BorderLayout.WEST);
    bot.add(right, BorderLayout.CENTER);

    // Вставляем верхнюю и нижнюю панели в форму
    getContentPane().add(top, BorderLayout.NORTH);
    getContentPane().add(bot, BorderLayout.CENTER);

    // Задаем границы формы   
    setBounds(100, 100, 600, 400);
  }


  public static void main(String args[])
  {
    StudentsFrame sf = new StudentsFrame();
    sf.setDefaultCloseOperation(EXIT_ON_CLOSE);
    sf.setVisible(true);
  }
}


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

Теперь структура нашего каталога выглядит так:
Код

- student
   - frame
      - StudentsFrame.java
   - logic
      - Student.java
      - Group.java
      - ManagementSystem.java
- mysql-connector-java-3.1.13-bin.jar

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

javac 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, предварительные знания
Автор: AntonSaburov






Просмотров: 5953

 

 

Новые статьи:


Популярные:
  1. Как сделать цикличным проигрывание MIDI-файла?
  2. Создание AVI файла из рисунков
  3. Как устройство "отключить в данной конфигурации"?
  4. Kто в данный момент присоединен через Сеть?
  5. Как узнать количество доступной памяти?
  6. Как реализовать в RichEdit разноцветный текст?
  7. Как скрыть свое приложение от ProcessViewer
  8. Как программно нажать/скрыть/показ кнопку "Start"?
  9. Модуль работы с ресурсами в PE файлах
10. Функции вызова диалоговых окон выбора
11. Проверка граматики средствами Word'а из Delphi.
12. Модуль для упрощенного вызова сообщений
13. Функции для записи и чтение своих данных в, ЕХЕ- файле
14. Рекурсивный просмотр директорий
15. Network Traffic Monitor
16. Разные модули
17. Универсальная функция для обращения к любым экспортируем функциям DLL
18. Библиотека от VladS
19. Протектор для UPX'а
20. Еще об ICQ, сообщения по контакт листу?
21. Использование открытых интерфейсов
22. Теория и практика использования RTTI
23. Работа с TApplication
24. Примеры использования Drag and Drop для различных визуальных компонентов
25. Что такое порт? Правила для работы с портами
26. Симфония на клавиатуре
27. Загрузка DLL
28. Исправление автоинкремента
29. Взаимодействие с чужими окнами
30. Проверить дубляжи в столбце


 

 

 
 
На главную