Spring Data 注解

1、简介

Spring Data 提供了对数据存储技术的抽象。因此,我们的业务逻辑代码可以更加独立于底层持久化实现。而且,Spring 还简化了处理与数据存储相关的实现细节的过程。

本文将带你了解 Spring DataSpring Data JPASpring Data MongoDB 项目中最常见的注解。

2、常见的 Spring Data 注解

2.1、@Transactional

@Transactional 用于定义事务方法:

@Transactional
void pay() {}

如果在类上应用此注解,那么它就会对类中的所有方法起作用。也可以在方法上定义此注解来进行覆盖。

2.2、@NoRepositoryBean

有时我们会通过一个基本的 Repository 接口,定义一些通用的方法。然后,所有的 Repository 来继承这个基本的 Repository 接口。

基本的 Repository 接口不应该被实例化为 Bean,所以可以使用 @NoRepositoryBean 注解进行标注。

例如,如果想在所有 Repository 中使用 Optional<T> findById(ID id) 方法,那么可以创建一个基础 Repository 接口:

@NoRepositoryBean
interface MyUtilityRepository<T, ID extends Serializable> extends CrudRepository<T, ID> {
    Optional<T> findById(ID id);
}

此注解不会影响子接口,因此 Spring 将会把下面 Repository 接口创建为 Bean:

@Repository
interface PersonRepository extends MyUtilityRepository<Person, Long> {}

注意,Spring Data 第 2 版已经包含了该方法,取代了旧版的 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 将 Model 类中的一个字段标记为主键:

class Person {

    @Id
    Long id;

    // ...
    
}

由于它与具体实现无关,使得 Model 类在多个数据存储引擎中易于使用。

2.5、@Transient

可以使用此注解将 Model 类中的一个字段标记为瞬时(transient)字段。这样,数据存储引擎就不会读取或写入这个字段的值:

class Person {

    // ...

    @Transient
    int age;

    // ...

}

@Id 一样,@Transient 也是独立于实现的,这使得它可以方便地与多个数据存储实现一起使用。

2.6、@CreatedBy、@LastModifiedBy、@CreatedDate 和 @LastModifiedDate

审计注解: Spring 会自动在注解字段中填入对象创建者、对象最后修改者、创建日期和最后修改日期:

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 注解在 Repository 方法上定义 JPQL 查询:

@Query("SELECT COUNT(*) FROM Person p")
long getPersonCount();

此外,还可以使用命名参数:

@Query("FROM Person p WHERE p.name = :name")
Person findByName(@Param("name") String name);

此外,还可以把 nativeQuery 参数设置为 true,以使用原生 SQL 查询:

@Query(value = "SELECT AVG(p.age) FROM person p", nativeQuery = true)
int getAverageAge();

3.2、@Procedure

通过 Spring Data JPA,可以轻松地从 Repository 调用存储过程。

首先,需要使用标准 JPA 注解在实体类上声明 Repository:

@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 {}

之后,就可以在 Repository 中使用在 name 参数中声明的名称引用它。

@Procedure(name = "count_by_name")
long getCountByName(@Param("name") String name);

3.3、@Lock

可以在执行 Repository 查询方法时配置加锁模式:

@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 用于注解 Repository 中对数据进行修改的方法。

@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 Repository,必须先通过 @EnableJpaRepositories 启用 JPA Repository。

注意,必须将此注解与 @Configuration 一起使用:

@Configuration
@EnableJpaRepositories
class PersistenceJPAConfig {}

Spring 会在此 @Configuration 类的子包中查找 Repository。

可以使用 basePackages 参数来手动指定 Repository 接口所在的包:

@Configuration
@EnableJpaRepositories(basePackages = "com.baeldung.persistence.dao")
class PersistenceJPAConfig {}

注意,如果 Spring Boot 的 classpath 上存在 Spring Data JPA 依赖,它会自动执行此操作。

4、Spring Data Mongo 注解

Spring Data 让使用 MongoDB 变得更加容易。

4.1、@Document

该注解将一个类标记为要持久化到数据库的 Domain 对象:

@Document
class User {}

它还允许选择要使用的集合(collection)名称:

@Document(collection = "user")
class User {}

该注解类似于 JPA 中的 @Entity

4.2、@Field

通过 @Field 配置 MongoDB 持久化文档(Document)时要使用的字段名称:

@Document
class User {

    // ...

    @Field("email")
    String emailAddress;

    // ...

}

该注解等同于 JPA 中的 @Column

4.3、@Query

通过 @Query,可以在 MongoDB Repository 方法上提供 find 查询:

@Query("{ 'name' : ?0 }")
List<User> findUsersByName(String name);

4.4、@EnableMongoRepositories

同样,要使用 MongoDB Repository,也必须先通过 @EnableMongoRepositories 注解进行启用。

该注解也需要与 @Configuration 一起使用:

@Configuration
@EnableMongoRepositories
class MongoConfig {}

Spring 会在此 @Configuration 类的子包中查找 Repository。也可以使用 basePackages 参数来指定要扫描的包路径:

@Configuration
@EnableMongoRepositories(basePackages = "com.baeldung.repository")
class MongoConfig {}

同样的,如果 Spring Boot 的 classpath 上存在 Spring Data MongoDB 依赖,它会自动执行此操作。

5、总结

本文介绍了 Spring Data、Spring Data JPA 和 Spring Data MongoDB 项目中最常见的注解及其作用和使用方法。


Ref:https://www.baeldung.com/spring-data-annotations