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.foreach.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.foreach.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.foreach.jdo.query.ProductItem");
List<ProductItem> r = query.executeList();
Как видно из приведенного выше примера, com.foreach.jdo.query.ProductItem здесь
является классом-кандидатом.
4.2. Фильтр
Фильтр можно написать на Java, но он должен возвращать логическое значение:
Query query = pm.newQuery("SELECT FROM com.foreach.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.foreach.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.foreach.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.foreach.jdo.query.ProductItem "
+ "WHERE price < :threshold");
List<ProductItem> result = (List<ProductItem>) query.execute(10);
5. Типизированный JDOQL
Чтобы использовать 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 мы можем выполнить следующие шаги, чтобы включить аннотированную обработку:
- Перейдите к
компилятору Java
и убедитесь, что уровень соответствия компилятора 1.8 или выше. - Перейдите в
Компилятор Java → Обработка аннотаций
и включите специальные настройки проекта и включите обработку аннотаций. - Перейдите в
Компилятор Java → Обработка аннотаций → Путь к фабрике
, включите специальные настройки проекта, а затем добавьте в список следующие файлы jar:javax.jdo.jar,
datanucleus-jdo-query.jar.
Приведенная выше подготовка означает, что всякий раз, когда мы компилируем сохраняемые классы, процессор аннотаций в datanucleus-jdo-query.jar будет генерировать класс запроса для каждого класса, аннотированного @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.foreach.jdo.query.ProductItem i where i.price < 10"
+ " and i.status = 'InStock'");
List<ProductItem> results = (List<ProductItem>) query.execute();
Имя сущности здесь — com.foreach.jdo.query.ProductItem.
Мы не можем использовать только имя класса. Это связано с тем, что JDO не имеет метаданных для определения имени объекта, такого как JPA .
Мы определили ProductItem
p
, и после этого мы можем использовать p
в качестве псевдонима для ссылки на ProductItem.
Дополнительные сведения о синтаксисе JPQL см. по этой ссылке .
8. Заключение
В этой статье мы показали различные языки запросов, поддерживаемые JDO. Мы показали, как сохранять именованные запросы для повторного использования, объяснили концепции JDOQL и показали, как использовать SQL и JPQL с JDO.
Примеры кода в статье можно найти на GitHub .