3.2.2 Định nghĩa các interface repository
May mắn thay, chúng ta đã tạo IngredientRepository và OrderRepository, vì vậy phần lớn công việc trong việc định nghĩa các repository đã hoàn thành. Tuy nhiên, chúng ta cần thực hiện một thay đổi nhỏ để có thể sử dụng chúng với Spring Data JDBC.
Spring Data sẽ tự động tạo ra các phần hiện thực cho các interface repository của chúng ta khi chạy ứng dụng. Nhưng nó chỉ làm điều đó đối với các interface mở rộng từ một trong các interface repository mà Spring Data cung cấp. Ít nhất, các interface repository của chúng ta cần phải mở rộng từ Repository để Spring Data biết rằng cần tạo phần hiện thực một cách tự động. Ví dụ, đây là cách bạn có thể viết IngredientRepository sao cho nó mở rộng từ 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);
}Như bạn có thể thấy, interface Repository là một interface có tham số hóa. Tham số đầu tiên là kiểu của đối tượng sẽ được lưu trữ bởi repository này—trong trường hợp này là Ingredient. Tham số thứ hai là kiểu của trường ID của đối tượng được lưu trữ. Đối với Ingredient, đó là String.
Mặc dù IngredientRepository sẽ hoạt động như đã trình bày ở đây bằng cách mở rộng Repository, Spring Data cũng cung cấp CrudRepository như một interface cơ sở cho các thao tác phổ biến, bao gồm ba phương thức mà chúng ta đã định nghĩa trong IngredientRepository. Vì vậy, thay vì mở rộng Repository, thường thì dễ hơn khi mở rộng CrudRepository, như được trình bày tiếp theo.
package tacos.data;
import org.springframework.data.repository.CrudRepository;
import tacos.Ingredient;
public interface IngredientRepository
extends CrudRepository<Ingredient, String> {
}Similarly, our OrderRepository can extend CrudRepository as shown in the next listing.
package tacos.data;
import org.springframework.data.repository.CrudRepository;
import tacos.TacoOrder;
public interface OrderRepository
extends CrudRepository<TacoOrder, Long> {
}Trong cả hai trường hợp, vì CrudRepository đã định nghĩa sẵn các phương thức bạn cần, nên không cần phải định nghĩa rõ ràng lại chúng trong các interface IngredientRepository và OrderRepository.
Và giờ đây bạn đã có hai repository của mình. Có thể bạn đang nghĩ rằng cần phải viết phần hiện thực cho cả hai repository này, bao gồm hàng tá phương thức được định nghĩa trong CrudRepository. Nhưng đây chính là điểm hay của Spring Data—bạn không cần phải viết phần hiện thực! Khi ứng dụng khởi động, Spring Data sẽ tự động tạo phần hiện thực ngay lập tức. Điều này có nghĩa là các repository đã sẵn sàng để sử dụng ngay từ đầu. Chỉ cần inject chúng vào controller là xong.
Hơn nữa, vì Spring Data tự động tạo phần hiện thực cho các interface này khi chạy, bạn không cần phải giữ lại các phần hiện thực thủ công trong JdbcIngredientRepository và JdbcOrderRepository. Bạn có thể xóa hai lớp đó và không cần nhìn lại nữa!
