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






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


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

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

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

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

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




Rambler's Top100
Rambler's Top100

Java: СтатьиИспользование Hibernate Java Persistence

Использование Hibernate Java Persistence

Содержание

1. Основные технологии хранения данных в java
2. Пример реализации Hibernate JPA
2.1. Файл настроек pom.xml проекта для Maven’а
2.2. Настройка параметров подключения к базе данных
2.3. Бизнес - модель данных
2.4. Бизнес - логика
3. Рекомендуемые ресурсы
1. Основные технологии хранения данных в java

Не секрет, что данные являются основой практически для любого проекта. На основе требований к программной системе строится модель данных. В дальнейшем именно с данной моделью работает программа, вводится некоторая информация, производятся вычисления, формируются отчеты и т. д. В процессе развития программных систем проектировались и используются различные системы управления базами данных (СУБД), иерархические, реляционные, объектные и др.

На практике наибольшую популярность получили именно реляционные модели баз данных, хотя в современных методологиях программирования пользуется популярностью объектно-ориентированное программирование. Для стыковки данных технологий разработано множество технологий, спецификаций и фреймворков для маппинга объектов на таблицы реляционных баз данных. Java разработчикам доступно множество технологий для работы с данными это может быть просто сереализация объектов, JDBC, JDO и множество других. Но каждая из них имеет ряд достоинств и недостатков.

Таблица 1. Основные технологии хранения данных в java

Поддержка Сериализация JDBC ORM ODB EJB2 JDO JPA
Java Объекты Есть Нет Есть Есть Есть Есть Есть
Объектно ориентированный подход Есть Нет Есть Есть Нет Есть Есть
Танзакционность Нет Есть Есть Есть Есть Есть Есть
Параллелизм Нет Есть Есть Есть Есть Есть Есть
Работа с наборами данных Нет Есть Есть Есть Есть Есть Есть
Схема данных Нет Есть Есть Нет Есть Есть Есть
Хранение данных в реляционном и нереляционном форматах Нет Нет Нет Нет Есть Есть Нет
Поддержка запросов к данным Нет Есть Есть Есть Есть Есть Есть
Переносимость и жесткие стандарты Есть Нет Нет Нет Есть Есть Есть
Простота Есть Есть Есть Есть Нет Есть Есть

  • Сериализация (Serialization) является встроенным механизмом хранения и передачи объектов в Java. Но для практической работы с данными данный подход мало пригоден, так как требуется извлекать и хранить весь граф объектов, что затрудняет работу с большими объемами данных.

  • Java Database Connectivity (JDBC) Application programming interface (API) разрабатывался для работы с реляционными базами данных. Минусом данной технологии является отсутствие механизмов проекции реляционных данных на объекты, что существенно увеличивает объем кода для данного преобразования.

  • Object-relational mapping (ORM) представляет собой попытки различных поставщиков маппинга объектов на реляционные данные. Отсутствие стандартов привело к созданию множества реализаций данного подхода несовместимых друг с другом. Как результат код становится непереносимым и жестко завязаннм на конкретного поставщика.

  • Object databases (ODB) представляют собой объектные реализации баз данных. Как и в случае с ORM здесь множество реализаций, несмотря на попытки Object Database Management Group (ODMG) создать и стандартизировать API для доступа к объектным базам данных.

  • Enterprise Java Beans (EJB) введены в Enterprise Edition платформе Java уровня предприятия. Сущности EJB 2 представляют собой компоненты для хранения в хранилищах данных. Данная технология позволяет работать с данными на уровне объектов. Варианты физического хранения данных не лимитированы только реляционными базами данных. К сожалению, в стандарте EJB 2.x лимитирован объектно-ориентированный подход. Это выражается в отсутствии или сложности реализации таких важных функций как наследование, полиморфизм и внешние связи объектов. Дополнительные проблемы возникают из-за необходимости применения дорогих и “тяжеловесных” серверов.

  • Спецификация JDO на текущий момент является одной из самых прогрессивных и позволяет использовать не только реляционные, но и объектные хранилища данных.

  • Java Persistence API (JPA) сочетает в себе простоту сериализации объектов с возможностью работы с данными на уровне объектно-ориентированной модели. При этом остается возможность комбинирования доступа к данным как в JDBC на уровне реляционных данных, что позволяет порой достичь большей производительности и гибкости по сравнению с JDO.

