Логин:   Пароль:






Новости
Рассылки
Форум
Поиск


Java
- Апплеты
- Вопрос-ответ
- Классы
- Примеры
- Руководства
- Статьи
- IDE
- Словарь терминов
- Скачать

Мобильная Java
- Игры
- Примеры
- Статьи
- WAP, WML и пр.

JavaScript
- Вопрос-ответ
- Примеры
- Статьи

Веб-мастеринг
- HTML
- CSS
- SSI

Разминка для ума
Проекты
Книги
Ссылки
Программы
Юмор :)




Rambler's Top100
Rambler's Top100

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

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

Для начала о себе я не являюсь дипломированным или сертифицированным специалистом по 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 мы должны выполнить несколько шагов по инициализации.

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

Начнем с начала, 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

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

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








Warning: mysql_connect() [function.mysql-connect]: Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2) in /pub/home/javaport/javaportal/books/show2b.php on line 11

Warning: mysql_db_query() [function.mysql-db-query]: Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2) in /pub/home/javaport/javaportal/books/show2b.php on line 19

Warning: mysql_db_query() [function.mysql-db-query]: A link to the server could not be established in /pub/home/javaport/javaportal/books/show2b.php on line 19

Warning: mysql_fetch_array(): supplied argument is not a valid MySQL result resource in /pub/home/javaport/javaportal/books/show2b.php on line 30
Узнай о чем ты на самом деле сейчас думаешь тут.


[an error occurred while processing this directive]



Warning: mysql_connect() [function.mysql-connect]: Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2) in /pub/home/javaport/javaportal/news/worldnews.php on line 91

Warning: mysql_db_query() [function.mysql-db-query]: Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2) in /pub/home/javaport/javaportal/news/worldnews.php on line 93

Warning: mysql_db_query() [function.mysql-db-query]: A link to the server could not be established in /pub/home/javaport/javaportal/news/worldnews.php on line 93

Warning: mysql_fetch_array(): supplied argument is not a valid MySQL result resource in /pub/home/javaport/javaportal/news/worldnews.php on line 95