Рубрики
Без рубрики

Руководство по модулю данных DeltaSpike

Изучите модуль данных DeltaSpike, чтобы упростить реализацию шаблона репозитория.

Автор оригинала: baeldung.

1. Обзор

Apache DeltaSpike – это проект, который предоставляет коллекцию расширений CDI для проектов Java; он требует, чтобы реализация CDI была доступна во время выполнения.

Конечно, он может работать с другой реализацией CDI – JBoss Weld или OpenWebBeans. Он также протестирован на многих серверах приложений.

В этом уроке мы сосредоточимся на одном из самых известных и полезных модулей данных .

2. Настройка модуля данных DeltaSpike

Модуль данных Apache DeltaSpike используется для упрощения реализации шаблона репозитория . Это позволяет сократить шаблонный код, предоставляя централизованную логику для создания и выполнения запросов .

Это очень похоже на проект Spring Data . Чтобы запросить базу данных, нам нужно определить объявление метода (без реализации), которое следует определенному соглашению об именовании или содержит @Query аннотацию. Реализация будет выполнена для нас с помощью расширения CDI.

В следующих подразделах мы рассмотрим, как настроить модуль данных Apache DeltaSpike в нашем приложении.

2.1. Необходимые зависимости

Чтобы использовать модуль данных Apache DeltaSpike в приложении, нам необходимо настроить необходимые зависимости.

Когда Maven является нашим инструментом сборки, мы должны использовать:


    org.apache.deltaspike.modules
    deltaspike-data-module-api
    1.8.2
    compile


    org.apache.deltaspike.modules
    deltaspike-data-module-impl
    1.8.2
    runtime

Когда мы используем Gradle:

runtime 'org.apache.deltaspike.modules:deltaspike-data-module-impl'
compile 'org.apache.deltaspike.modules:deltaspike-data-module-api'

Артефакты модуля данных Apache DeltaSpike доступны на Maven Central:

Чтобы запустить приложение с модулем данных, нам также нужны реализации JPA и CDI, доступные во время выполнения .

Хотя можно запустить Apache DeltaSpike в приложении Java SE, в большинстве случаев он будет развернут на сервере приложений (например, Wildfly или WebSphere).

Серверы приложений имеют полную поддержку Jakarta EE, поэтому нам больше ничего не нужно делать. В случае приложения Java SE мы должны предоставить эти реализации (например, добавив зависимости в Hibernate и JBoss).

Далее мы также рассмотрим необходимую конфигурацию для EntityManager .

2.2. Конфигурация менеджера сущностей

Модуль Data требует, чтобы EntityManager вводился через CDI .

Мы можем добиться этого с помощью производителя CDI:

public class EntityManagerProducer {

    @PersistenceContext(unitName = "primary")
    private EntityManager entityManager;

    @ApplicationScoped
    @Produces
    public EntityManager getEntityManager() {
        return entityManager;
    }
}

Приведенный выше код предполагает, что у нас есть единица сохранения с именем primary , определенным в persistence.xml файл.

Давайте рассмотрим ниже в качестве примера определения:


   java:jboss/datasources/baeldung-jee7-seedDS
   
      
      
   

Единица сохранения в нашем примере использует тип транзакции JTA, что означает, что мы должны предоставить стратегию транзакций, которую мы собираемся использовать.

2.3. Стратегия сделки

В случае, если мы используем тип транзакции JTA для нашего источника данных, мы должны определить стратегию транзакций, которая будет использоваться в репозиториях Apache DeltaSpike . Мы можем сделать это внутри apache-deltaspike.properties file (в каталоге META-INF ):

globalAlternatives.org.apache.deltaspike.jpa.spi.transaction.TransactionStrategy=org.apache.deltaspike.jpa.impl.transaction.ContainerManagedTransactionStrategy

Существует четыре типа стратегии транзакций, которые мы можем определить:

  • BeanManagedUserTransactionStrategy
  • Стратегия локальных транзакций ресурсов
  • Стратегия управляемых транзакций с контейнерами
  • Стратегия транзакций с учетом окружающей среды