На текущий момент существует множество реализаций спецификации JPA, как коммерческих, так и свободных с открытым исходным кодом(open source).

2. Пример реализации Hibernate JPA

Рассмотрим пример использования реализации Hibernate JPA для простых Java Standart Edition (SE) приложений. Идея данного проекта в создании максимально упрощенной архитектуры приложения, т.е. сведению к минимуму количества всевозможных настроек и фокусировании только на поставленной задаче. Java разработчики которые ранее имели дело с Hibernate смогут оценить всю мощь нововведений. Применение аннотаций для внедрения в код служебной информации позволяет освободиться от десятков служебных XML файлов с описанием маппинга java бинов на таблицы баз данных.

Задача: Требуется создать методы для доступа и манипулирования информацией о клиентах.

При помощи утилиты сборки проектов Maven 2 создадим базовую структуру проекта.

Замечание

Применение Maven позволяет абстрагироваться от применяемой разработчиком интегрированной среды разработки. Достаточно вызвать задачу по созданию проекта, например mvn eclipse:eclipse для Eclipse IDE, mvn jdev:jdev для Oracle java Developer или mvn idea:idea для Idea. Вторая особенно ценная функция Maven заключается в создании локального репозитория требуемых java библиотек и автоматического разрешения зависимостей. Это позволяет быстро обновлять библиотеки и устранить дублирование таковых от проекта к проекту. На сайте проекта Maven есть простое руководство, на основе которого можно получить общее представление о приемах работы с данным продуктом. За 10-15 минут можно научиться создавать новые проекты, собирать билды и т.д.

2.1. Файл настроек pom.xml проекта для Maven’а

Файл настроек pom.xml проекта для Maven’а содержит наименование проекта и перечень зависимостей на требуемые библиотеки.

<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.berdaflex</groupId>
  <artifactId>com.berdaflex.jpa_simple_test</artifactId>
  <packaging>jar</packaging>
  <version>1.0</version>
  <name>Maven Quick Start Archetype</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate</artifactId>
      <version>3.2.1.ga</version>
      <type>jar</type>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-annotations</artifactId>
      <version>3.2.1.ga</version>
      <type>jar</type>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-entitymanager</artifactId>
      <version>3.2.1.ga</version>
      <type>jar</type>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>javax.persistence</groupId>
      <artifactId>persistence-api</artifactId>
      <version>1.0</version>
    </dependency>
    <dependency>
      <groupId>commons-lang</groupId>
      <artifactId>commons-lang</artifactId>
      <version>2.3</version>
      <type>jar</type>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>commons-logging</groupId>
      <artifactId>commons-logging-api</artifactId>
      <version>1.0.4</version>
      <type>jar</type>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.14</version>
      <type>jar</type>
      <scope>compile</scope>
    </dependency>
    <!-- JDBC Drivers -->
    <dependency>
      <groupId>postgresql</groupId>
      <artifactId>postgresql</artifactId>
      <version>8.2-504.jdbc3</version>
      <type>jar</type>
      <scope>runtime</scope>
    </dependency>
    <!-- Test -->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
   </dependency>
  </dependencies>
</project>

Утилита Maven создает проект с разделением программного кода на основной код проекта (src/main/java) и код для тестов (src/test/java), что позволяет легко отделить тесты и не включать их в пакет при конечной сборке проекта. На рисунке 1 показана структура созданного java проекта для Eclipse IDE.

Рисунок 1. Структура java проекта com.berdaflex.jpa_simple_test

Структура java проекта com.berdaflex.jpa_simple_test

2.2. Настройка параметров подключения к базе данных

Проект Hibernate позволяет работать с большим разнообразием популярных СУБД. Постоянно ведется тестирование для следующих баз данных:

  • Oracle 8i, 9i, 10g

  • DB2 7.1, 7.2, 8.1

  • Microsoft SQL Server 2000

  • Sybase 12.5 (JConnect 5.5)

  • MySQL 3.23, 4.0, 4.1, 5.0

  • PostgreSQL 7.1.2, 7.2, 7.3, 7.4, 8.0, 8.1

  • TimesTen 5.1, 6.0

  • HypersonicSQL 1.61, 1.7.0, 1.7.2, 1.7.3, 1.8

  • SAP DB 7.3

  • InterSystems Cache&apos; 2007.1

