Определение структуры данных
Команда CREATE TABLE
Для создания новых таблиц используется команда CREATE TABLE. В общем виде ее синтаксис следующий:
CREATE TABLE <имя таблицы>
(
<имя колонки> <тип колонки>[(<размер колонки>)] [<ограничение целостности уровня колонки>]
[, <имя колонки> <тип колонки>[(<размер колонки>)] [<ограничение целостности уровня колонки>]]
[, …]
[<ограничение целостности уровня таблицы>]
[,<ограничение целостности уровня таблицы>]
[, …]
)
Примеры:
CREATE TABLE Departments
(
DeptNum int NOT NULL PRIMARY KEY,
Name varchar(80) NOT NULL
)
CREATE TABLE Employees
(
TabNum int NOT NULL PRIMARY KEY,
Name varchar(100) NOT NULL,
Position varchar(200),
DeptNum int,
Salary decimal(10, 2) DEFAULT0,
CONSTRAINT FK_DEPARTMENT FOREIGN KEY (DeptNum)
REFERENCES Departments(DeptNum)
)
Помимо команды CREATE TABLE, можно создать новую таблицу с помощью специальной формы команды SELECT:
SELECT [DISTINCT] <список колонок>
INTO <имя новой таблицы>
FROM <имя таблицы> [JOIN <имя таблицы> ON <условия связывания>]
[WHERE <условия выборки>]
[GROUP BY <список колонок для группировки> [HAVING <условия выборки групп>] ]
[ORDER BY <список колонок для сортировки>]
При наличии ключевого слова INTO в команде SELECT ядро СУБД не вернет результирующую выборку пользователю, а автоматически создаст новую таблицу с указанным именем и заполнит ее данными из результирующей выборки. Имена колонок таблицы и типы будут определены автоматически при анализе команды SELECT и словаря базы данных.
Команда ALTER TABLE
Созданную таблицу можно впоследствии изменить с помощью команды ALTER TABLE. Команда ALTER TABLE позволяет добавлять новые колонки и ограничения целостности, удалять их, менять типы колонок, переименовывать колонки.
Примеры различных вариантов команды ALTER TABLE:
ALTER TABLE Departments ADD COLUMN City int
ALTER TABLE Departments DROP COLUMN City
ALTER TABLE Departments ADD
CONSTRAINT FK_City
FOREIGN KEY (City)
REFERENCES Cities(City)
ALTER TABLE Departments DROP CONSTRAINT FK_City
Команда DROP TABLE
Удаление ранее созданной таблицы производится командой DROP TABLE:
DROP TABLE Departments
HIBERNATE
Hibernate – инструмент объектно-реляционного отображения (Object-Relational Mapping, ORM) данных для Java-окружения. Целью Hibernate является освобождение разработчика от большинства общих работ, связанных с задачами получения, сохранения данных в СУБД. Эта технология помогает удалить или инкапсулировать зависящий от поставщика SQL-код, а также решает стандартную задачу преобразования типов Java-данных в типы данных SQL и наборов данных из табличного представления в объекты Java-классов.
Установка
1. Загрузить и установить сервер баз данных MySQL с сервера http://dev.mysql.com/
2. Загрузить и подключить Hibernate с сервера
http://hibernate.org/
3. Загрузить и подключить JDBC-драйвер, используемой базы данных
в tomcat/common/lib (или, в случае использования Ant, в папку lib проекта), в данном случае mysql-connector-java-3.1.12.jar. Обычно JDBC-драйвер предоставляется на сайте разработчика сервера баз данных.
Библиотека hibernate3.1.3.jar является основной. Кроме нее, устанавливается еще целый ряд необходимых библиотек из дистрибутива Hibernate,
а именно:
cglib.jar, commons-collections.jar, commons-logging.jar, jta.jar, dom4j.jar, log4j.jar, а также библиотеки antlr.jar, asm.jar, asm-attrs.jar для запуска приложения из-под Apache Ant.
dom4j.jar – отвечает за разбор файлов XML-настроек и файла XML-mapping метаданных;
CGLIB (cglib.jar) – эта библиотека используется для генерации кода для расширения классов во время исполнения;
commons-collections.jar – вспомогательная библиотека из проекта Apache Jakarta Commons;
commons-logging.jar – вспомогательная библиотека для журналирования событий из проекта Apache Jakarta Commons;
ODMG4 (odmg.jar) – пакет, необходимый для mapping-коллекций;
EHCache (ehcache.jar) – кэш-провайдер второго уровня;
ANother Tool for Language (antlr.jar) – инструмент, позволяющий создавать трансляторы, компиляторы и распознаватели для текстов, содержащие Java, C#, C++ или Python код;
ASM (asm.jar, asm-attrs.jar) – библиотека, предназначенная для динамического создания классов, а также их динамической корректировки.
Создание простейшего приложения
Hibernate использует JDBC-соединения для вызова SQL-запросов к базе данных, поэтому необходимо указать настроенный пул JDBC-соединений либо использовать один из поддерживаемых пулов, встроенных в Hibernate (C3P0, Proxool). Tomcat настраивает и дает доступ к пулу соединений, используя встроенный DBCP пул, а Hibernate запрашивает данные соединения через интерфейс JNDI. Tomcat связывает пул соединений с JNDI, объявляя ресурс в свой основной конфигурационный файл Tomcat 5.5/conf/server.xml, в виде:
<Context path="/test_db" docBase="test_db">
<Resource name="jdbc/test_db" scope="Shareable"
type="javax.sql.DataSource"/>
<ResourceParams name="jdbc/test_db">
<parameter>
<name>factory</name>
<value>org.apache.commons.dbcp.BasicDataSourceFactory </value>
</parameter>
<Context/>
Далее следует настроить конфигурационный файл Hibernate на использование пула соединений. Этот файл должен располагаться в каталоге
WEB-INF/classes и иметь имя hibernate.cfg.xml.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.datasource"> java:comp/env/jdbc/test_db</property>
<property name="show_sql">true</property>
<property name="dialect"> net.sf.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.connection.password">pass</property>
<property name="hibernate.connection.username">root</property>
<mapping resource="courses/hiber/Course.hbm.xml"/>
<mapping resource="courses/hiber/Student.hbm.xml"/> </session-factory>
</hibernate-configuration>
Здесь указан способ получения JDBC-соединения, включено логирование команд SQL, настроен диалект SQL.
Для настройки параметров работы Hibernate вместо конфигурационного XML-файла можно использовать файл hibernate.properties в WEB-INF/classes (в случае, если приложение разбито по пакетам, необходимо это учитывать, чтобы данный файл был доступен):
##Данная директива позволяет делать автозамену значений ##полей класса в другие значения для удобства хранения
в ##базе данных
hibernate.query.substitutions true 1, false 0, yes 'Y',
no 'N'
##Прописывается JDBC-драйвер для базы данных MySQL
hibernate.dialect net.sf.hibernate.dialect.MySQLDialect
hibernate.connection.driver_class com.mysql.jdbc.Driver
##Прописывается адрес для подсоединения к серверу
##баз данных
##Формат подключения следующий:
##hibernate.connection.url ##jdbc:mysql://АДРЕС_МАШИНЫ:НОМЕР_ПОРТА/ИМЯ_БАЗЫ_ДАННЫХ? ##autoReconnect=Автоматически переподключатся к базе данных ##или нет, при потере соединения. Этот параметр должен быть ##выставлен в true, т.к. отключение от БД происходит в ##случае 30-ти минутного простоя.
##Параметр useUnicode=true отвечает за использование
##кодировки unicode при работе с БД.
##Параметр characterEncoding=Cp1251 отвечает за кодировку ##при передаче данных в базу данных
hibernate.connection.url jdbc:mysql://localhost:3306/test_db?autoReconnect =true&useUnicode=true&characterEncoding=Cp1251
##Имя пользователя при подключении к БД
hibernate.connection.username root
##Пароль при подключении к БД
hibernate.connection.password pass
##Размер пула соединений к БД
##Обычно используется значение в 50 соединений при
##создании реальных проектов
hibernate.connection.pool_size 50
##Кеширование запросов. Кеш повышает быстродействие при ##использовании большого числа однотипных запросов к базе ##данных
hibernate.statement_cache.size 20
##Директива, которая используется при debug. Результатом ##является то, что все запросы, которые осуществляются
к базе ##данных, будут показаны (или нет) разработчику.
hibernate.show_sql true
Как еще одну альтернативу (не очень удачную) можно рассматривать метод, генерирующий объект java.util.Properties. Например, в виде:
private Properties createProperties() {
Properties properties = new Properties();
properties.setProperty(
"hibernate.dialect",
"net.sf.hibernate.dialect.MySQLDialect");
properties.setProperty(
"hibernate.connection.driver_class",
"com.mysql.jdbc.Driver");
properties.setProperty(
"hibernate.connection.url",
"jdbc:mysql://localhost/test_db");
properties.setProperty(
"hibernate.connection.username", "root");
properties.setProperty(
"hibernate.connection.password", "pass");
return properties;
}
Создание POJO-классов
В примере, рассматривающем учебные курсы и студентов, их посещающих, будут созданы следующие классы POJO (Plain Ordinary Java Objects):
Класс Course – хранит информацию об учебном курсе (название курса
и список студентов, записанных на курс);
Класс Student – содержит информацию о студенте (имя, фамилия).
Кроме указанных выше полей, оба эти класса имеют поле id. Это свойство содержит значение столбца первичного ключа в таблице базы данных. Такое свойство может называться любым именем, и иметь любой примитивный тип,
тип класса-оболочки базового типа, а также типы java.lang.String
и java.util.Date. Свойство-идентификатор не является обязательным для класса, можно не создавать его и дать Hibernate самостоятельно следить за идентификацией объекта.
/* пример # 1: POJO-класс сущности : Course.java */
package courses.hiber;
import java.util.Set;
public class Course {
private Integer id;
private String title;
private Set students;
public Integer getId() {
return id;
}
protected void setId(Integer id) { /*в данном случае использовать protected как спецификатор доступа, поскольку данное поле не будет определяться вручную, а значение генерируется автоматически в соответствии с mapping-файлом. Сама технология Hibernate имеет доступ к полям и методам, имеющим любые спецификаторы доступа(friendly, public, protected, private)*/
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Set getStudents() {
return students;
}
public void setStudents(Set students) {
this.students = students;
}
}
/* пример # 2: POJO-класс сущности : Student.java */
package courses.hiber;
public class Student {
private Integer id;
private String lastname;
private String login;
private String password;
public Integer getId() {
return id;
}
protected void setId(Integer id) {
this.id = id;
}
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login;
}
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
После создания таблиц в базе данных задается соответствие между POJO-классами и таблицами. Объектно-реляционный mapping описывается в виде XML-документа hbm.xml в каталоге, содержащем *.class файл соответствующего класса: для Tomcat - это WEB-INF\classes\’каталог_пакета’, а для Ant - bin\’каталог_пакета’. Эти файлы создаются для того, чтобы обеспечить Hibernate данными о том, какие объекты по каким таблицам базы данных создавать и как их инициализировать. Язык описания mapping-файла ориентирован на Java, следовательно, mapping конструируется вокруг объявлений java-классов, а не таблиц БД.
/* пример # 3: Mapping-файл для класса courses.hiber.Course */
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<classname="courses.hiber.Course"table="course">
<idname="id"column="id"type="java.lang.Integer">
<generatorclass="increment"/>
</id>
<propertyname="title"type="java.lang.String"/>
<setname="students"table="course_student"
cascade="all">
<keycolumn="course_id"/>
<many-to-manycolumn="student_id"class="courses.hiber.Student"/>
</set>
</class>
</hibernate-mapping>
/* пример # 4: Mapping-файл для класса courses.hiber.Student */
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "- //Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="courses.hiber">
<class name="Student" table="student">
<idname="id"column="id" type="java.lang.Integer">
<generator class="native"/>
</id>
<property name="lastname" type="java.lang.String"/>
<propertyname="login"type="java.lang.String"/>
<propertyname="password"type="java.lang.String"/>
</class>
</hibernate-mapping>
Пояснения по приведенному коду:
<class name="courses.hiber.Course"> – необходимо указать класс, который будет использоваться при работе с указанной ниже таблицей базы данных. Причём есть две возможности указать пакет расположения класса: либо явно указать полное имя класса, либо указать атрибут package в теге <hibernate-mapping>;
table="course" – указывается таблица на сервере баз данных, к которой будет вестись обращение. Если данный атрибут не указан, то за название таблицы берется название класса, т.е. в данном случае COURSE, поэтому в данном примере атрибут table можно было опустить;
<id name="id" column="id" type="java.lang.Integer">
<generator class="native"/>
</id> – указывается соответствие поля класса и столбца в базе данных, которые являются основными идентификаторами, т.е. уникальны, не имеют значений null. Тег <generator> указывает способ генерация значений в данном столбце, возможные его значения: increment, identity, sequence, hilo,, seqhilo, uuid, guid, native, assigned, select, foreign;
<property name="title" column="column" type="java.lang.String"/> – указывается соответствие полей класса
и столбцов базы данных. В mapping-файле несколько параметров может быть выделено как id. Это позволяет получать объекты из БД, удалять, создавать их без написания SQL-запросов. Процесс реализации будет продемонстрирован ниже.
Кроме того, следует обратить внимание на следующие теги и их параметры:
<many-to-one name="propertyName" column="column_name"class="ClassName"lazy="proxy|no-proxy|false"> – данный тег используется для указания связи таблиц (классов). К примеру, объект одного класса содержит ссылку на объект другого класса, а последний, в свою очередь, содержит коллекцию объектов первого класса. Параметры name и column аналогичным параметрам в предыдущих тегах и несут такой же смысл. Атрибут class указывает, какой класс будет связан с данным. Параметр lazy в большей части случаев является существенным, т.е. его необходимо выставлять вручную, поскольку значение по умолчанию, proxy, означает, что объекты класса, с которым связан данный, не будут автоматически загружены в память.
<set name="propertyName" inverse="true">
<key column="foreignId"/>
<one-to-many class="ClassName"/>
</set> - является интерпретацией коллекции «множество».
Необходимо строгое соответствие между столбцами таблиц базы данных
и mapping-файлами.
При изменении базы данных необходимо следить за изменением mapping-файлов и соответствующих им классов, т.к. такие ошибки достаточно сложно выявить.
Более подробно о рассмотренных и прочих тегах и их атрибутах вы можете прочитать в документации по технологии Hibernate, которая доступна на сайте разработчика.