@spring Data Annotations
@spring Data Annotations
@spring Data Annotations
Spring Data
reference
Spring Annotations
1. Introduction
Spring Data provides an abstraction over data storage technologies. Therefore, our business
logic code can be much more independent of the underlying persistence implementation.
Also, Spring simplifies the handling of implementation-dependent details of data storage.
In this tutorial, we’ll see the most common annotations of the Spring Data, Spring Data JPA,
and Spring Data MongoDB projects.
2. Common Spring Data Annotations
2.1. @Transactional
When we want to configure the transactional behavior of a method, we can do it with:
@Transactional
void pay() {}Copy
If we apply this annotation on class level, then it works on all methods inside the class.
However, we can override its effects by applying it to a specific method.
It has many configuration options, which can be found in this article.
2.2. @NoRepositoryBean
Sometimes we want to create repository interfaces with the only goal of providing
common methods for the child repositories.
Of course, we don’t want Spring to create a bean of these repositories since we won’t inject
them anywhere. @NoRepositoryBean does exactly this: when we mark a child interface
of org.springframework.data.repository.Repository, Spring won’t create a bean out of it.
For example, if we want an Optional<T> findById(ID id) method in all of our repositories,
we can create a base repository:
@NoRepositoryBean
interface MyUtilityRepository<T, ID extends Serializable> extends
CrudRepository<T, ID> {
Optional<T> findById(ID id);
}Copy
This annotation doesn’t affect the child interfaces; hence Spring will create a bean for the
following repository interface:
@Repository
interface PersonRepository extends MyUtilityRepository<Person, Long>
{}Copy
Note, that the example above isn’t necessary since Spring Data version 2 which includes this
method replacing the older T findOne(ID id).
2.3. @Param
We can pass named parameters to our queries using @Param:
@Query("FROM Person p WHERE p.name = :name")
Person findByName(@Param("name") String name);Copy
Note, that we refer to the parameter with the :name syntax.
For further examples, please visit this article.
2.4. @Id
@Id marks a field in a model class as the primary key:
class Person {
@Id
Long id;
// ...
}Copy
Since it’s implementation-independent, it makes a model class easy to use with multiple data
store engines.
2.5. @Transient
We can use this annotation to mark a field in a model class as transient. Hence the data store
engine won’t read or write this field’s value:
class Person {
// ...
@Transient
int age;
// ...
}Copy
Like @Id, @Transient is also implementation-independent, which makes it convenient to use
with multiple data store implementations.
// ...
@CreatedBy
User creator;
@LastModifiedBy
User modifier;
@CreatedDate
Date createdAt;
@LastModifiedDate
Date modifiedAt;
// ...
}Copy
Note, that if we want Spring to populate the principals, we need to use Spring Security as
well.
For a more thorough description, please visit this article.
3.1. @Query
With @Query, we can provide a JPQL implementation for a repository method:
@Query("SELECT COUNT(*) FROM Person p")
long getPersonCount();Copy
Also, we can use named parameters:
@Query("FROM Person p WHERE p.name = :name")
Person findByName(@Param("name") String name);Copy
Besides, we can use native SQL queries, if we set the nativeQuery argument to true:
@Query(value = "SELECT AVG(p.age) FROM person p", nativeQuery = true)
int getAverageAge();Copy
For more information, please visit this article.
3.2. @Procedure
With Spring Data JPA we can easily call stored procedures from repositories.
First, we need to declare the repository on the entity class using standard JPA annotations:
@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)
}
)
})
3.3. @Lock
We can configure the lock mode when we execute a repository query method:
@Lock(LockModeType.NONE)
@Query("SELECT COUNT(*) FROM Person p")
long getPersonCount();Copy
The available lock modes:
READ
WRITE
OPTIMISTIC
OPTIMISTIC_FORCE_INCREMENT
PESSIMISTIC_READ
PESSIMISTIC_WRITE
PESSIMISTIC_FORCE_INCREMENT
NONE
3.4. @Modifying
We can modify data with a repository method if we annotate it with @Modifying:
@Modifying
@Query("UPDATE Person p SET p.name = :name WHERE p.id = :id")
void changeName(@Param("id") long id, @Param("name") String name);Copy
For more information, please visit this article.
3.5. @EnableJpaRepositories
To use JPA repositories, we have to indicate it to Spring. We can do this
with @EnableJpaRepositories.
Note, that we have to use this annotation with @Configuration:
@Configuration
@EnableJpaRepositories
class PersistenceJPAConfig {}Copy
Spring will look for repositories in the sub packages of this @Configuration class.
We can alter this behavior with the basePackages argument:
@Configuration
@EnableJpaRepositories(basePackages = "com.baeldung.persistence.dao")
class PersistenceJPAConfig {}Copy
Also note, that Spring Boot does this automatically if it finds Spring Data JPA on the
classpath.
4.1. @Document
This annotation marks a class as being a domain object that we want to persist to the database:
@Document
class User {}Copy
It also allows us to choose the name of the collection we want to use:
@Document(collection = "user")
class User {}Copy
Note, that this annotation is the Mongo equivalent of @Entity in JPA.
4.2. @Field
With @Field, we can configure the name of a field we want to use when MongoDB persists
the document:
@Document
class User {
// ...
@Field("email")
String emailAddress;
// ...
}Copy
Note, that this annotation is the Mongo equivalent of @Column in JPA.
4.3. @Query
With @Query, we can provide a finder query on a MongoDB repository method:
@Query("{ 'name' : ?0 }")
List<User> findUsersByName(String name);Copy
4.4. @EnableMongoRepositories
To use MongoDB repositories, we have to indicate it to Spring. We can do this
with @EnableMongoRepositories.
Note, that we have to use this annotation with @Configuration:
@Configuration
@EnableMongoRepositories
class MongoConfig {}Copy
Spring will look for repositories in the sub packages of this @Configuration class. We can
alter this behavior with the basePackages argument:
@Configuration
@EnableMongoRepositories(basePackages = "com.baeldung.repository")
class MongoConfig {}Copy
Also note, that Spring Boot does this automatically if it finds Spring Data MongoDB on the
classpath.
5. Conclusion
In this article, we saw which are the most important annotations we need to deal with data in
general, using Spring. In addition, we looked into the most common JPA and MongoDB
annotations.
As usual, examples are available over on GitHub here for common and JPA annotations,
and here for MongoDB annotations.