3.2.2 定义 Repository 接口
幸运的是,我们已经创建了 IngredientRepository 和 OrderRepository,定义存储库的工作已经完成。但我们需要对它们做一点微小的改变,以使它们与 Spring Data JDBC 一起工作。
Spring Data 将在运行时,自动为我们的存储库接口生成实现类。但它只会对扩展自 Spring Data 几个 Repository 接口的类执行此操作。所以,我们的存储库接口需要扩展自 Repository,以便 Spring Data 知道要自动创建实现类。例如,以下是您可能编写的 IngredientRepository,扩展自 Repository :
package tacos.data;
import java.util.Optional;
import org.springframework.data.repository.Repository;
import tacos.Ingredient;
public interface IngredientRepository
extends Repository<Ingredient, String> {
Iterable<Ingredient> findAll();
Optional<Ingredient> findById(String id);
Ingredient save(Ingredient ingredient);
}
如您所见,存储库接口是参数化的。第一个参数是要由该存储库持久化的对象 —— 在本例中为 Ingredient。第二个参数是持久化对象的 ID 字段的类型。对于 Ingredient,是 String。
通过扩展 Repository,如上所示的 IngredientRepository 能够正常工作。Spring Data 还提供 CrudRepository 作为常见操作的基本接口,包括三个我们在 IngredientRepository 中定义的方法。因此,我们可以不扩展 Repository,而通常更方便的扩展 CrudRepository,如下所示:
package tacos.data;
import org.springframework.data.repository.CrudRepository;
import tacos.Ingredient;
public interface IngredientRepository
extends CrudRepository<Ingredient, String> {
}
同样,我们的 OrderRepository 可以像这样扩展 CrudRepository:
package tacos.data;
import org.springframework.data.repository.CrudRepository;
import tacos.TacoOrder;
public interface OrderRepository
extends CrudRepository<TacoOrder, Long> {
}
在这两种情况下,因为 CrudRepository 已经定义了所需的方法,所以没有必要在 IngredientRepository 和 OrderRepository 接口中显式定义它们。
现在您有了两个存储库。您可能认为您需要写这两个存储库的实现,包括 Crudepository 中定义的十几个方法。但 Spring Data 给您带来了好消息,根本不需要编写实现类!不管什么时候,只要应用程序启动了,Spring Data 将自动生成一个实现类。这意味着存储库从一开始就已经可以使用了。只需将它们注入控制器,您的工作就完成了。
此外,因为 Spring Data 在运行时将自动创建这些接口的实现,您不再需要显式实现 JdbcIngredientRepository 和 JdbcOrderRepository。您可以删除这两个类,根本不必有任何担心!