Spring Data是Spring 的一个子项目,用于简化数据库访问。Spring Data提供了对数据存储技术的抽象。使业务逻辑代码可以更加独立于底层的持久化实现。目前Spring Data支持NoSQL和关系数据库存储。
在本文中,我们将介绍Spring Data,Spring Data JPA和Spring Data MongoDB项目中最常见的注解。
当我们想要配置方法的事务行为时,我们可以使用:
@Transactional
void pay() {}
如果我们在类级别上使用此注解,那么它适用于类中的所有方法。但是我们也可以通过对特定方法来单独设置。
有时我们想要创建存储库接口,其唯一目标是为子存储库提供通用方法。也就是说,使用了该注解的接口不会被单独创建实例,只会作为其他接口的父接口而被使用。这个公共接口就需要这个注解@NoRepositoryBean来标识。
例如,如果我们想在所有存储库中使用Optional 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> {}
我们可以使用@Param将命名参数传递给我们的查询:
@Query("FROM Person p WHERE p.name = :name")
Person findByName(@Param("name") String name);
也可以传递Collection参数:
@Query(value = "SELECT u FROM User u WHERE u.name IN :names")
List<User> findUserByNameList(@Param("names") Collection<String> names);
@Id 将模型类中的字段标记为主键:
class Person {
@Id
Long id;
// ...
}
由于它与具体实现无关,因此它使模型类易于与多个数据存储引擎一起使用。
@Transient表示该属性并非一个到数据库表的字段的映射,ORM框架将忽略该属性。如果一个属性并非数据库表的字段映射,就务必将其标示为@Transient,数据存储引擎不会读取或写入此字段的值:
class Person {
// ...
@Transient
int age;
// ...
}
通过这些注解可以为我们的数据模型添加一些审计信息。
public class Person {
// ...
@CreatedBy
User creator;
@LastModifiedBy
User modifier;
@CreatedDate
Date createdAt;
@LastModifiedDate
Date modifiedAt;
// ...
}
使用@Query,我们可以为存储库方法提供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();
使用此注解我们可以轻松地从存储库调用存储过程。
首先,我们需要使用标准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 {}
之后,我们可以在存储库中使用我们在name参数中声明的名称来调用它:
@Procedure(name = "count_by_name")
long getCountByName(@Param("name") String name);
我们可以在执行查询方法时配置锁定模式:
@Lock(LockModeType.NONE)
@Query("SELECT COUNT(*) FROM Person p")
long getPersonCount();
可用的锁模式:
如果我们使用@Modifying进行注解,我们可以使用存储库方法修改数据:
@Modifying
@Query("UPDATE Person p SET p.name = :name WHERE p.id = :id")
void changeName(@Param("id") long id, @Param("name") String name);
使用@EnableJpaRepositories注解来指定开启JPA存储库。注意,我们必须在@Configuration中使用此注释:
@Configuration
@EnableJpaRepositories
class PersistenceJPAConfig {}
Spring将在此@Configuration 类的子包中查找存储库。可以使用basePackages 参数更改包的路径:
@Configuration
@EnableJpaRepositories(basePackages = "org.peterwanghao.persistence.dao")
class PersistenceJPAConfig {}
此注解将类标记为我们要保留到数据库的域对象:
@Document
class User {}
它还允许我们选择我们想要使用的集合的名称:
@Document(collection = "user")
class User {}
此注解类似于JPA中的@Entity。
使用@Field,我们可以配置MongoDB持久化保存文档时要使用的字段的名称:
@Document
class User {
// ...
@Field("email")
String emailAddress;
// ...
}
此注解类似于JPA中的@Column。
使用@Query,可以在MongoDB存储库方法上提供查询:
@Query("{ 'name' : ?0 }")
List<User> findUsersByName(String name);
使用@EnableMongoRepositories注解来指定开启MongoDB存储库。类似于JPA中的@EnableJpaRepositories。
在本文中,我们看到了使用Spring时我们需要处理数据的最主要的一些注解。此外,我们介绍了最常见的JPA和MongoDB注解。