Выскажи свое мнение
Категории раздела
Статьи с других форумов [25]
Наш опрос
Пользуетесь ли Вы Твиттером?
Всего ответов: 27
Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0
Форма входа
Главная » Статьи » Чужие статьи » Статьи с других форумов

Основы Hibernate Часть №1


Совсем недавно, по роду свой деятельности, мне пришлось столкнуться с таким понятием как ORM - (англ. Object-relational mapping). В двух словах ORM - это отображение объектов какого-либо объектно-ориентированного языка в структуры реляционных баз данных. Именно объектов, таких, какие они есть, со всеми полями, значениями, отношениями м/у друг другом.

ORM-решением для языка Java, является технология Hibernate, которая не только заботится о связи Java классов с таблицами базы данных (и типов данных Java в типы данных SQL), но также предоставляет средства для автоматического построения запросов и извлечения данных и может значительно уменьшить время разработки, которое обычно тратится на ручное написание SQL и JDBC кода. Hibernate генерирует SQL вызовы и освобождает разработчика от ручной обработки результирующего набора данных и конвертации объектов, сохраняя приложение портируемым во все SQL базы данных.
Итак, перед нами стоит задача написать небольшое приложение, которое бы осуществляло простое взаимодействие с базой данных, посредством технологии Hibernate.
Немного подумав, решил написать так называемый «Виртуальный автопарк». Суть парка такова: есть автобусы, есть маршруты и есть водители. Автобусы и маршруты связаны отношением один ко многим, т.е. на одном маршруте может кататься сразу несколько автобусов. Водители и автобусы связаны отношением многие ко многим, т.е. один водитель может водить разные автобусы и один автобус могут водить разные водители. Вроде ничего сложного.
Вот схема базы данных.
За качество не ругайте - под рукой не оказалось нормального инструмента таблички рисовать...
Вот ссылка на дамп, снятый с базы, вдруг кто-то решит все это дело поднять :)
Приступаем к коду. Во первых нам необходимо описать классы наших сущностей, т.е. класс автобуса, водителя и маршрута.
Класс автобус.
package logic;
import java.util.Set;
import java.util.HashSet;

public class Bus {
  private Long id;
  private String number;
  private Set drivers = new HashSet();
  private Long route_id;

  public Bus() {
  }
  public void setId(Long id) {
    this.id = id;
  }
  public void setNumber(String number) {
    this.number = number;
  }
  public void setDrivers(Set drivers) {
    this.drivers = drivers;
  }
  public void setRoute_id(Long route_id) {
    this.route_id = route_id;
  }
  public Long getId() {
    return id;
  }
  public String getNumber() {
    return number;
  }
  public Set getDrivers() {
    return drivers;
  }
  public Long getRoute_id() {
    return route_id;
  }
}


* This source code was highlighted with Source Code Highlighter.
Класс водитель.
package logic;

import java.util.Set;
import java.util.HashSet;

public class Driver {
  private Long id;
  private String name;
  private String surname;
  private int age;
  private Set busses = new HashSet();

  public Driver() {
  }
  public void setBusses(Set busses) {
    this.busses = busses;
  }
   public Set getBusses() {
    return busses;
  }
  public void setId(Long id) {
    this.id = id;
  }
  public void setName(String name) {
    this.name = name;
  }
  public void setSurname(String surname) {
    this.surname = surname;
  }
  public void setAge(int age) {
    this.age = age;
  }
  public Long getId() {
    return id;
  }
  public String getName() {
    return name;
  }
  public String getSurname() {
    return surname;
  }
  public int getAge() {
    return age;
  }
}


* This source code was highlighted with Source Code Highlighter.
И класс маршрут.
package logic;

import java.util.Set;
import java.util.HashSet;

public class Route {
  private Long id;
  private String name;
  private int number;
  private Set busses = new HashSet();

