Hibernate для чайников. Часть 1.

Автор: content Понедельник, Апрель 9th, 2012 Нет комментариев

Рубрика: Язык Java

Для начала о себе я не являюсь дипломированным или сертифицированным специалистом по java и hibernate, поэтому все что будем мною изложено в данной статье было подчеркнуто из документации и личного опыта.

Начинаем. Для чего все это нужно. Hibernate — это механизм отображения в реляционной базе данных объектов java. Используемые для работы библиотеки можно загрузить с сайта http://hibernate.org. Нам понадобятся Hibernate Core непосредственно сама библиотека, и Hibernate Annotations для поддержки описаний объектов (можно обходиться и без нее но тогда нужно использовать другие методы для инициализации отображаемых объектов). Прямых ссылок на загрузку я не даю потому как проект постоянно развивается и ссылки могут устареть, думаю с загрузкой с сайта проблем возникнуть не должно. Также нужен запущенный SQL сервер (какой вам больше нравится), и ясно дело jdbc драйвера на него.

Не мастер я объяснять поэтому сразу к примерам на них все и поймете. Допустим вы хотите написать небольшое приложение для хранения каталога фильмов в базе данных. Для в Hibernate это будет выглядеть следующим образом. Создадим пару классов для работы с данными:

// Video.java
package org.media;

public class Video {

private Long id;
private String description;

public void setId(Long id){this.id = id;}
public Long getId(){return id;}
….
}
// Actor.java
package org.media;

public class Actor {

private Long id;
private String name;
private Date birthday;

public void setId(Long id){this.id = id;}
public Long getId(){return id;}
….
}
//Cast.java
package org.media;

public class Cast {

private Long id;
private Video video;
private Actor actor;

public void setId(Long id){this.id = id;}
public Long getId(){return id;}
….
}

Структура вроде понятна фильмы, актеры и связка актеры которые снимались в фильме. Оговорюсь сразу что тип реквизита должен быть обязательно объект, а не базовые типы как int, long, boolean, вместо них следует использовать Integer, Long, Boolean. Два слова для тех кто собирается хранить данные с фиксированной дробной частью (ака денежные единицы) используете для этих целей BigDecimal. Начнем издеваться над этими тремя объектами для начала оговорюсь что я буду использовать аннотации поэтому вам понадобиться jdk 1.5 и дополнительный пакет hibernate-annotations. Начнем для начала нам нужно определить что эти обекты будут храниться (отображаться) в базе данных это достигается добавлением в код следующего

// Video.java
package org.media;

