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

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

1. обзор

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

Of course, it can work with the different implementation of CDI - JBoss Weld или OpenWebBeans. Он также протестирован на многих серверах приложений.

В этом руководстве мы сосредоточимся наone of the best known and useful – Data module.

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

Модуль данных Apache DeltaSpike используется дляsimplify implementation of the repository pattern. Это позволяетreducing a boilerplate code by providing centralized logic for queries creation and execution.

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

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

2.1. Требуемые зависимости

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

Когда 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 Data доступны в Maven Central:

Кrun an application with Data module, we also need a JPA and CDI implementations available at runtime.

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

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

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

2.2. Конфигурация Entity Manager

Data module requires EntityManager to be injected over CDI.

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

public class EntityManagerProducer {

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

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

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

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


   java:jboss/datasources/example-jee7-seedDS
   
      
      
   

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

2.3. Стратегия транзакции

In case we’re using JTA transaction type for our data source then we have to define Transaction Strategy that will be used in the Apache DeltaSpike repositories. Мы можем сделать это внутри файлаapache-deltaspike.properties (в каталогеMETA-INF):

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

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

  • BeanManagedUserTransactionStrategy

  • ResourceLocalTransactionStrategy

  • ContainerManagedTransactionStrategy

  • EnvironmentAwareTransactionStrategy

Все они реализуютorg.apache.deltaspike.jpa.spi.transaction.TransactionStrategy.

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

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

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

Когда мы используем модуль данных Apache DeltaSpike классany abstract class or interface can become a repository.

All we have to do is toadd an @Repositoryannotation включает атрибутforEntity, который определяет объект JPA, который должен обрабатывать наш репозиторий:

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

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

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

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

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

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

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

Первая возможностьdefine a query is to use method name which follows a defined naming convention.

Это выглядит ниже:

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

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

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

return type mainly defines how many objects our query might return. Мы не можем определить один тип объекта в качестве возвращаемого значения в случае, если наш запрос может вернуть более одного результата.

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

public abstract User findByFirstName(String firstName);

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

public abstract Collection findAnyByFirstName(String firstName);

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

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

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

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

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

Prefix defines the action we want to execute on the repository. Наиболее полезным является поиск объектов, которые соответствуют заданным критериям поиска.

Для этого действия есть много префиксов, напримерfindBy,findAny,findAll. . Для получения подробного списка, пожалуйста, проверьте официальный Apache DeltaSpikedocumentation:

public abstract User findAnyByLastName(String lastName);

Однако есть ещеother method templates which are used for counting and removing entities. Мы можемcount все строки в таблице:

public abstract int count();

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

public abstract void remove(User user);

Поддержка префиксов методовcountBy иremoveBy будет добавлена ​​в следующей версии Apache DeltaSpike 1.9.0.

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

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

В запросе мы можем использоватьmany properties combined with and operators.

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

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

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

query can also use nested properties.

В следующем примере объектUser имеет свойство адреса типаAddress, а объектAddress имеет свойствоcity:

@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 позволяет намdefine an order in which result should be returned. Мы можем определить как восходящий, так и нисходящий порядок:

public abstract List findAllOrderByFirstNameAsc();

Как показано выше,we have to do is to add a part to the method name which contains property name we want to sort by and the short name for the order direction.

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

public abstract List findAllOrderByFirstNameAscLastNameDesc();

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

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

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

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

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

Тогда мы можемenable query pagination by providing two additional parameters: @FirstResult and @MaxResult:

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

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

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

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

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

Кget some basic repository methods, our repository should extend basic type provided by Apache DeltaSpike. Вот некоторые из них, напримерEntityRepository,FullEntityRepository, и т. Д .:

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

Или используя абстрактный класс:

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

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

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

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

Abstract base repository classes, e.g., AbstractEntityRepository gives us an access to fields (via getters) or utility methods which we can use to create a query:

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

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

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

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

SQLquery to execute can also be defined with the @Query annotation. Это очень похоже на решение Spring. Мы должны добавить аннотацию к методу с 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 и сосредоточились на захватывающей части - модуле данных. Он очень похож на проект Spring Data.

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

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