一直搞不懂棟哥的各類EQ啊EXIST啊什麼的,說實話,我很是討厭數據庫和sql...sql
可是,逃不掉的,必需要看懂了 /(ㄒoㄒ)/~~數據庫
先來一張圖app
首先,咱們須要繼承以加入框架框架
servicethis
@Service public class UserService extends DcBaseService<User> { @Autowired private UserRepo userRepo; }
repodebug
public interface UserRepo extends DcJpaRepository<User, String> { }
service 和 repo 層的代碼幾乎什麼都不用寫。code
這裏來看一次分頁的過程。繼承
UserService
調用父類 DcBaseService
的 queryPage
方法。接口
DcJpaRepository
代碼圖片
@NoRepositoryBean public interface DcJpaRepository<T, PK extends Serializable> extends JpaRepository<T, PK> { Page<T> queryPage(DcQuery var1); }
DcBaseService
代碼
@Transactional public class DcBaseService<T extends IDAble> { @Autowired private DcJpaRepository<T, String> dcJpaRepository; public Page<T> queryPage(DcQuery dcQuery) { return this.dcJpaRepository.queryPage(dcQuery); } }
DcBaseService
中的queryPage
方法中調用了自動注入的 dcJpaRepository
實例,但這個實例究竟是什麼呢?
回頭來看,UserService
中的 userRepo
也是自動注入的。
對於dcJpaRepository
和userRepo
, userRepo
的類型是dcJpaRepository
的子類,User
也能夠當作T
的子類, 那麼,這二者應該是同一個實例,即子類實例userRepo
,但userRepo
的類型是接口,它的實例從哪來?
因而開始debug,兩種狀況以下
UserService
自有方法
UserController
@GetMapping("/123") public void getAll(@PageableDefault Pageable page) { System.out.println(ticketService.ticketRepo); ticketService.findAllabc(); // ticketService.queryPage(null); }
UserService
public void findAllabc() { System.out.println(this.ticketRepo); }
因而可知,實例類型爲DcJpaRepositorySupport
,順便看到了 Spring 的依賴,是在方法調用須要時才注入(想一想都是一個很複雜的過程)。
DcBaseService
父類方法
UserController
@GetMapping("/123") public void getAll(@PageableDefault Pageable page) { System.out.println(ticketService.ticketRepo); // ticketService.findAllabc(); ticketService.queryPage(null); }
DcBaseService
public Page<T> queryPage(DcQuery dcQuery) { return this.dcJpaRepository.queryPage(dcQuery); }
如圖,實例類型仍是DcJpaRepositorySupport
。
經過以上兩種狀況,查看這個DcJpaRepositorySupport
源碼以下
public class DcJpaRepositorySupport<T, PK extends Serializable> extends SimpleJpaRepository<T, PK> implements DcJpaRepository<T, PK> { public Page<T> queryPage(DcQuery dcQuery) { return this.findAll(.......); } }
Ok,再回頭看最初的類圖,推論以下:
正如直接寫UserRepo
繼承JpaRepository
同樣,後者定義的方法,如findOne
,是由SimpleJpaRepository
類來實現的。 queryPage
是由DcJpaRepository
接口定義,DcJpaRepositorySupport
實現的。
由於多態,Spring 能夠經過類型自動注入子類實例,而這個實現類,必然加持@Repository
註解(或其它), 之因此DcJpaRepositorySupport
能夠被注入,是由於它繼承了SimpleJpaRepository
。
若是沒有自定義的Repository
實現,繼承DcBaseService
的 service 能夠不用再注入任何 xxxRepo
,由於 Spring 根本就不會找上門來。