Spring学习笔记(八)Spring Data JPA学习

简介: Spring学习笔记(八)Spring Data JPA学习

jpa简单的命名规则如下,这个不多做介绍,放在这里也是给自己以后查找起来方便,这篇文章主要介绍之前一直忽略了的几个点,像@NoRepositoryBean这个注解,以及怎么自定义Repository的实现。

image.pngimage.png

@NoRepositoryBean

我们查看JpaRepository这个类的继承关系可以看到下面这张图

image.png

而在JpaRepository,PagingAndSortingRepository,QueryByExampleExecutor,这三个接口上我们都能发现这个注解@NoRepositoryBean,这个注解到底有上面用呢?

我们来看下官网的解释:

image.png

上面这段话大致的意思是:只要在相应的Repository接口上添加了这个注解,Spring就不会在运行时为这个接口创建对应的实例。

看到这里估计有的同学更加迷惑了,这又是什么意思呢?我们来看下面这段代码:

我定义了一个Repository接口

public interface UserRepository extends JpaRepository<User, Integer> {
    /**
     * 根据id查询
     *
     * @param part
     * @return
     */
    List<User> findFirstByUseEmailLike(String part);
}

启动类如下:

package com.study.spring.springdatajpa;
import com.study.spring.springdatajpa.config.CustomRepositoryFactoryBean;
import com.study.spring.springdatajpa.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
@SpringBootApplication
@EnableJpaRepositories(basePackages = {"com.study.spring.springdatajpa.repository"})
public class SpringDataJpaApplication implements ApplicationRunner {
    @Autowired
    UserRepository userRepository;
    public static void main(String[] args) {
        SpringApplication.run(SpringDataJpaApplication.class, args);
    }
    @Override
    public void run(ApplicationArguments args) throws Exception {
       userRepository.findFirstByUseEmailLike("*.com")
    }
}

断点调试如下:




可以看到,虽然我们定义了一个userRepository接口,但是Spring为我们生成了一个代理对象,并且这个代理对象代理是org.springframework.data.jpa.repository.support.SimpleJpaRepository这个类。


我们看下SimpleJpaRepository这个类的继承关系:

image.png

可以发现,SimpleJpaRepository实现了JpaRepository这个接口。


其实在程序初始化的时候,SpringBoot会通过这个注解@EnableJpaRepositories(basePackages = {"com.study.spring.springdatajpa.repository"})将我们配置的包下的所有继承0了JpaRepository这个接口的接口,注册到spring容器中,然后以SimpleJpaRepository为目标对象创建代理对象。


我们知道对应的接口有3个,为什么它们没被创建代理对象呢?这样就要说到我们提到的注解@NoRepositoryBean了,JpaRepository,PagingAndSortingRepository,QueryByExampleExecutor这个3个接口都被这个注解标注了,所以不会被创建代理对象,这也是这个注解的作用


利用@NoRepositoryBean来自定义一个Repository的实现

我们要达到的目的就是,定义一个Repository接口(仿JpaRepository),只要有别的接口继承了这个类,就自动拥有这个接口对应的实现类(仿SimpleJpaRepository)中的方法。


代码如下:


1.定义接口:

package com.wisely.support;
import java.io.Serializable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.NoRepositoryBean;
@NoRepositoryBean  //指明当前这个接口不是领域类的接口
//我们自定义的CustomRepository继承了JpaRepository接口,具备JPA的能力
public interface CustomRepository<T, ID extends Serializable> extends JpaRepository<T, ID>, JpaSpecificationExecutor<T> {
    //要定义的数据操作方法在接口中定义
    void doWithId(ID id);
}

2.定义接口实现类

//要实现 CustomRepository接口,继承SimpleJpaRepository类让我们可以使用其提供的方法(如findAll)
public class CustomRepositoryImpl<T, ID extends Serializable>
        extends SimpleJpaRepository<T, ID> implements CustomRepository<T, ID> {
    //数据操作方法会用到entityManager,我们这里没有用到
    private final EntityManager entityManager;
    //CustomRepositoryImpl的构造函数,
    // 需当前处理的领域类和entityManager作为构造参数,在这里也给entityManager赋值了
    public CustomRepositoryImpl(Class<T> domainClass, EntityManager entityManager) {
        super(domainClass, entityManager);
        this.entityManager = entityManager;
    }
    @Override
    public void doWithId(ID id) {
        //定义数据访问操作,如调用findAll方法并构造一些查询条件
        System.out.println("拿到id干点事儿");
    }
}