Все они реализуют org.apache.deltaspike.jpa.spi.транзакция.Стратегия сделки .

Это была последняя часть конфигурации, необходимой для нашего модуля данных.

Далее мы покажем, как реализовать классы шаблонов репозитория.

3. Классы репозитория

Когда мы используем модуль данных Apache DeltaSpike любой абстрактный класс или интерфейс может стать хранилищем класса.

Все, что нам нужно сделать, это добавить @Репозиторий | аннотацию с атрибутом для сущности , который определяет сущность JPA, которую должен обрабатывать ваш репозиторий:

@Entity
public class User {
    // ...
}  

@Repository(forEntity = User.class) 
public interface SimpleUserRepository { 
    // ... 
}

или с абстрактным классом:

@Repository(forEntity = User.class)
public abstract class SimpleUserRepository { 
    // ... 
}

Модуль данных обнаруживает классы (или интерфейсы) с такой аннотацией и обрабатывает методы, которые находятся внутри.

Существует несколько возможностей определить запрос для выполнения. Мы рассмотрим один за другим в следующих разделах.

4. Запрос От Имени Метода

Первая возможность определить запрос-это использовать имя метода, которое следует определенному соглашению об именовании .

Это выглядит следующим образом:

(Entity|Optional|List|Stream) (prefix)(Property[Comparator]){Operator Property [Comparator]}

Далее мы сосредоточимся на каждой части этого определения.

4.1. Тип возврата

Тип возврата в основном определяет, сколько объектов может вернуть наш запрос . Мы не можем определить один тип сущности в качестве возвращаемого значения, если наш запрос может вернуть более одного результата.

Следующий метод вызовет исключение в случае, если существует более одного Пользователя с заданным именем:

public abstract User findByFirstName(String firstName);

Обратное неверно – мы можем определить возвращаемое значение как Collection , даже если результатом будет только один объект.

public abstract Collection findAnyByFirstName(String firstName);

Префикс имени метода, который предлагает одно значение в качестве возвращаемого типа (например, find Any ) , подавляется, если мы определяем возвращаемое значение как Collection .

Приведенный выше запрос вернет всех Пользователей с именем, соответствующим даже префиксу имени метода, что предполагает что-то другое.

Таких комбинаций ( Collection return type и префикс, который предполагает возврат одного значения) следует избегать, поскольку код становится не интуитивно понятным и трудным для понимания.

В следующем разделе приведены более подробные сведения о префиксе имени метода.

4.2. Префикс для метода запроса

Префикс определяет действие, которое мы хотим выполнить в репозитории . Наиболее полезным является поиск сущностей, соответствующих заданным критериям поиска.

Для этого действия существует множество префиксов, таких как findBy , find Any , find All. Для получения подробного списка, пожалуйста, проверьте официальную документацию Apache DeltaSpike |:

public abstract User findAnyByLastName(String lastName);

Однако существуют также другие шаблоны методов, которые используются для подсчета и удаления сущностей . Мы можем подсчитать все строки в таблице:

public abstract int count();

Кроме того, существует шаблон метода remove , который мы можем добавить в наш репозиторий:

public abstract void remove(User user);

Поддержка префиксов county и remove By method будет добавлена в следующей версии Apache DeltaSpike 1.9.0.

В следующем разделе показано, как мы можем добавить дополнительные атрибуты в запросы.

4.3. Запрос Со Многими Свойствами

В запросе мы можем использовать многие свойства в сочетании с и операторами .

public abstract Collection findByFirstNameAndLastName(
  String firstName, String lastName);
public abstract Collection findByFirstNameOrLastName(
  String firstName, String lastName);

Мы можем объединить столько свойств, сколько захотим. Также доступен поиск вложенных свойств, которые мы покажем далее.

4.4. Запрос С Вложенными Свойствами

Запрос также может использовать вложенные свойства .

В следующем примере Пользователь сущность имеет свойство адреса типа Адрес и Адрес сущность имеет свойство город :

@Entity
public class Address {
private String city;
    // ...
}
@Entity
public class User {
    @OneToOne 
    private Address address;
    // ...
}
public abstract Collection findByAddress_city(String city);

