Spring Data JPA框架系列(三)-自定义Repository接口详解

2.1 自定义Repository接口

要定义一个repository接口,你首先需要自定义一个实体类专用的Repository接口。该接口必须扩展 Repository,并将其类型指定为实体类和实体类的 ID 类型。

如果你想为该实体类资源类型开放CRUD方法,请直接继承CrudRepository而不是Repository。

2.1.1 repository接口定义

通常,你的repository接口会扩展Repository、CrudRepository或PagingAndSortingRepository。

如果你不想扩展Spring Data接口,你也可以用@RepositoryDefinition来注解你的repository接口。

继承CrudRepository接口会公开一套完整的CRUD方法来操作你的实体类对象, 如果你希望自行决定暴露哪些方法,可以从CrudRepository中复制你想暴露的方法到你的自定义的repository接口中即可。

通过以上的操作可以让你在所提供的Spring Data Repositories功能的基础上定义自己的repository接口抽象。

下面通过实例展示了如何有选择地对外开放某些指定的CRUD方法(本例中对外开放findById和save接口方法)。

选择性对外暴露指定CRUD方法让其他人使用

@NoRepositoryBean
interface MyBaseRepository<T, ID> extends Repository<T, ID> {

  Optional<T> findById(ID id);

  <S extends T> S save(S entity);
}

interface UserRepository extends MyBaseRepository<User, Long> {
  User findByEmailAddress(EmailAddress emailAddress);
}

在前面的例子中,我们为所有的repository定义了一个通用的基础接口,并暴露了findById(…)以及save(…)方法。

这些方法被路由到Spring Data提供的你所选择的store的基础repository实现(例如,如果你使用JPA,实现就是SimpleJpaRepository),因为它们与CrudRepository中的方法签名一致。所以UserRepository现在可以保存用户,通过ID找到单个用户,并触发查询,通过电子邮件地址找到用户对象。

自定义的中间repository接口上需要添加@NoRepositoryBean。但是请特别注意,在所有Spring Data需要在运行时动态创建实例的repository接口上一定不要添加该注解。

就比如上面的示例代码,

- MyBaseRepository就是中间repository接口, 我们需要使用他来自定义对外开放哪些CRUD方法,需要添加@NoRepositoryBean注解, 这个注解的意思就是一个标记,为了通知JPA不要创建该接口的bean对象

  • 这个@NoRepositoryBean就是用在中间repository接口上的, 但是从中间接口派生出具体的repository接口, 对应上面的示例代码就是UserRepository接口, 在这个接口上一定不要添加@NoRepositoryBean注解,如果添加了, 这个UserRepository接口的bean对象就不会注入到容器中了
2.1.2 在多个Spring Data模块中使用Repository接口

在你的应用程序中使用一个唯一的的Spring Data模块使事情变得简单,因为定义范围内的所有存储库接口都绑定到Spring Data模块。有时,应用程序需要使用一个以上的Spring Data模块。在这种情况下,存储库定义必须区分持久化技术。当它检测到类classpath路径下有多个repository factory时,Spring Data会进入严格的respository配置模式。严格的配置使用respository或域类的细节来决定respository定义的Spring Data模块绑定。

如果资源库定义扩展了特定模块的资源库,那么它就是特定Spring Data模块的有效候选者。

如果域类被注解了特定模块的类型注解,它就是特定Spring Data模块的有效候选者。Spring Data模块接受第三方注解(如JPA的@Entity)或提供自己的注解(如Spring Data MongoDB和Spring Data Elasticsearch的@Document)。

下面的例子显示了一个使用特定模块接口的存储库(本例中为 JPA)。

例1. 使用module-specific接口的repository定义

interface MyRepository extends JpaRepository<User, Long> { }

@NoRepositoryBean
interface MyBaseRepository<T, ID> extends JpaRepository<T, ID> {}

interface UserRepository extends MyBaseRepository<User, Long> {}

MyRepository和UserRepository在其类型层次上扩展了JpaRepository。它们是Spring Data JPA模块的有效候选者。

下面的例子显示了一个使用通用接口的repository接口。

例2. 使用通用接口的repository定义

interface AmbiguousRepository extends Repository<User, Long> {}

@NoRepositoryBean
interface MyBaseRepository<T, ID> extends CrudRepository<T, ID> {}

