«1. Обзор
В предыдущей статье этой серии мы показали, как сохранять объекты Java в разных хранилищах данных. Дополнительные сведения см. в Руководстве по объектам данных Java.
JDO поддерживает различные языки запросов, чтобы предоставить разработчику гибкость в использовании наиболее знакомого ему языка запросов.
2. Языки запросов JDO
JDO поддерживает следующие языки запросов:
-
JDOQL — язык запросов, использующий синтаксис Java Типизированный JDOQL — следующий синтаксису JDOQL, но предоставляющий API для упрощения использования запросов. SQL — используется только для РСУБД. JPQL — предоставляется Datanucleus, но не является частью спецификаций JDO.
3. API запросов
3.1. Создание запроса
Чтобы создать запрос, нам нужно указать язык, а также строку запроса:
Query query = pm.newQuery(
"javax.jdo.query.SQL",
"select * from product_item where price < 10");
Если мы не указываем язык, по умолчанию используется JDOQL:
Query query = pm.newQuery(
"SELECT FROM com.baeldung.jdo.query.ProductItem WHERE price < 10");
3.2. Создание именованного запроса
Мы также можем определить запрос и обращаться к нему по сохраненному имени.
Для этого мы сначала создадим класс ProductItem:
@PersistenceCapable
public class ProductItem {
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.INCREMENT)
int id;
String name;
String status;
String description;
double price;
//standard getters, setters & constructors
}
Затем мы добавим конфигурацию класса в файл META-INF/package.jdo, чтобы определить запрос и назвать его:
<jdo>
<package name="com.baeldung.jdo.query">
<class name="ProductItem" detachable="true" table="product_item">
<query name="PriceBelow10" language="javax.jdo.query.SQL">
<![CDATA[SELECT * FROM PRODUCT_ITEM WHERE PRICE < 10]]>
</query>
</class>
</package>
</jdo>
~~ ~ Мы определили запрос с именем «PriceBelow10».
Мы можем использовать это в нашем коде:
Query<ProductItem> query = pm.newNamedQuery(
ProductItem.class, "PriceBelow10");
List<ProductItem> items = query.executeList();
3.3. Закрытие запроса
Для экономии ресурсов мы можем закрыть запросы:
query.close();
Аналогично, мы можем закрыть конкретный результирующий набор, передав его в качестве параметра методу close():
query.close(ResultSet);
3.4 . Компиляция запроса
Если мы хотим проверить запрос, мы можем вызвать метод compile():
query.compile();
Если запрос недействителен, метод выдаст исключение JDOException.
4. JDOQL
JDOQL — это объектно-ориентированный язык запросов, предназначенный для реализации возможностей языка SQL и сохранения отношений объектов Java в модели приложения.
Запросы JDOQL могут быть определены в виде одной строки.
Прежде чем углубиться, давайте рассмотрим некоторые основные понятия:
4.1. Класс-кандидат
Класс-кандидат в JDOQL должен быть сохраняемым классом. Мы используем полное имя класса вместо имени таблицы на языке SQL:
Query query = pm.newQuery("SELECT FROM com.baeldung.jdo.query.ProductItem");
List<ProductItem> r = query.executeList();
Как видно из приведенного выше примера, com.baeldung.jdo.query.ProductItem является здесь классом-кандидатом.
4.2. Фильтр
Фильтр можно написать на Java, но он должен возвращать логическое значение:
Query query = pm.newQuery("SELECT FROM com.baeldung.jdo.query.ProductItem");
query.setFilter("status == 'SoldOut'");
List<ProductItem> result = query.executeList();
4.3. Методы
JDOQL не поддерживает все методы Java, но поддерживает различные методы, которые мы можем вызывать из запроса и которые можно использовать в широком диапазоне:
query.setFilter("this.name.startsWith('supported')");
Для получения более подробной информации о поддерживаемых методах, пожалуйста, проверьте эта ссылка.
4.4. Параметры
Мы можем передавать значения в запросы как параметры. Мы можем определить параметры явно или неявно.
Чтобы определить параметр явно:
Query query = pm.newQuery(
"SELECT FROM com.baeldung.jdo.query.ProductItem "
+ "WHERE price < threshold PARAMETERS double threshold");
List<ProductItem> result = (List<ProductItem>) query.execute(10);
Этого также можно добиться с помощью метода setParameters:
Query query = pm.newQuery(
"SELECT FROM com.baeldung.jdo.query.ProductItem "
+ "WHERE price < :threshold");
query.setParameters("double threshold");
List<ProductItem> result = (List<ProductItem>) query.execute(10);
Мы можем сделать это неявно, не определяя тип параметра:
Query query = pm.newQuery(
"SELECT FROM com.baeldung.jdo.query.ProductItem "
+ "WHERE price < :threshold");
List<ProductItem> result = (List<ProductItem>) query.execute(10);
5 JDOQL Typed
Чтобы использовать JDOQLTypedQueryAPI, нам нужно подготовить среду.
5.1. Установка Maven
<dependency>
<groupId>org.datanucleus</groupId>
<artifactId>datanucleus-jdo-query</artifactId>
<version>5.0.2</version>
</dependency>
...
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
Последними версиями этих зависимостей являются datanucleus-jdo-query и maven-compiler-plugin.
5.2. Включение обработки аннотаций
Для Eclipse мы можем выполнить следующие шаги, чтобы включить обработку аннотаций:
- Go to Java Compiler and make sure the compiler compliance level is 1.8 or above
- Go to Java Compiler → Annotation Processing and enable the project specific settings and enable annotation processing
- Go to Java Compiler → Annotation Processing → Factory Path, enable the project specific settings and then add the following jars to the list: javax.jdo.jar, datanucleus-jdo-query.jar
Приведенная выше подготовка означает, что всякий раз, когда мы компилируем сохраняемые классы, процессор аннотаций в datanucleus-jdo-query.jar будет генерировать запрос. class для каждого класса, аннотированного @PersistenceCapable.
В нашем случае процессор генерирует класс QProductItem. Сгенерированный класс имеет почти то же имя, что и сохраняемый класс, хотя и с префиксом Q.
5.3. Создайте типизированный запрос JDOQL:
JDOQLTypedQuery<ProductItem> tq = pm.newJDOQLTypedQuery(ProductItem.class);
QProductItem cand = QProductItem.candidate();
tq = tq.filter(cand.price.lt(10).and(cand.name.startsWith("pro")));
List<ProductItem> results = tq.executeList();
Мы можем использовать класс запроса для доступа к полям-кандидатам и использовать его доступные методы Java.
6. SQL
JDO поддерживает язык SQL, если мы используем СУБД.
Давайте создадим SQL-запрос:
Query query = pm.newQuery("javax.jdo.query.SQL","select * from "
+ "product_item where price < ? and status = ?");
query.setClass(ProductItem.class);
query.setParameters(10,"InStock");
List<ProductItem> results = query.executeList();
Мы использовали setClass() для запроса, чтобы получить объекты ProductItem при выполнении запроса. В противном случае он извлекает тип объекта.
7. JPQL
JDO DataNucleus предоставляет язык JPQL.
Давайте создадим запрос, используя JPQL:
Query query = pm.newQuery("JPQL","select i from "
+ "com.baeldung.jdo.query.ProductItem i where i.price < 10"
+ " and i.status = 'InStock'");
List<ProductItem> results = (List<ProductItem>) query.execute();
«
«Имя сущности здесь — com.baeldung.jdo.query.ProductItem. Мы не можем использовать только имя класса. Это связано с тем, что JDO не имеет метаданных для определения имени объекта, такого как JPA. Мы определили ProductItem p, и после этого мы можем использовать p в качестве псевдонима для ссылки на ProductItem.
Для получения дополнительной информации о синтаксисе JPQL перейдите по этой ссылке.
8. Заключение
В этой статье мы показали различные языки запросов, поддерживаемые JDO. Мы показали, как сохранять именованные запросы для повторного использования, объяснили концепции JDOQL и показали, как использовать SQL и JPQL с JDO.