Так же поддерживается еще много других СУБД (при необходимости можно легко расширить базовый список и добавить свою реализацию требуемого диалекта).

Для тестов выберем популярную Open Source базу данных PostgreSql. Для подключения к базе данных создадим конфигурационный файл 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="hibernate.connection.driver_class">
      org.postgresql.Driver
    </property>
    <property name="hibernate.connection.password">
      manager
    </property>
    <property name="hibernate.connection.url">
      jdbc:postgresql://localhost:5432/jpa_test
    </property>
    <property name="hibernate.connection.username">
      postgres
    </property>
    <property name="hibernate.dialect">
      org.hibernate.dialect.PostgreSQLDialect
    </property>
    <property name="current_session_context_class">thread</property>
    <property name="hibernate.hbm2ddl.auto">update</property>

    <mapping class="com.berdaflex.contacts.model.Contact" />
  </session-factory>
</hibernate-configuration>

Параметр " hibernate.hbm2ddl.auto " устанавливаем в значение “true” для того, чтобы объекты базы данных создавались автоматически на основе маппинга в java-hibernate проекте. Для работы с Hibernate и создания конфигурационных файлов удобно использовать подключаемый модуль Hibernate Tools для Eclipse.

2.3. Бизнес - модель данных

Создадим простой POJO (Plain Old Java Object) объект для хранения данных о контактах. Это типовой JavaBean с доступом к приватным полям через get и set методы. Аннотации можно “привязывать” либо к приватным молям, либо к get методам.

/*******************************************************************************
 * Copyright (c) 2005, 2006 Berdaflex Software Systems and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *******************************************************************************/
package com.berdaflex.contacts.model;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

import org.apache.commons.lang.builder.ToStringBuilder;

/**
 * Contact bean.
 * 
 * @author Siarhei Berdachuk
 */
@Entity
@Table(name = "CONTACT")
public class Contact {

  private Long contactId;

  private String firstName;

  private String lastName;

  @Id
  @GeneratedValue
  @Column(name = "CONTACT_ID")
  public Long getContactId() {
    return contactId;
  }

  public void setContactId(Long contactId) {
    this.contactId = contactId;
  }

  @Column(name = "FIRST_NAME")
  public String getFirstName() {
    return firstName;
  }

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

  @Column(name = "LAST_NAME")
  public String getLastName() {
    return lastName;
  }

  public void setLastName(String lastName) {
    this.lastName = lastName;
  }

  @Override
  public String toString() {
    return new ToStringBuilder(this)//
        .append("contactId", getContactId())//
        .append("firstName", getFirstName())//
        .append("lastName", getLastName())//
        .toString();
  }

}

Использование javax.persistence аннотаций, позволяет встроить маппинг сущностей используемой системы хранения (в данном случае hibernate) непосредственно в программый код. Это снижает вероятность появления ошибок и теперь не требуется создавать десятки XML файлов маппинга объектов.

Использование стандартизированного API позволяет сменить при необходимости библиотеку реализации Persistence API, например с Hibernate на Oracle Toplink. Аннотация @Entity указывает, что данный класс является сущностью бизнес модели. Аннотация @Table(name = "CONTACT") указывает на имя таблицы в базе данных. Если имя таблицы совпадает с именем класса, то его можно опустить.

Для идентификации конкретной записи в базе данных требуется ключевое поле (аннотация @Id). Чаще всего для этого используется суррогатный ключ. В данном случае для автоматической генерации ключа указываем аннотацию @GeneratedValue. Маппинг атрибутов java бина на колонки таблиц задается при помощи аннотации @Column в дополнительных параметрах которой можно указать наименование колонки таблицы. Если наименование колонок совпадает с именем атрибута, то его можно опустить.

Классы хранимых (persistence) бинов должны быть перечислены в файле конфигурации (строка <mapping class="com.berdaflex.contacts.model.Contact" />).

2.4. Бизнес - логика