interface AmbiguousUserRepository extends MyBaseRepository<User, Long> {}

AmbiguousRepository和AmbiguousUserRepository在其类型层次结构中只扩展了Repository和CrudRepository。虽然在使用唯一的Spring Data模块时,这很好,但多个模块无法区分这些repository接口应该被绑定到哪个特定的Spring Data。

下面的例子显示了一个使用带注解的领域类的repository接口。

例3. 使用带注解的domain类的repository定义

interface PersonRepository extends Repository<Person, Long> {}

@Entity
class Person {}

interface UserRepository extends Repository<User, Long> {}

@Document
class User {}

PersonRepository引用了Person,它被JPA的@Entity注解所注解,所以这个repository接口显然属于Spring Data JPA。UserRepository引用了User,它被Spring Data MongoDB的@Document注释所注解。

下面的坏例子显示了一个使用混合注解的domain类的repository接口。

例4. 使用混合注解的领域类的repository定义

interface JpaPersonRepository extends Repository<Person, Long> {}

interface MongoDBPersonRepository extends Repository<Person, Long> {}

@Entity
@Document
class Person {}

这个例子展示了一个同时使用JPA和Spring Data MongoDB注解的领域类。它定义了两个repository接口:JpaPersonRepository和MongoDBPersonRepository。一个用于JPA,另一个用于MongoDB的使用。Spring Data不再能够区分这些repository接口库,这导致了未定义的行为。

repository接口类型细节和区分domian类注释用于严格的repository接口配置,以确定特定Spring Data模块的repository接口候选者。在同一domain类型上使用多个持久化技术的特定注解是可能的,并且能够在多个持久化技术中重复使用domian类型。然而,Spring Data就不能再确定一个唯一的模块来绑定repository接口了。

区分repository的最后一个方法是通过对repository接口基础包的扫描。基础包定义了扫描repository接口定义的起点,这意味着将repository接口的定义放在适当的包中。默认情况下,注解驱动的配置使用配置类的包。基于XML的配置中的基础包是强制性的。

下面的例子显示了注释驱动的基本包的配置。

例5. 注释驱动的基础包配置

@EnableJpaRepositories(basePackages = "com.acme.repositories.jpa")
@EnableMongoRepositories(basePackages = "com.acme.repositories.mongo")
public class Configuration { 

}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您好,感谢您的提问。创建一个 Spring Data JPARepository 接口非常简单,只需要按照以下步骤操作即可: 1. 创建一个继承自 `JpaRepository` 的接口,指定实体类和主键类型: ``` public interface UserRepository extends JpaRepository<User, Long> { } ``` 其中,`User` 是您的实体类,`Long` 是实体类的主键类型。`JpaRepository` 是 Spring Data JPA 提供的一个基础 Repository 接口,提供了一些基本的数据操作方法,如插入、删除、更新、查询等。 2. 在您的实体类上添加注解,指定表名和主键: ``` @Entity @Table(name = "user") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String username; private String password; // 省略 getter 和 setter 方法 } ``` 在上述代码中,`@Entity` 注解表示该类是一个 JPA 实体类,`@Table(name = "user")` 指定该实体类对应的数据库表名为 `user`,`@Id` 和 `@GeneratedValue` 注解指定实体类的主键。 3. 在您的 Spring Boot 应用程序中,使用 `@EnableJpaRepositories` 注解启用 Spring Data JPA,并指定 Repository 接口的包路径: ``` @SpringBootApplication @EnableJpaRepositories(basePackages = "com.example.repository") public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } } ``` 在上述代码中,`@EnableJpaRepositories` 注解用于启用 Spring Data JPA,`basePackages` 属性指定 Repository 接口的包路径。 4. 在您的服务层或控制器中注入 Repository 接口,即可使用 Spring Data JPA 提供的基本数据操作方法: ``` @RestController public class UserController { @Autowired private UserRepository userRepository; @GetMapping("/users") public List<User> getAllUsers() { return userRepository.findAll(); } } ``` 在上述代码中,`@Autowired` 注解用于自动注入 `UserRepository` 对象,然后在 `getAllUsers` 方法中调用 `findAll` 方法获取所有用户信息。 通过上述步骤创建一个 Spring Data JPARepository 接口非常简单,希望能够帮助到您。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值