null

Начало работы с Java Persistence API

Любое корпоративное приложение имеет в своем составе уровень хранения (Persistence layer). Java Persistence API (JPA) предоставляет разработчикам набор инструментов, позволяющих решать задачи по работе с хранимыми данными и ORM. В данной статье я хочу показать как начать использовать JPA 2.0. 

Прежде всего разберемся с терминологией. Мы разрабатываем некоторое приложение на объектно-ориентированном языке (Java) и хотим сохранить результаты его работы в реляционной базе данных. В связи с этим возникает задача преобразовать объекты (с которыми мы работаем в приложении) в форму, в которой они могут быть сохранены в базе данных и легко (а главное без потерь) извлечены в последующем. В этом нам поможет ORM – object-relational mapping – объектно-реляционное отображение – преобразование данных из объектной формы в реляционную и наоборот.

Перед нами стоит задача отобразить модель, представленную на рисунке ниже:

 

У нас есть схема, состоящая из одной сущности: Customer. Предположим, что это часть предметной области некоторого электронного магазина, описывающая покупателя, имеющего аттрибуты: имя, фамилия, номер кредитной карты.

 

Давайте создадим приложение, которое реализует данную схему в объектном виде, отображает её в реляционную базу данных, а также позволяет осуществлять взаимодействие приложения с БД.

При разработке я использовал Netbeans 6.9.1 (в максимальной комплектации).

 

Начнем с создания и конфигурирования приложения, использующего JPA в Netbeans. Первым делом создадим базу данных, с которой будет работать наше приложение. Для простоты будем использовать Derby DB. Во вкладке Services выберите Databases. В появившемся списке щелкните правой кнопкой мыши по Java DB, в меню выберите Create Database...

 

 

В диалоговом окне необходимо ввести название новой БД, имя пользователя и пароль:

 

 

Нажимаем OK. Мы создали базу данных online_shop, которую будем использовать для нашего проекта. Также автоматически было создано Database Connection, которое потребуется нам в дальнейшем.

 

Теперь перейдем к созданию проекта.

Для этого нажмите File → New Project... → Java → Java Application → Next >

В появившемя окне введите в качестве названия OnlineShop, нажмите Finish. Теперь проект успешно создан.

 

Настала пора реализовать сущность Customer. Так как мы хотим, чтобы в дальнейшем объекты данного класса могли быть сохранены в базе данных (для этого мы и используем JPA), вместо создания обычного класса Customer необходимо создать так называемый класс-сущность (Entity). По сути, Entity – обычный Java-класс, который должен удовлетворять нескольким требованиям. Создадим наш первый Entity. Кликните на созданном проекте правой кнопкой мыши → New → Entity Class... В появившемся диалоговом окне укажите название класса-сущности и пакет, где он будет располагаться:

 

 

Нажмите Next.

 

Для Netbeans создание Entity является сигналом о том, что необходимо использовать ORM-фреймворк. Здесь я хочу отметить одну важную вещь: Java Persistence API сама по себе не является ORM-реализацией. JPA предоставляет единый, стандартизированный интерфейс для работы с ORM-фреймворками. Получается мы работаем со следующей связкой: JPA + Persistence Provider (понятия ORM-реализацией, ORM-фреймворк, Persistence Provider являются синонимами). В качестве Persistence Provider мы можем использовать любой фреймворк, реализующий JPA 2.0, например, EclipseLink, Hibernate, OpenJPA.

 

В появившемся окне нам предлагают настроить ORM-реализацию:

 

 

Особо обратим внимание на следующие установки:

В качестве Persistence Library мы выбрали EclipseLink с указанием, что будем использовать ее вместе с JPA 2.0;

В поле Database Connection мы указали название соединения к созданной нами на первом этапе базе;

 

Нажимаем на Finish, и наш первый класс-сущность готов! Обратите внимание, что кроме создания нового класса, в проект была добавлена библиотека EclipseLink, а также создана директория META-INF с файлом persistence.xml. Помимо всего прочего данный файл содержит информацию об используемом с JPA ORM-фреймворке, а также настройки соединения с базой данных:

 

  <persistence-unit name="OnlineShopPU" transaction-type="RESOURCE_LOCAL">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <class>com.onlineshop.mapping.Customer</class>
    <properties>
      <property name="javax.persistence.jdbc.url" value="jdbc:derby://localhost:1527/online_shop"/>
      <property name="javax.persistence.jdbc.password" value="12345"/>
      <property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.ClientDriver"/>
      <property name="javax.persistence.jdbc.user" value="user"/>
      <property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>
    </properties>
  </persistence-unit>

 

Прежде чем приступить к редактированию созданных классов, необходимо добавить в проект библиотеки для работы с DerbyDB. Их расположение можно узнать, кликнув по пункту Properties в контекстном меню Java DB:

 

 

Библиотеки расположены в папке lib каталога, указанного в Java DB Installation (то есть в моем случае /usr/lib/jvm/java-6-sun/db/lib):

 

 

