Google Code предлагается на следующих языках: English – Español – 日本語 – 한국어 – Português – Pусский – 中文(简体) – 中文(繁體)
API постоянства Java Persistence (JPA) – это стандартный интерфейс хранения объектов, содержащих данные, в реляционной базе данных. Стандарт определяет интерфейсы для аннотации объектов Java, получения объектов с помощью запросов и взаимодействия с базой данных с помощью транзакций. Приложение, использующее интерфейс JPA, может работать с различными базами данных, не используя код базы данных какого-либо производителя. JPA позволяет легко переносить приложение на разные базы данных.
Java SDK App Engine включает реализацию JPA 1.0 для хранилища данных App Engine. Реализация основана на платформе DataNucleus Access Platform. Так как JPA представляет собой стандартный интерфейс для взаимодействия с реляционными базами данных, а хранилище данных App Engine – не реляционная база данных, некоторые функции JPA реализация App Engine поддерживать просто не может. Мы постарались обратить внимание на эти функции везде, где возможно.
Дополнительные сведения о JPA см.в документации Access Platform 1.1. В частности, посмотрите "JPA Mapping" и "JPA API".
Для получения доступа к хранилищу данных с помощью JPA App Engine нужно следующее.
war/WEB-INF/lib/ приложения.persistence.xml должен находится в каталоге war/WEB-INF/classes/META-INF/ приложения и содержать конфигурацию, предписывающую JPA использовать хранилище данных App Engine.Если вы используете плагин Google для Eclipse, первое и третье уже сделано. Мастер нового проекта помещает JAR JPA и хранилища данных в правильное место и процесс сборки выполняет этап "улучшения" автоматически. persistence.xml все равно нужно создать вручную и поместить в war/WEB-INF/classes/META-INF/. Плагин вскоре будет автоматически делать и это.
Если вы используете для сборки проекта Apache Ant, можно использовать задание Ant, включенное в SDK, для выполнения этапа улучшения. Нужно скопировать JAR и создать файл конфигурации при настройке проекта. Подробнее о задании Ant см. Использование Apache Ant.
JAR JPA и хранилища данных включены в Java SDK App Engine. Они находятся в каталоге appengine-java-sdk/lib/user/orm/.
Скопируйте JAR в каталог war/WEB-INF/lib/ приложения.
Убедитесь, что appengine-api.jar находится в каталоге war/WEB-INF/lib/. (Вы могли его уже скопировать при создании проекта.) Плагин App Engine для DataNucleus использует этот JAR для доступа к хранилищу данных.
Интерфейс JPA требует файла конфигурации под названием persistence.xml в каталоге war/WEB-INF/classes/META-INF/ приложения. Этот файл можно создать прямо в этом месте или скопировать его из исходного каталога в процессе сборки.
Создайте файл со следующим содержанием:
<?xml version="1.0" encoding="UTF-8" ?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0">
<persistence-unit name="transactions-optional">
<provider>org.datanucleus.store.appengine.jpa.DatastorePersistenceProvider</provider>
<properties>
<property name="datanucleus.NontransactionalRead" value="true"/>
<property name="datanucleus.NontransactionalWrite" value="true"/>
<property name="datanucleus.ConnectionURL" value="appengine"/>
</properties>
</persistence-unit>
</persistence>
Реализация JPA DataNucleus использует в процессе сборки этап "улучшения" после компиляции, чтобы связать классы данных с реализацией JPA.
Если используется Apache Ant, SDK включает задание Ant, выполняющее этот этап. Подробнее о задании Ant см. Использование Apache Ant.
Выполнить этап улучшения компилированных классов можно из командной строки с помощью следующей команды:
java -cp classpath org.datanucleus.enhancer.DataNucleusEnhancer class-files
classpath должен содержать JAR datastore-core-*.jar, datanucleus-enhancer-*.jar, asm-*.jar и geronimo-jpa-*.jar (где * – соответствующий номер версии каждого JAR) из каталога appengine-java-sdk/lib/tools/, а также все классы данных.
Дополнительные сведения об улучшителе байтового кода DataNucleus см. в документации DataNucleus.
Приложение взаимодействует с JPA с помощью экземпляра класса EntityManager. Этот экземпляр получается за счет создания экземпляра и вызова метода с экземпляром класса EntityManagerFactory. Фабрика использует конфигурацию JPA (идентифицируемую по имени "transactions-optional") для создания экземпляров EntityManager.
Так как экземпляр EntityManagerFactory инициализируется довольно долго, стоит постараться использовать один экземпляр как можно больше. Это нетрудно сделать, создав отдельный класс-оболочку для статического экземпляра следующим образом:
EMF.java
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
public final class EMF {
private static final EntityManagerFactory emfInstance =
Persistence.createEntityManagerFactory("transactions-optional");
private EMF() {}
public static EntityManagerFactory get() {
return emfInstance;
}
}
Приложение использует экземпляр фабрики для создания одного экземпляра EntityManager для каждого запроса, обращающегося к хранилищу данных.
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import EMF;
// ...
EntityManager em = EMF.get().createEntityManager();
EntityManager используется для хранения, обновления и удаления объектов данных и для выполнения запросов к хранилищу данных.
Закончив с экземпляром EntityManager, следует вызвать его метод close(). Использование экземпляра EntityManager после вызова его метода close() – это ошибка.
try {
// ... do stuff with em ...
} finally {
em.close();
}
Все объекты, сохраненные JPA, становятся элементами в хранилище данных App Engine. Тип элемента происходит от простого названия класса (без названия пакета). Каждое постоянное поле класса представляет собой свойство элемента, при этом имя свойства совпадает с именем поля (с сохранением регистра).
Для объявления класса Java как сохраняемого и получаемого их хранилища данных с помощью JPA, присоедините к нему аннотацию @Entity. Например:
import javax.persistence.Entity;
@Entity
public class Employee {
// ...
}
Поля класса данных, которые нужно сохранить в хранилище данных, должны либо иметь тип, постоянный по умолчанию, либо должны быть явно объявлены постоянными. На веб-сайте DataNucleus имеется схема, разъясняющая поведение JPA в отношении постоянства по умолчанию. Для явного объявления поля постоянным следует присоединить к нему аннотацию @Basic, но на настоящий момент это не работает из-за ошибки. В качестве обходного пути можно использовать аннотацию @Enumerated.
import java.util.Date;
import javax.persistence.Enumerated;
import com.google.appengine.api.datastore.ShortBlob;
// ...
@Enumerated
private ShortBlob data;
У поля может быть один из следующих типов:
java.util.List<...>) значений основного типа хранилища данных;@Entity;У класса данных должен быть открытый или закрытый конструктор по умолчанию и одно поле, в котором хранится основной ключ соответствующего элемента хранилища данных. Можно выбирать один из 4 типов полей ключей, каждое из которых использует свой тип значения и аннотации. (Дополнительные сведения см. в статье Создание данных: ключи.) Простейшее поле ключей – длинное целочисленное значение, при первом сохранении объекта в хранилище данных автоматически заполняемое JPA значением, уникальным относительно других экземпляров класса. Ключи с длинным целым числом используют аннотацию @Id и аннотацию @GeneratedValue(strategy = GenerationType.IDENTITY):
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
// ...
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
Вот пример класса данных:
import java.util.Date;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String firstName;
private String lastName;
private Date hireDate;
// Accessors for the fields. JPA doesn't use these, but your application does.
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getHireDate() {
return hireDate;
}
public void setHireDate(Date hireDate) {
this.hireDate = hireDate;
}
}
Следующие функции интерфейса JPA не поддерживаются реализацией App Engine: