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 根本就不会找上门来。

相关文章
相关标签/搜索