«1. Введение
Spring Data обеспечивает абстракцию технологий хранения данных. Следовательно, наш код бизнес-логики может быть гораздо более независимым от базовой реализации постоянства. Кроме того, Spring упрощает обработку деталей хранения данных, зависящих от реализации.
В этом руководстве мы рассмотрим наиболее распространенные аннотации проектов Spring Data, Spring Data JPA и Spring Data MongoDB.
2. Общие аннотации данных Spring
2.1. @Transactional
Когда мы хотим настроить транзакционное поведение метода, мы можем сделать это с помощью:
@Transactional
void pay() {}
Если мы применим эту аннотацию на уровне класса, то она будет работать со всеми методами внутри класса. Однако мы можем переопределить его эффекты, применив его к определенному методу.
Он имеет множество параметров конфигурации, с которыми можно ознакомиться в этой статье.
2.2. @NoRepositoryBean
Иногда мы хотим создать интерфейсы репозитория с единственной целью — предоставить общие методы для дочерних репозиториев.
Конечно, мы не хотим, чтобы Spring создавал bean-компонент этих репозиториев, так как мы не будем их никуда внедрять. @NoRepositoryBean делает именно это: когда мы помечаем дочерний интерфейс org.springframework.data.repository.Repository, Spring не будет создавать из него компонент.
Например, если нам нужен метод Optional\u003cT\u003e findById(ID id) во всех наших репозиториях, мы можем создать базовый репозиторий:
@NoRepositoryBean
interface MyUtilityRepository<T, ID extends Serializable> extends CrudRepository<T, ID> {
Optional<T> findById(ID id);
}
Эта аннотация не влияет на дочерние интерфейсы; следовательно, Spring создаст bean-компонент для следующего интерфейса репозитория:
@Repository
interface PersonRepository extends MyUtilityRepository<Person, Long> {}
Обратите внимание, что приведенный выше пример не нужен, поскольку Spring Data версии 2 включает этот метод, заменяющий старый T findOne(ID id).
2.3. @Param
Мы можем передавать именованные параметры нашим запросам, используя @Param:
@Query("FROM Person p WHERE p.name = :name")
Person findByName(@Param("name") String name);
Обратите внимание, что мы обращаемся к параметру с синтаксисом :name.
Дополнительные примеры см. в этой статье.
2.4. @Id
@Id помечает поле в классе модели как первичный ключ:
class Person {
@Id
Long id;
// ...
}
Поскольку он не зависит от реализации, он упрощает использование класса модели с несколькими механизмами хранения данных.
2.5. @Transient
Мы можем использовать эту аннотацию, чтобы пометить поле в классе модели как переходное. Следовательно, механизм хранилища данных не будет читать или записывать значение этого поля:
class Person {
// ...
@Transient
int age;
// ...
}
Как и @Id, @Transient также не зависит от реализации, что делает его удобным для использования с несколькими реализациями хранилища данных.
2.6. @CreatedBy, @LastModifiedBy, @CreatedDate, @LastModifiedDate
С помощью этих аннотаций мы можем проверять наши классы моделей: последняя модификация:
public class Person {
// ...
@CreatedBy
User creator;
@LastModifiedBy
User modifier;
@CreatedDate
Date createdAt;
@LastModifiedDate
Date modifiedAt;
// ...
}
Обратите внимание, что если мы хотим, чтобы Spring заполнил участников, нам также нужно использовать Spring Security.
Более подробное описание можно найти в этой статье.
3. Аннотации Spring Data JPA
3.1. @Query
С помощью @Query мы можем предоставить реализацию JPQL для метода репозитория:
@Query("SELECT COUNT(*) FROM Person p")
long getPersonCount();
Также мы можем использовать именованные параметры:
@Query("FROM Person p WHERE p.name = :name")
Person findByName(@Param("name") String name);
Кроме того, мы можем использовать собственные SQL-запросы, если мы устанавливаем для аргумента nativeQuery значение true:
@Query(value = "SELECT AVG(p.age) FROM person p", nativeQuery = true)
int getAverageAge();
Для получения дополнительной информации посетите эту статью.
3.2. @Procedure
С Spring Data JPA мы можем легко вызывать хранимые процедуры из репозиториев.
Во-первых, нам нужно объявить репозиторий в классе сущностей, используя стандартные аннотации JPA:
@NamedStoredProcedureQueries({
@NamedStoredProcedureQuery(
name = "count_by_name",
procedureName = "person.count_by_name",
parameters = {
@StoredProcedureParameter(
mode = ParameterMode.IN,
name = "name",
type = String.class),
@StoredProcedureParameter(
mode = ParameterMode.OUT,
name = "count",
type = Long.class)
}
)
})
class Person {}
После этого мы можем ссылаться на него в репозитории с именем, которое мы объявили в аргументе имени:
@Procedure(name = "count_by_name")
long getCountByName(@Param("name") String name);
3.3. @Lock
Мы можем настроить режим блокировки при выполнении метода запроса репозитория:
@Lock(LockModeType.NONE)
@Query("SELECT COUNT(*) FROM Person p")
long getPersonCount();
Доступные режимы блокировки:
-
READ WRITE OPTIMISTIC OPTIMISTIC_FORCE_INCREMENT PESSIMISTIC_READ PESSIMISTIC_WRITE PESSIMISTIC_FORCE_INCREMENT NONE
3.4. @Modifying
Мы можем изменить данные с помощью метода репозитория, если аннотируем их с помощью @Modifying:
@Modifying
@Query("UPDATE Person p SET p.name = :name WHERE p.id = :id")
void changeName(@Param("id") long id, @Param("name") String name);
Для получения дополнительной информации посетите эту статью.
3.5. @EnableJpaRepositories
«Чтобы использовать репозитории JPA, мы должны указать это Spring. Мы можем сделать это с помощью @EnableJpaRepositories.
Обратите внимание, что мы должны использовать эту аннотацию с @Configuration:
@Configuration
@EnableJpaRepositories
class PersistenceJPAConfig {}
Spring будет искать репозитории в подпакетах этого класса @Configuration.
Мы можем изменить это поведение с помощью аргумента basePackages:
@Configuration
@EnableJpaRepositories(basePackages = "com.baeldung.persistence.dao")
class PersistenceJPAConfig {}
Также обратите внимание, что Spring Boot делает это автоматически, если находит Spring Data JPA в пути к классам.
4. Аннотации Spring Data Mongo
Spring Data значительно упрощает работу с MongoDB. В следующих разделах мы рассмотрим самые основные функции Spring Data MongoDB.
Для получения дополнительной информации посетите нашу статью о Spring Data MongoDB.
4.1. @Document
Эта аннотация помечает класс как объект домена, который мы хотим сохранить в базе данных:
@Document
class User {}
Она также позволяет нам выбрать имя коллекции, которую мы хотим использовать:
@Document(collection = "user")
class User {}
~ ~~ Обратите внимание, что эта аннотация является эквивалентом Mongo для @Entity в JPA.
4.2. @Field
С помощью @Field мы можем настроить имя поля, которое мы хотим использовать, когда MongoDB сохраняет документ:
@Document
class User {
// ...
@Field("email")
String emailAddress;
// ...
}
Обратите внимание, что эта аннотация является эквивалентом Mongo для @Column в JPA.
4.3. @Query
С помощью @Query мы можем предоставить поисковый запрос для метода репозитория MongoDB:
@Query("{ 'name' : ?0 }")
List<User> findUsersByName(String name);
4.4. @EnableMongoRepositories
Чтобы использовать репозитории MongoDB, мы должны указать это для Spring. Мы можем сделать это с помощью @EnableMongoRepositories.
Обратите внимание, что мы должны использовать эту аннотацию с @Configuration:
@Configuration
@EnableMongoRepositories
class MongoConfig {}
Spring будет искать репозитории в подпакетах этого класса @Configuration. Мы можем изменить это поведение с помощью аргумента basePackages:
@Configuration
@EnableMongoRepositories(basePackages = "com.baeldung.repository")
class MongoConfig {}
Также обратите внимание, что Spring Boot делает это автоматически, если находит Spring Data MongoDB в пути к классам.
5. Заключение
В этой статье мы увидели, какие аннотации наиболее важны для работы с данными в целом с использованием Spring. Кроме того, мы изучили наиболее распространенные аннотации JPA и MongoDB.
Как обычно, примеры доступны на GitHub здесь для общих аннотаций и аннотаций JPA, а здесь для аннотаций MongoDB.