4.5. Порядок в запросе

DeltaSpike позволяет нам определить порядок, в котором результат должен быть возвращен . Мы можем определить как восходящий, так и нисходящий порядок:

public abstract List findAllOrderByFirstNameAsc();

Как показано выше, все, что нам нужно сделать, это добавить часть к имени метода, которая содержит имя свойства, по которому мы хотим отсортировать, и краткое имя направления заказа .

Мы можем легко объединить много заказов:

public abstract List findAllOrderByFirstNameAscLastNameDesc();

Далее мы покажем, как ограничить размер результата запроса.

4.6. Ограничить размер результатов запроса и Разбиение на страницы

Есть случаи использования, когда мы хотим получить несколько первых строк из всего результата. Это так называемый предел запросов. Это также просто с модулем данных:

public abstract Collection findTop2OrderByFirstNameAsc();
public abstract Collection findFirst2OrderByFirstNameAsc();

First и top могут использоваться взаимозаменяемо.

Затем мы можем включить разбиение запросов на страницы, указав два дополнительных параметра: @firstResult и @Maxresults :

public abstract Collection findAllOrderByFirstNameAsc(@FirstResult int start, @MaxResults int size);

Мы уже определили множество методов в репозитории. Некоторые из них являются универсальными и должны быть определены один раз и использоваться каждым репозиторием.

Apache DeltaSpike предоставляет несколько основных типов, которые мы можем использовать, чтобы иметь много методов из коробки.

В следующем разделе мы сосредоточимся на том, как это сделать.

5. Основные типы репозиториев

Чтобы получить некоторые базовые методы репозитория, наш репозиторий должен расширить базовый тип, предоставляемый Apache DeltaSpike . Есть некоторые из них, такие как EntityRepository , Full EntityRepository, и т. Д.:

@Repository
public interface UserRepository 
  extends FullEntityRepository {
    // ...
}

Или с помощью абстрактного класса:

@Repository
public abstract class UserRepository extends AbstractEntityRepository {
    // ...
}

Вышеприведенная реализация дает нам множество методов без написания дополнительных строк кода, поэтому мы получили то, что хотели – мы массово сокращаем шаблонный код.

В случае, если мы используем базовый тип репозитория, нет необходимости передавать дополнительное значение атрибута для сущности в наш @Репозиторий аннотацию .

Когда мы используем абстрактные классы вместо интерфейсов для наших репозиториев, мы получаем дополнительную возможность создать пользовательский запрос.

Абстрактные базовые классы репозитория, например, AbstractEntityRepository дает нам доступ к полям (через геттеры) или служебным методам, которые мы можем использовать для создания запроса :

public List findByFirstName(String firstName) {
    return typedQuery("select u from User u where u.firstName = ?1")
      .setParameter(1, firstName)
      .getResultList();
}

В приведенном выше примере мы использовали метод typedQuery utility для создания пользовательской реализации.

Последняя возможность создать запрос-использовать аннотацию @Query , которую мы покажем далее.

6. Аннотация @Query

SQL запрос для выполнения также может быть определен с помощью @Query аннотации . Это очень похоже на весеннее решение. Мы должны добавить аннотацию к методу с SQL-запросом в качестве значения.

По умолчанию это запрос JPQL:

@Query("select u from User u where u.firstName = ?1")
public abstract Collection findUsersWithFirstName(String firstName);

Как и в приведенном выше примере, мы можем легко передавать параметры в запрос через индекс.

В случае, если мы хотим передать запрос через собственный SQL вместо JPQL, нам нужно определить дополнительный атрибут запроса – isNative с истинным значением:

@Query(value = "select * from User where firstName = ?1", isNative = true)
public abstract Collection findUsersWithFirstNameNative(String firstName);

7. Заключение

В этой статье мы рассмотрели основное определение Apache DeltaSpike и сосредоточились на захватывающем модуле part – Data. Это очень похоже на проект Spring Data.

Мы изучили, как реализовать шаблон репозитория. Мы также представили три возможности определения запроса для выполнения.

Как всегда, полные примеры кода, используемые в этой статье, доступны на Github .