  public Route(){
  }
  public void setId(Long id) {
    this.id = id;
  }
  public void setName(String name) {
    this.name = name;
  }
  public void setNumber(int number) {
    this.number = number;
  }
  public void setBusses(Set busses) {
    this.busses = busses;
  }
  public Long getId() {
    return id;
  }
  public String getName() {
    return name;
  }
  public int getNumber() {
    return number;
  }
  public Set getBusses() {
    return busses;
  }
}


* This source code was highlighted with Source Code Highlighter.
Заметьте, что все классы сущностей должны соответствовать Java naming conventions, т.е. у них должны быть обязательно геттеры, сеттеры и конструктор по умолчанию. Ничего сложного :)

Теперь для наших классов необходимо описать маппинг в виде xml-файлов, эти файлы как раз и будут отвечать за взаимодействие наших объектов с Hibernate и с базой данных.
Bus.hbm.xml
<hibernate-mapping>
  <class name="logic.Bus" table="busses">
    <id column="bus_id" name="id" type="java.lang.Long">
      <generator class="increment"/>
    </id>
    <property column="number" name="number" type="java.lang.String"/>
    
    <set name="drivers" table="busDriver" lazy="false">
      <key column="bus_id"/>
      <many-to-many column="driver_id" class="logic.Driver"/>
    </set>

  </class>
</hibernate-mapping>


* This source code was highlighted with Source Code Highlighter.
Driver.hbm.xml
<hibernate-mapping>
  <class name="logic.Driver" table="drivers">
    <id column="driver_id" name="id" type="java.lang.Long">
      <generator class="increment"/>
    </id>
    <property column="name" name="name" type="java.lang.String"/>
    <property column="surname" name="surname" type="java.lang.String"/>
    <property column="age" name="age" type="java.lang.Integer"/>

    <set name="busses" table="busDriver" lazy="false">
      <key column="driver_id"/>
      <many-to-many column="bus_id" class="logic.Bus"/>
    </set>


  </class>
</hibernate-mapping>


* This source code was highlighted with Source Code Highlighter.
Route.hbm.xml
<hibernate-mapping>
  <class name="logic.Route" table="routes">
    <id column="route_id" name="id" type="java.lang.Long">
      <generator class="increment"/>
    </id>
    <property column="name" name="name" type="java.lang.String"/>
    <property column="number" name="number" type="java.lang.Integer"/>

    <set name="busses" lazy="false">
      <key column="route_id"/>
      <one-to-many class="logic.Bus"/>
    </set>

  </class>
</hibernate-mapping>


* This source code was highlighted with Source Code Highlighter.
Теперь давайте немного разберемся в этих xml-ных макаронах :)

  • Тег hibernate-mapping я думаю понятен, тут ничего говорить не стоит.

  • Тег class имеет два параметра: параметр name - Имя класса (необходимо указывать полный путь с учетом структуры пакетов) и параметр table - имя таблицы в базе данных, на которую будет маппиться наш класс.

  • Тег id описывает идентификатор. Параметр column указывает на какую колонку в таблице будет ссылаться поле id нашего объекта, так же указываем класс и указываем generator, который отвечает за генерацию id.

  • Тег property описывает простое поле нашего объекта, в качестве параметров указываем имя поля, его класс и имя колонки в таблице.

  • Тег set описывает поле в котором содержится некий набор(коллекция) объектов. Тег содержит параметр name - имя поля нашего объекта, параметр table - имя таблицы связи(в случае отношения многие ко многим) и параметр lazy. Lazy, если меня не подводит моя память, с английского - ленивый. Так называемые ленивые коллекци, сейчас постараюсь объяснить понятнее. Когда мы в параметре lazy указываем значечение false, то у нас при получении объекта Route из базы вместе с объектом достается и коллекция объектов Bus, так как busses это поле объекта Route. А если в качестве параметра мы указываем значение true, то коллекция объектов Bus не вытаскивается, для ее получения надо явно вызывать метод route.getBusses(). Вот предположим такой очень хороший пример. Есть объект город, в него входит массив районов, в каждый район - массив улиц, в каждую улицу - массив домов и так далее до людей, живущих в квартирах. Предположим мы хотим вытянуть из базы названия районов. Если укажем lazy = false,то помимо районом у нас вытянется еще огромный объем "ненужных" данных, если же lazy = true, то мы получим то что надо и ничего лигнего.

  • Тег key имеет параметр column, который говорит, на какую колонку в таблице связи будет ссылаться поле нашего объекта.

  • Тег many-to-many описывает связь типа многие ко многим, в качестве параметров тег использует column - имя колонки второй колонки в таблице связи и параметр class, указывающий какого класса будут объеты на той стороне.
