1、简介 {#1简介}
Spring Data 提供了对数据存储技术的抽象。因此,我们的业务逻辑代码可以更加独立于底层持久化实现。而且,Spring 还简化了处理与数据存储相关的实现细节的过程。
本文将带你了解 Spring Data、Spring Data JPA 和 Spring Data MongoDB 项目中最常见的注解。
2、常见的 Spring Data 注解 {#2常见的-spring-data-注解}
2.1、@Transactional {#21transactional}
@Transactional
用于定义事务方法:
@Transactional
void pay() {}
如果在类上应用此注解,那么它就会对类中的所有方法起作用。也可以在方法上定义此注解来进行覆盖。
2.2、@NoRepositoryBean {#22norepositorybean}
有时我们会通过一个基本的 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 {#23param}
使用 @Param
将命名参数传递给查询:
@Query("FROM Person p WHERE p.name = :name")
Person findByName(@Param("name") String name);
这里使用 :name
语法来引用参数。
2.4、@Id {#24id}
@Id
将 Model 类中的一个字段标记为主键:
class Person {
@Id
Long id;
// ...
}
由于它与具体实现无关,使得 Model 类在多个数据存储引擎中易于使用。
2.5、@Transient {#25transient}
可以使用此注解将 Model 类中的一个字段标记为瞬时(transient)字段。这样,数据存储引擎就不会读取或写入这个字段的值:
class Person {
// ...
@Transient
int age;
// ...
}
与 @Id
一样,@Transient
也是独立于实现的,这使得它可以方便地与多个数据存储实现一起使用。
2.6、@CreatedBy、@LastModifiedBy、@CreatedDate 和 @LastModifiedDate {#26createdbylastmodifiedbycreateddate-和-lastmodifieddate}
审计注解: Spring 会自动在注解字段中填入对象创建者、对象最后修改者、创建日期和最后修改日期:
public class Person {
// ...
@CreatedBy
User creator;
@LastModifiedBy
User modifier;
@CreatedDate
Date createdAt;
@LastModifiedDate
Date modifiedAt;
// ...
}
如果想让 Spring 来填充当前用户,还需要使用 Spring Security。
3、Spring Data JPA 注解 {#3spring-data-jpa-注解}
3.1、@Query {#31query}
通过 @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 {#32procedure}
通过 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 {#33lock}
可以在执行 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 {#34modifying}
@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 {#35enablejparepositories}
要使用 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 注解 {#4spring-data-mongo-注解}
Spring Data 让使用 MongoDB 变得更加容易。
4.1、@Document {#41document}
该注解将一个类标记为要持久化到数据库的 Domain 对象:
@Document
class User {}
它还允许选择要使用的集合(collection
)名称:
@Document(collection = "user")
class User {}
该注解类似于 JPA 中的 @Entity
。
4.2、@Field {#42field}
通过 @Field
配置 MongoDB 持久化文档(Document)时要使用的字段名称:
@Document
class User {
// ...
@Field("email")
String emailAddress;
// ...
}
该注解等同于 JPA 中的 @Column
。
4.3、@Query {#43query}
通过 @Query
,可以在 MongoDB Repository 方法上提供 find
查询:
@Query("{ 'name' : ?0 }")
List<User> findUsersByName(String name);
4.4、@EnableMongoRepositories {#44enablemongorepositories}
同样,要使用 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、总结 {#5总结}
本文介绍了 Spring Data、Spring Data JPA 和 Spring Data MongoDB 项目中最常见的注解及其作用和使用方法。
Ref:https://www.baeldung.com/spring-data-annotations