3.自定义一个RepositoryFactoryBean

//自定义CustomRepositoryFactoryBean,继承JpaRepositoryFactoryBean
public class CustomRepositoryFactoryBean<T extends JpaRepository<S, ID>, S, ID extends Serializable>
        extends JpaRepositoryFactoryBean<T, S, ID> {
    public CustomRepositoryFactoryBean(Class<? extends T> repositoryInterface) {
        super(repositoryInterface);
    }
    @Override
    //重写createRepositoryFactory方法,用当前的CustomRepositoryFactory创建实例
    protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {
        return new CustomRepositoryFactory(entityManager);  //该类见下面的定义
    }
    //定义一个私有的静态类,并继承JpaRepositoryFactory
    //复写其中两个核心方法
    private static class CustomRepositoryFactory extends JpaRepositoryFactory {
        //构造函数
        public CustomRepositoryFactory(EntityManager entityManager) {
            super(entityManager);
        }
        @Override
        protected JpaRepositoryImplementation<?, ?> getTargetRepository(RepositoryInformation information, EntityManager entityManager) {
            return new CustomRepositoryImpl<>(information.getDomainType(), entityManager);
        }
        @Override
        protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {// 获得当前自定义类的类型
            return CustomRepositoryImpl.class;
        }
    }
}

4.启动类代码,注意上面的注解

@SpringBootApplication
//@EnableJpaRepositories(basePackages = //{"com.study.spring.springdatajpa.repository"})
@EnableJpaRepositories(repositoryFactoryBeanClass = CustomRepositoryFactoryBean.class)
public class SpringDataJpaApplication implements ApplicationRunner {
    @Autowired
    UserRepository userRepository;
    public static void main(String[] args) {
        SpringApplication.run(SpringDataJpaApplication.class, args);
    }
    @Override
    public void run(ApplicationArguments args) throws Exception {
        userRepository.doWithId(11);
    }
}

运行程序打印结果如下:

拿到id干点事儿
相关文章
|
9天前
|
前端开发 Java 开发者
Spring生态学习路径与源码深度探讨
【11月更文挑战第13天】Spring框架作为Java企业级开发中的核心框架,其丰富的生态系统和强大的功能吸引了无数开发者的关注。学习Spring生态不仅仅是掌握Spring Framework本身,更需要深入理解其周边组件和工具,以及源码的底层实现逻辑。本文将从Spring生态的学习路径入手,详细探讨如何系统地学习Spring,并深入解析各个重点的底层实现逻辑。
35 9
|
29天前
|
前端开发 Java 数据库
SpringBoot学习
【10月更文挑战第7天】Spring学习
34 9
|
30天前
|
XML Java 数据格式
Spring学习
【10月更文挑战第6天】Spring学习
19 1
|
1月前
|
Java 测试技术 开发者
springboot学习四:Spring Boot profile多环境配置、devtools热部署
这篇文章主要介绍了如何在Spring Boot中进行多环境配置以及如何整合DevTools实现热部署,以提高开发效率。
56 2
|
1月前
|
前端开发 Java 程序员
springboot 学习十五:Spring Boot 优雅的集成Swagger2、Knife4j
这篇文章是关于如何在Spring Boot项目中集成Swagger2和Knife4j来生成和美化API接口文档的详细教程。
84 1
|
Java Spring Kotlin
第2讲 Kotlin + Spring Boot 集成 JPA 【Kotlin + Spring Boot 服务端开发课程系列】
【Kotlin + Spring Boot 服务端开发课程系列】第2讲 Kotlin + Spring Boot 集成 JPA 【视频教程】 投影片01.
1074 0
|
Java Spring 测试技术
Spring Boot集成JPA的Column注解命名字段无效的问题
偶然发现,Spring Boot集成jpa编写实体类的时候,默认使用的命名策略是下划线分隔的字段命名。
3996 0
|
SQL Java 数据库
6.2 Spring Boot集成jpa
6.2 Spring Boot集成jpa Java持久化API(JPA,Java Persistence API)是一个将对象映射为关系数据库的标准技术。
1022 0
|
Java 数据库连接 Spring
|
XML Java 数据库连接
spring集成jpa【为什么有 persistant.xml 文件呢?】
原文地址: http://www.cnblogs.com/javahuang/archive/2012/12/19/2824633.html spring集成JPA的其中一种方式 JPA和hibernate的关系: spring对JPA的集成.
726 0