Основным интерфейсом для работы с хранимыми объектами является javax.persistence.EntityManager. Некая единица работы с объектами (unit of work) непосредственно осуществляется в типовой связке:

//Получаем конкретный экземпляр реализации интерфейса EntityManager
EntityManager em = getEntityManager();
//Начинаем тразакцию
em.getTransaction().begin();

//выполняем некоторую обработку бизнес объектов
em.persist(объект);
. . .
//завершаем транзакцию 
em.getTransaction().commit();
em.close();

Для того чтобы упростить задачу получения конкретного экземпляра реализации интерфейса EntityManager создадим класс помощник (helper) HibernateUtil, который будет автоматически инициализировать конфигурацию Ejb3Configuration на основе созданного нами ранее файла конфигурации Hibernate.

/*******************************************************************************
 * Copyright (c) 2005, 2006 Berdaflex Software Systems and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *******************************************************************************/
package com.berdaflex.db.utils;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.ejb.Ejb3Configuration;

public class HibernateUtil {
  public static final Log logger = LogFactory.getLog(HibernateUtil.class
      .getName());

  private static final SessionFactory sessionFactory;

  private static final Ejb3Configuration ejb3Configuration;

  static {
    try {
      // Create the SessionFactory from hibernate.cfg.xml
      sessionFactory = new AnnotationConfiguration().configure()
          .buildSessionFactory();
      ejb3Configuration = new Ejb3Configuration()
          .configure("/hibernate.cfg.xml");
    } catch (Throwable ex) {
      logger.error("Initial SessionFactory creation failed." + ex);
      throw new ExceptionInInitializerError(ex);
    }
  }

  public static SessionFactory getSessionFactory() {
    return sessionFactory;
  }

  public static Ejb3Configuration getEjb3Configuration() {
    return ejb3Configuration;
  }
}

Для получения экземпляра EntityManager теперь можно будет использовать следующую конструкцию:

EntityManager em = HibernateUtil.getEjb3Configuration()
    .buildEntityManagerFactory().createEntityManager();

Пример тестов, код которого можно использовать в создаваемых приложениях.

/*******************************************************************************
 * Copyright (c) 2005, 2006 Berdaflex Software Systems and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *******************************************************************************/
package com.berdaflex.db;

import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.persistence.Query;

import junit.framework.TestCase;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.berdaflex.contacts.model.Contact;
import com.berdaflex.db.utils.HibernateUtil;

/**
 * Simple JPA tests.
 * 
 * @author Siarhei Berdachuk
 */
public class HibernateUtilsTest extends TestCase {
  public static final Log logger = LogFactory.getLog(HibernateUtilsTest.class
      .getName());

  @Override
  protected void setUp() throws Exception {
    super.setUp();

  }

  @Override
  protected void tearDown() throws Exception {
    super.tearDown();
  }

  private void clearData() {
    logger.debug("clear test database");
    EntityManager em = HibernateUtil.getEjb3Configuration()
        .buildEntityManagerFactory().createEntityManager();
    EntityTransaction tx = em.getTransaction();
    tx.begin();
    Query query = em.createQuery(new StringBuilder("delete from ").append(
        Contact.class.getName()).toString());
    query.executeUpdate();
    tx.commit();
    em.close();
  }

  public void testInsertData() {
    clearData();

    EntityManager em = HibernateUtil.getEjb3Configuration()
        .buildEntityManagerFactory().createEntityManager();
    em.getTransaction().begin();

    Long id_500 = null;
    for (int i = 0; i < 1000; i++) {
      Contact newContact = new Contact();
      newContact.setFirstName(new StringBuilder("FName_").append(i)
          .toString());
      newContact.setLastName(new StringBuilder("LName_").append(i)
          .toString());
      em.persist(newContact);
      if (i == 500) {
        id_500 = newContact.getContactId();
      }
    }
    em.getTransaction().commit();

    em.getTransaction().begin();
    Contact testContact = em.find(Contact.class, id_500);
    assertEquals("FName_500", testContact.getFirstName());
    assertEquals("LName_500", testContact.getLastName());
    em.getTransaction().commit();

    em.close();
  }
}

3. Рекомендуемые ресурсы



Автор: Сергей Бердачук
http://www.berdaflex.com
Издание 1.0 2007.03.15

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