Spring Data注解

2023/05/18

1. 简介

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

在本教程中,我们将看到Spring Data、Spring Data JPA和Spring Data MongoDB项目最常见的注解。

2. 常见的Spring Data注解

2.1 @Transactional

当我们想要配置方法的事务行为时,我们可以这样做:

@Transactional
void pay() {}

如果我们在类级别应用此注解,那么它适用于类内的所有方法。但是,我们可以通过将其应用于特定方法来覆盖其效果。

它有很多配置选项,可以在这篇文章中找到。

2.2 @NoRepositoryBean

有时我们想要创建Repository接口,其唯一目标是为子Repository提供通用方法

当然,我们不希望Spring创建这些Repository的bean,因为我们不会将它们注入任何地方。@NoRepositoryBean正是这样做的:当我们标记org.springframework.data.repository.Repository的子接口时,Spring不会从中创建一个bean。

例如,如果我们想要在所有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包含此方法替换了旧的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

使用这些注解,我们可以审计我们的模型类: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 {}

在此之后,我们可以使用我们在name参数中声明的名称在Repository中引用它:

@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,我们必须向Spring指出它。我们可以使用@EnableJpaRepositories来做到这一点。

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

@Configuration
@EnableJpaRepositories
class PersistenceJPAConfig {}

Spring将在这个@Configuration类的子包中查找Repository。

我们可以使用basePackages参数改变这种行为:

@Configuration
@EnableJpaRepositories(basePackages = "cn.tuyucheng.taketoday.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 {}

请注意,此注解是JPA中@Entity的Mongo等价物。

4.2 @Field

使用@Field,我们可以配置我们想要在MongoDB持久化文档时使用的字段名称:

@Document
class User {

    // ...

    @Field("email")
    String emailAddress;

    // ...
}

请注意,此注解是JPA中@Column的Mongo等价物。

4.3 @Query

使用@Query,我们可以在MongoDB Repository方法上提供查找器查询:

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

4.4 @EnableMongoRepositories

要使用MongoDBRepository,我们必须向Spring指出它。我们可以使用@EnableMongoRepositories来做到这一点。

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

@Configuration
@EnableMongoRepositories
class MongoConfig {}

Spring将在这个@Configuration类的子包中查找Repository。我们可以使用basePackages参数改变这种行为:

@Configuration
@EnableMongoRepositories(basePackages = "cn.tuyucheng.taketoday.repository")
class MongoConfig {}

另请注意,如果Spring Boot在类路径上找到Spring Data MongoDB,它会自动执行此操作。

5. 总结

在本文中,我们了解了使用Spring处理一般数据所需的最重要的注解。此外,我们研究了最常见的JPA和MongoDB注解。

与往常一样,本教程的完整源代码可在GitHub上获得。

Show Disqus Comments

Post Directory

扫码关注公众号:Taketoday
发送 290992
即可立即永久解锁本站全部文章