@Entity
@Table(name= «video»)
public class Video {

@Entity говорит о том что этот объект будет обрабатываться hibernate, @Table(name= «video») , что он будет храниться в таблице video.

Особенностью работы hibernate является то что каждый хранимый объект должен иметь уникальный ключ (идентификатор), в нашем случае этим ключем является реквизит private Long id, чтобы правильно определиться для hibernate этот реквизит добавляем следующее :

….
public class Video {
@Id
@Column(name= «id»)
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String description;

что мы при это получаем, @Id говорит о том что следующий реквизит является ключем для текущего объекта, @Column(name= «id») — необязательная запись определяет имя колонки для хранения ключа, и @GeneratedValue(strategy = GenerationType.AUTO) используется в том случае если вы хотите чтобы hibernate при создании новых объектов сам заполнял значение ключа (подробнее читать в документации), т.е. если вы не против устанавливать значение id вручную данное поле можно опустить. движемся дальше к простым полям с данными

….
private Long id;
@Column(name= «description», length=64)
private String description;

Ну здесь и так все понятно текущий реквизит будет храниться в нашей таблице в колонке с именим description и длинна этого поля будет составлять 64 символа.

В итоге получаем следующее :

// Video.java
package org.media;

@Entity
@Table(name= «video»)
public class Video {
@Id
@Column(name= «id»)
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(name= «description», length=64)
private String description;

public void setId(Long id){this.id = id;}
public Long getId(){return id;}
….
}

Опуская импорт и реализацию гетеров и сетеров, мы имеем класс готовый для отображения в hibernate, т.е. нам потребовалось пара описаний для самого класса, отдельно описание для реквизита ключа, и описание для стандартных реквизитов. Движемся дальше. в ряде случаев, например для реквизитов типа Data, Hibernate требует указание дополнительных аннотаций:

// Actor.java
package org.media;

private String name;
@Column(name= «birthday»)
@Temporal(value=TemporalType.DATE)
private Date birthday;

Добавившеяся новая аннотация @Temporal(value=TemporalType.DATE) говорит о том, что реквизит будет использоваться для хранения даты, также есть варианты хранения времени и даты и времени. Обращаю внимание что Hibernate не выполняет приведение типа дата автоматически, т.е. в нашем случае при birthday=new Date(); birthday хранит и дату и время, и только после сохранения и повторной загрузки время будет усечено.

Теперь непосредственно осталось самое вкусное — хранение ссылок на пользовательские классы. Эта операция не требует ничего сверхестественного, только для пользовательских классов используются специфические аннотации и именно связи между объектами, всего их три ManyToOne, ManyToMany, OneToOne. Последние две рассматривать не будем если кому интересно все есть в документации. Приступим к нашему примеру.

//Cast.java

public class Cast {
//Все как и раньше
….
private Long id;
@ManyToOne
@JoinColumn(name= «video»)
private Video video;
@ManyToOne
@JoinColumn(name= «actor»)
private Actor actor;
….
}

Собственно и все при помощи @ManyToOne мы выполняем привязку объектов друг к другу, @JoinColumn(name= «actor») определяет имя поля в таблице (если не указывать имя полю будет присвоено автоматически, потом в таблица сложно будет разобраться поэтому я предпочитаю указывать все явно).

Ну что можно сказать наши объекты готовы дело за малым начать их использование.

Для работы с Hibernate мы должны выполнить несколько шагов по инициализации.

Инициализировать базу данных для работы
Определить объекты которые будут отображаться в базе данных
Непосредственно начать работу с данными

Начнем с начала, Hibernate для своей работы требует специальный файл конфигурации, к слову вместо аннотаций принято использовать конфигурацию классов в этом файле или других внешних, которые все равно импортируются в нем. Имя этого файла hibernate.cfg.xml, располагаться он должен в самом корне дерева классов. Он представляет из себя правильных xml документ следующего вида

<!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.driver_class»>org.postgresql.Driver</property>
<property name=»connection.url»>jdbc:postgresql://127.0.0.1/media</property>
<property name=»connection.username»>media</property>
<property name=»connection.password»>123456</property>
<property name=»connection.pool_size»>1</property>
<property name= «cache.provider_class»>
org.hibernate.cache.NoCacheProvider
</property>
<property name=»dialect»>org.hibernate.dialect.PostgreSQLDialect</property>
<property name=»show_sql»>true</property>
<property name=»hbm2ddl.auto»>update</property>
<property name=»current_session_context_class»>thread</property>
</session-factory>
</hibernate-configuration>

Как видите большинство свойств перекликаются с подобными в JDBC. Коснемся только важных для нас свойств connection.driver_class – драйвер для подключения к БД, connection.url – адрес для подключения, connection.username – имя пользователя имеющего право доступа к БД, connection.password – ну куда уж без него. Все покончили с файлом конфигурации, начинаем его использование, т.е. на данном этапе становиться ясно что доступ к БД определяется этим файлом.

Теперь непосредственно к реализации. Создаем служебный класс например HibernateUtil и добавляем в него следующие строки:

static{
try{
AnnotationConfiguration aconf = new AnnotationConfiguration()
.addAnnotatedClass(Video.class)
.addAnnotatedClass(Actor.class)
.addAnnotatedClass(Cast.class);
Configuration conf = aconf.configure();

На данном этапе мы загрузили данные из файла конфигурации

Configuration conf=aconf.configure();

и навязали на его голову работу с нашими классами посредством .addAnnotatedClass(…)

Практически все. Hibernate для работы реализует механизм фактори (не знаю как перевести), через него мы и будем работать с нашими данными и именно создавать Сессии подключения для доступа к данным.

Вот наша фактори, ее можно инициализировать в статическом блоке. На данном шаге в базе данных будут созданы необходимые для работы таблицы и т.п., но есть одно «но» ,база данных должна уже быть создана до настоящего шага.

Ну теперь понеслась, сохранение данных программы

Video video = new Video();
video.setId();
video.setDescription(«Калигула»);

я подразумеваю что сеттер вы сами написали

Actor actor – new Actor();
actor.setId(new Long(1));

Представим что я не указывал для актеров @GeneratedValue(strategy = GenerationType.AUTO)

actor.setName(«Телка из массовки звать Маня»);
Cast cast = new Cast();
cast.setVideo(video);
cast.setActor(actor);
Session session = factory.openSession();
session.beginTransaction();
session.saveOrUpdate(video);
session.saveOrUpdate(actor);
session.saveOrUpdate(cast);
session.getTransaction().commit();
session.close();

После выполнения commit() данные из наших java классов благополучно перекочевали в таблицы SQL сервера. Кому интересно можно сразу посмотреть в вашу БД и полюбоваться наличием заданных данных в ваших таблицах.

Ну, а теперь пару примеров о получении данных из БД. Почему пару, наверное потому что хочу подробнее расписать это все в следующих статьях.

Session session = factory.openSession();
Actor actor = (Actor)session.get(Actor.class,new Long(1));
session.close();
System.out.println(actor.getName());

либо так:

Session session = factory.openSession();
List list = (List

В первом случае получаем актера с id равным 1, во втором список из названий фильмов.

Собственно для первой статьи наверное хватит.

Источник: http://www.javaportal.ru/java/articles/hibernate_annotations.html
Автор: Дмитрий Кузнецов

Оставить комментарий

Чтобы оставлять комментарии Вы должны быть авторизованы.

Похожие посты