1. Обзор
Объекты данных Java — это API, предназначенный для сохранения объектно-ориентированных данных в любой базе данных и предоставления удобного для пользователя языка запросов с использованием синтаксиса Java.
В этой статье мы увидим, как использовать JDO API для сохранения наших объектов в базе данных.
2. Зависимости и настройка Maven
Мы собираемся использовать API DataNucleus JDO, который обновлен и предлагает полную поддержку API JDO 3.2.
Давайте добавим следующую зависимость в наш файл pom.xml
:
<dependency>
<groupId>org.datanucleus</groupId>
<artifactId>javax.jdo</artifactId>
<version>3.2.0-m6</version>
</dependency>
<dependency>
<groupId>org.datanucleus</groupId>
<artifactId>datanucleus-core</artifactId>
<version>5.1.0-m2</version>
</dependency>
<dependency>
<groupId>org.datanucleus</groupId>
<artifactId>datanucleus-api-jdo</artifactId>
<version>5.1.0-m2</version>
</dependency>
<dependency>
<groupId>org.datanucleus</groupId>
<artifactId>datanucleus-rdbms</artifactId>
<version>5.1.0-m2</version>
</dependency>
<dependency>
<groupId>org.datanucleus</groupId>
<artifactId>datanucleus-xml</artifactId>
<version>5.0.0-release</version>
</dependency>
Последние версии зависимостей можно найти здесь: javax.jdo , datanucleus-core , datanucleus-api-jdo , datanucleus-rdbms и datanucleus-xml .
3. Модель
Мы собираемся сохранить наши данные в базе данных, и прежде чем мы сможем это сделать, нам нужно создать класс, который будет использоваться JDO для хранения наших данных.
Для этого нам нужно создать класс с некоторыми свойствами и аннотировать его с помощью @PersistentCapable:
@PersistenceCapable
public class Product {
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.INCREMENT)
long id;
String name;
Double price = 0.0;
// standard constructors, getters, setters
}
Мы также аннотировали наш первичный ключ и выбранную стратегию.
Как только мы создадим наш объект, нам нужно запустить энхансер для генерации байт-кода, необходимого для JDO. Используя Maven, мы можем запустить эту команду:
mvn datanucleus:enhance
Этот шаг является обязательным. В противном случае мы получим ошибку времени компиляции, что класс не расширен.
Конечно, это можно сделать автоматически во время сборки Maven:
<plugin>
<groupId>org.datanucleus</groupId>
<artifactId>datanucleus-maven-plugin</artifactId>
<version>5.0.2</version>
<configuration>
<api>JDO</api>
<props>${basedir}/datanucleus.properties</props>
<log4jConfiguration>${basedir}/log4j.properties</log4jConfiguration>
<verbose>true</verbose>
</configuration>
<executions>
<execution>
<phase>process-classes</phase>
<goals>
<goal>enhance</goal>
</goals>
</execution>
</executions>
</plugin>
Последнюю версию плагина можно найти здесь: datanucleus-maven-plugin
4. Сохраняющиеся объекты
Мы получаем доступ к базе данных с помощью фабрики JDO, которая дает нам менеджер транзакций, отвечающий за выполнение транзакций:
PersistenceManagerFactory pmf = new JDOPersistenceManagerFactory(pumd, null);
PersistenceManager pm = pmf.getPersistenceManager();
Транзакции используются для разрешения отката в случае ошибки:
Transaction tx = pm.currentTransaction();
Мы делаем наши транзакции внутри блока try/catch
:
Product product = new Product("Tablet", 80.0);
pm.makePersistent(product);
В нашем блоке finally
мы определяем эти операции, которые должны выполняться в случае сбоя.
Если по какой-либо причине транзакция не может быть завершена, мы делаем откат, а также закрываем соединение с базой данных с помощью pm.close()
:
finally {
if (tx.isActive()) {
tx.rollback();
}
pm.close();
}
Чтобы подключить нашу программу к базе данных, нам нужно создать блок сохранения
во время выполнения, чтобы указать постоянные классы, тип базы данных и параметры подключения:
PersistenceUnitMetaData pumd = new PersistenceUnitMetaData(
"dynamic-unit", "RESOURCE_LOCAL", null);
pumd.addClassName("com.foreach.jdo.Product");
pumd.setExcludeUnlistedClasses();
pumd.addProperty("javax.jdo.option.ConnectionDriverName", "org.h2.Driver");
pumd
.addProperty("javax.jdo.option.ConnectionURL", "jdbc:h2:mem:mypersistence");
pumd.addProperty("javax.jdo.option.ConnectionUserName", "sa");
pumd.addProperty("javax.jdo.option.ConnectionPassword", "");
pumd.addProperty("datanucleus.autoCreateSchema", "true");
5. Чтение объектов
Чтобы прочитать данные из нашей базы данных внутри нашего блока транзакций, мы создаем запрос. Затем мы сохраняем эти элементы в коллекции Java List
, которая будет содержать в памяти копию информации из постоянного хранилища.
Менеджер постоянства дает нам доступ к интерфейсу запросов, который позволяет нам взаимодействовать с базой данных:
Query q = pm.newQuery(
"SELECT FROM " + Product.class.getName() + " WHERE price < 1");
List<Product> products = (List<Product>) q.execute();
Iterator<Product> iter = products.iterator();
while (iter.hasNext()) {
Product p = iter.next();
// show the product information
}
6. Обновление объектов
Для обновления объектов в базе нам нужно найти объекты, которые мы хотим обновить с помощью запроса, затем мы обновляем результаты запроса и фиксируем транзакцию:
Query query = pm.newQuery(Product.class, "name == \"Phone\"");
Collection result = (Collection) query.execute();
Product product = (Product) result.iterator().next();
product.setName("Android Phone");
7. Удаление объектов
Подобно процедуре обновления, мы сначала ищем объект, а затем удаляем его с помощью диспетчера постоянства. В таких ситуациях JDO обновляет постоянное хранилище:
Query query = pm.newQuery(Product.class, "name == \"Android Phone\"");
Collection result = (Collection) query.execute();
Product product = (Product) result.iterator().next();
pm.deletePersistent(product);
8. XML-хранилища данных
Используя плагин XML, мы можем использовать файлы XML для сохранения наших данных.
Мы указываем наш ConnectionURL
, указывая, что это файл XML, и указываем имя файла: ``
pumdXML.addProperty("javax.jdo.option.ConnectionURL", "xml:file:myPersistence.xml");
Хранилище данных XML не поддерживает свойство автоинкремента, поэтому нам нужно создать еще один класс:
@PersistenceCapable()
public class ProductXML {
@XmlAttribute
private long productNumber = 0;
@PrimaryKey
private String name = null;
private Double price = 0.0;
// standard getters and setters
Аннотация @XmlAttribute
означает , что это будет отображаться в XML-файле как атрибут элемента.
Давайте создадим и сохраним наш продукт:
ProductXML productXML = new ProductXML(0,"Tablet", 80.0);
pm.makePersistent(productXML);
Получаем продукт, хранящийся в файле XML:
<productXML productNumber="0">
<name>Tablet</name>
<price>80.0</price>
</productXML>
8.1. Восстановление объектов из хранилища данных XML
Мы можем восстановить наши объекты из файла XML с помощью запроса:
Query q = pm.newQuery("SELECT FROM " + ProductXML.class.getName());
List<ProductXML> products = (List<ProductXML>) q.execute();
А затем мы используем итератор для взаимодействия с каждым объектом.
9. JDO-запросы
JDOQL — это объектный язык запросов, предназначенный для выполнения запросов с использованием объектов Java.
9.1. Декларативный JDOQL
С помощью декларативного запроса мы объявляем параметры и задаем их с помощью Java, это обеспечивает безопасность типов:
Query qDJDOQL = pm.newQuery(Product.class);
qDJDOQL.setFilter("name == 'Tablet' && price == price_value");
qDJDOQL.declareParameters("double price_value");
List<Product> resultsqDJDOQL = qDJDOQL.setParameters(80.0).executeList();
9.2. SQL
JDO предоставляет механизм для выполнения стандартных SQL-запросов:
Query query = pm.newQuery("javax.jdo.query.SQL", "SELECT * FROM PRODUCT");
query.setClass(Product.class);
List<Product> results = query.executeList();
Мы используем javax.jdo.query.SQL
в качестве одного параметра для объекта запроса, а вторым параметром является сам SQL.
9.3. JPQL
JDO также предоставляет механизм для выполнения запросов JPA. Мы можем использовать полный синтаксис языка запросов JPA:
Query q = pm.newQuery("JPQL",
"SELECT p FROM " + Product.class.getName() + " p WHERE p.name = 'Laptop'");
List results = (List) q.execute();
10. Резюме
В этом уроке мы:
- создал простое CRUD-приложение, использующее JDO
- сохранили и извлекли наши данные в формате XML
- изучили общие механизмы запросов
Как всегда, вы можете найти код из статьи на Github .