Ваш путь, скорее всего, будет отличаться от представленного. Далее щелкните правой кнопкой мыши по приложению, в меню выберите Properties, в открывшемся окне перейдите на вкладку Libraries, нажмите Add Library..., нажмите Create, в качестве названия введите Derby и добавьте jar файлы, расположенные в папке lib каталога, где у вас находится Java DB (определение этого пути описано выше). Затем добавьте Derby к остальным библиотекам пректа.

 

Теперь немного модифицируем класс Customer, чтобы он соответствовал требуемой в модели сущности Customer. Добавим необходимые поля и конструкторы (часть автосгенерированного кода опущена):

 

package com.onlineshop.mapping;

import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class Customer implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String name;
    private String surname;
    private Long cardNumber;

    public Customer() {
    }
    
    public Customer(String name, String surname, Long cardNumber) {
        this.name = name;
        this.surname = surname;
        this.cardNumber = cardNumber;
    }

    public Long getId() {
        return id;
    }

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

    …

}

 

Давайте посмотрим, чем сущность Customer отличается от обычного класса.

Перед объявлением класса стоит аннотация @Entity. Она говорит о том, что данный класс должен быть отображен в базу данных. Сущесвуют некоторые требования, которым должен удовлетворять класс-сущность, вот некоторые из них: он не должен быть final, не должен иметь отображаемых аттрибутов с модификатором final, должен содержать конструктор без аргументов (определенный пользователем или по умолчанию), а доступ извне к полям объекта должен осуществляться через соответствующие get и set методы. В нашем примере видно, что класс содержит два конструктора, один из которых без аргументов, а для каждого поля есть свои get и set методы.

Перед объявлением поля id стоят аннотации @Id и @GeneratedValue. Аннотация @Id говорит о том, что аттрибут, перед которым она установлена (в нашем случае id) должен уникально определять экземпляр данного класса. С помощью @GeneratedValue мы указываем стратегию генерации идентификатора (в нашем случае AUTO – решение за нас принимает Persistence Provider).

Во всем остальном Customer – обычный Java-класс.

 

На рисунке ниже показано, как данный класс будет представлен в базе данных:

 

 

При объектно-реляционном отображении созданный нами класс Customer отображается на таблицу CUSTOMER, аттрибуты класса проецируются на столбцы таблицы: аттрибуту id соответствует столбец ID, аттрибуту name соответствует столбец Name, аттрибуту surname – столбец SURNAME, аттрибуту cardNumber – столбец CardNumber. При сохранении некоторого объекта Customer он будет представлен в таблице CUSTOMER одной записью.

 

Теперь для того, чтобы осуществить отображение, осталось модернизировать класс Main. Добавим в Main следующие импорты и поля, а также переопределим метод main (класс Main должен быть сгенерирован Netbeans'ом при создании проекта):

 

package onlineshop;

import com.onlineshop.mapping.Customer;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

public class Main {

    public static final EntityManagerFactory emf = Persistence.createEntityManagerFactory("OnlineShopPU");
    public static EntityManager em = emf.createEntityManager();

    public static void main(String[] args) {
        Customer cust1 = new Customer("Ivan", "Ivanov", 12345L);
        em.getTransaction().begin();
        em.persist(cust1);
        em.getTransaction().commit();
    }

}

 

Чтобы отобразить объект в базу данных, необходимо некоторым образом “сообщить” ORM-фреймворку о нашем желании. В Java Persistence API для этого существует специальный интерфейс – EntityManager, в котором определены все действия, которые мы можем совершить над объектом (объявлены методы для работы с хранимыми данными). ORM-фреймворк реализует этот интерфейс.

 

В нашем примере мы получаем EntityManager через класс Persistence и объект EntityManagerFactory:

 

    public static final EntityManagerFactory emf = Persistence.createEntityManagerFactory("OnlineShopPU");
    public static EntityManager em = emf.createEntityManager();

  

Рассмотрим изменения в методе main:

Сначала мы создаем экземпляр сущности Customer

 

Customer cust1 = new Customer("Ivan", "Ivanov", 12345L);

 

В main через EntityManager мы получаем транзакцию:

 

em.getTransaction().begin();

 

Потом сохраняем сущность в базе:

 

em.persist(cust1);

 

При успешном выполнении метода присходит commit транзакции:

 

em.getTransaction().commit();

 

Теперь можно запустить проект. В результате работы наша объектная модель отображена в реляционную схему, а также в созданную таблицу Customer была занесена запись пользователя Ivan Ivanov (Services → Databases → подключаемся к нашей БД → смотрим таблицу).

 

Подробнее о настройках сущностей, работе с EntityManager и транзакциями, а также о создании связей будет рассказано в следующих статьях данного цикла. Если у вас остались вопросы, или вы хотите больше узнать об ORM и возможностях JPA 2.0, приходите к нам на мастер-классы.

Назад

В сферу интересов входят вопросы, связанные с хранением данных и парадигмами программирования.

Предпочитаю Java и Scala.

Ничего не найдено. n is 0