Spring data jpa 梳理

一直搞不懂棟哥的各類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 調用父類 DcBaseServicequeryPage 方法。接口

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 也是自動注入的。

對於dcJpaRepositoryuserRepouserRepo的類型是dcJpaRepository的子類,User也能夠當作T的子類, 那麼,這二者應該是同一個實例,即子類實例userRepo,但userRepo的類型是接口,它的實例從哪來?

Debug

因而開始debug,兩種狀況以下

  1. 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 的依賴,是在方法調用須要時才注入(想一想都是一個很複雜的過程)。

  2. 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,再回頭看最初的類圖,推論以下:

  1. 正如直接寫UserRepo繼承JpaRepository同樣,後者定義的方法,如findOne,是由SimpleJpaRepository類來實現的。 queryPage是由DcJpaRepository接口定義,DcJpaRepositorySupport實現的。

  2. 由於多態,Spring 能夠經過類型自動注入子類實例,而這個實現類,必然加持@Repository註解(或其它), 之因此DcJpaRepositorySupport能夠被注入,是由於它繼承了SimpleJpaRepository

  3. 若是沒有自定義的Repository實現,繼承DcBaseService的 service 能夠不用再注入任何 xxxRepo,由於 Spring 根本就不會找上門來。

相關文章
相關標籤/搜索