Теперь создадим главный конфигурационный файл hibernate.cfg.xml, файл, откуда он будет дергать всю необходимую ему информацию.
<hibernate-configuration>

  <session-factory>
    <property name="connection.url">jdbc:mysql://localhost/autopark</property>
    <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
    <property name="connection.username">root</property>
    <property name="connection.password"/>
    <property name="connection.pool_size">1</property>
    <property name="current_session_context_class">thread</property>
    <property name="show_sql">true</property>
    <property name="dialect">org.hibernate.dialect.MySQL5Dialect</property>

    <mapping resource="logic/Bus.hbm.xml"/>
    <mapping resource="logic/Driver.hbm.xml"/>
    <mapping resource="logic/Route.hbm.xml"/>

  </session-factory>
  
</hibernate-configuration>


* This source code was highlighted with Source Code Highlighter.
Тут я не буду особо вдаваться в объяснение, думаю многим и так все понятно :) Скажу, что надо только в конце не забыть добавить тег mapping и указать в качестве параметра resources файлы конфигурации ваших бинов.
Теперь создадим класс, который будет хавать наш конфиг-файл и возвращать нам объект типа SessionFactory, который отвечает за создание hibernate-сессии.
package util;

import org.hibernate.cfg.Configuration;
import org.hibernate.SessionFactory;

public class HibernateUtil {
  private static final SessionFactory sessionFactory;
    static {
      try {
        sessionFactory = new Configuration().configure().buildSessionFactory();
      } catch (Throwable ex) {
        System.err.println("Initial SessionFactory creation failed." + ex);
        throw new ExceptionInInitializerError(ex);
      }
    }

    public static SessionFactory getSessionFactory() {
      return sessionFactory;
    }
}


* This source code was highlighted with Source Code Highlighter.
Теперь нам осталось разобраться со взаимодействием нашего приложения с базой данных. Для этого для каждого класса-сущности, определим интерфейс, содержащий набор необходимых методов (Я приведу только один интерфейс и одну его реализацию, интерфейсы и реализации для др. классов подобны этим.)
package DAO;
import logic.Bus;
import logic.Driver;
import logic.Route;
import java.util.Collection;
import java.sql.SQLException;

public interface BusDAO {
  public void addBus(Bus bus) throws SQLException;
  public void updateBus(Long bus_id, Bus bus) throws SQLException;
  public Bus getBusById(Long bus_id) throws SQLException;
  public Collection getAllBusses() throws SQLException;
  public void deleteBus(Bus bus) throws SQLException;
  public Collection getBussesByDriver(Driver driver) throws SQLException;
  public Collection getBussesByRoute(Route route) throws SQLException;

}


* This source code was highlighted with Source Code Highlighter.
Статья beg'a habrahabr.ru
Категория: Статьи с других форумов | Добавил: MN (22.07.2008)
Просмотров: 2749 | Рейтинг: 0.0/0
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Поиск
Друзья сайта
  • Официальный блог
  • Сообщество uCoz
  • FAQ по системе
  • Инструкции для uCoz
  • Copyright MyCorp © 2025Конструктор сайтовuCoz