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

时间:2022-02-24 06:05:03

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

关键字 方法命名 sql where字句
And findByNameAndPwd where name= ? and pwd =?
Or findByNameOrSex where name= ? or sex=?
Is,Equals findById,findByIdEquals where id= ?
Between findByIdBetween where id between ? and ?
LessThan findByIdLessThan where id < ?
LessThanEquals findByIdLessThanEquals where id <= ?
GreaterThan findByIdGreaterThan where id > ?
GreaterThanEquals findByIdGreaterThanEquals where id > = ?
After findByIdAfter where id > ?
Before findByIdBefore where id < ?
IsNull findByNameIsNull where name is null
isNotNull,NotNull findByNameNotNull where name is not null
Like findByNameLike where name like ?
NotLike findByNameNotLike where name not like ?
StartingWith findByNameStartingWith where name like ‘?%’
EndingWith findByNameEndingWith where name like ‘%?’
Containing findByNameContaining where name like ‘%?%’
OrderBy findByIdOrderByXDesc where id=? order by x desc
Not findByNameNot where name <> ?
In findByIdIn(Collection<?> c) where id in (?)
NotIn findByIdNotIn(Collection<?> c) where id not in (?)
True findByAaaTrue where aaa = true
False findByAaaFalse where aaa = false
IgnoreCase findByNameIgnoreCase where UPPER(name)=UPPER(?)

@NoRepositoryBean

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

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

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

​ 我们来看下官网的解释:

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

​ 上面这段话大致的意思是:只要在相应的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")
}
}

断点调试如下:

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

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

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

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

​ 可以发现,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干点事儿

Spring学习笔记(八)Spring Data JPA学习的更多相关文章

  1. Spring实战第五章学习笔记————构建Spring Web应用程序

    Spring实战第五章学习笔记----构建Spring Web应用程序 Spring MVC基于模型-视图-控制器(Model-View-Controller)模式实现,它能够构建像Spring框架那 ...

  2. Spring实战第八章学习笔记————使用Spring Web Flow

    Spring实战第八章学习笔记----使用Spring Web Flow Spring Web Flow是一个Web框架,它适用于元素按规定流程运行的程序. 其实我们可以使用任何WEB框架写流程化的应 ...

  3. Java架构师之路 Spring学习笔记&lpar;一&rpar; Spring介绍

    前言 这是一篇原创的Spring学习笔记.主要记录我学习Spring4.0的过程.本人有四年的Java Web开发经验,最近在面试中遇到面试官总会问一些简单但我不会的Java问题,让我觉得有必要重新审 ...

  4. go微服务框架kratos学习笔记八 &lpar;kratos的依赖注入&rpar;

    目录 go微服务框架kratos学习笔记八(kratos的依赖注入) 什么是依赖注入 google wire kratos中的wire Providers injector(注入器) Binding ...

  5. 【opencv学习笔记八】创建TrackBar轨迹条

    createTrackbar这个函数我们以后会经常用到,它创建一个可以调整数值的轨迹条,并将轨迹条附加到指定的窗口上,使用起来很方便.首先大家要记住,它往往会和一个回调函数配合起来使用.先看下他的函数 ...

  6. Learning ROS forRobotics Programming Second Edition学习笔记&lpar;八&rpar;indigo rviz gazebo

    中文译著已经出版,详情请参考:http://blog.csdn.net/ZhangRelay/article/category/6506865 Learning ROS forRobotics Pro ...

  7. python3&period;4学习笔记&lpar;八&rpar; Python第三方库安装与使用,包管理工具解惑

    python3.4学习笔记(八) Python第三方库安装与使用,包管理工具解惑 许多人在安装Python第三方库的时候, 经常会为一个问题困扰:到底应该下载什么格式的文件?当我们点开下载页时, 一般 ...

  8. Go语言学习笔记八: 数组

    Go语言学习笔记八: 数组 数组地球人都知道.所以只说说Go语言的特殊(奇葩)写法. 我一直在想一个人参与了两种语言的设计,但是最后两种语言的语法差异这么大.这是自己否定自己么,为什么不与之前统一一下 ...

  9. Redis学习笔记八:集群模式

    作者:Grey 原文地址:Redis学习笔记八:集群模式 前面提到的Redis学习笔记七:主从复制和哨兵只能解决Redis的单点压力大和单点故障问题,接下来要讲的Redis Cluster模式,主要是 ...

  10. Java IO学习笔记八:Netty入门

    作者:Grey 原文地址:Java IO学习笔记八:Netty入门 多路复用多线程方式还是有点麻烦,Netty帮我们做了封装,大大简化了编码的复杂度,接下来熟悉一下netty的基本使用. Netty+ ...

随机推荐

  1. 艺萌TCP文件传输及自动更新系统介绍(TCP文件传输)(四)

    艺萌TCP文件上传下载及自动更新系统介绍(TCP文件传输) 该系统基于开源的networkComms通讯框架,此通讯框架以前是收费的,目前已经免费并开源,作者是英国的,开发时间5年多,框架很稳定. 项 ...

  2. Nodejs简单介绍以及在windows环境下安装与配置流程

    简介 一. Nodejs是什么? Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境.Node.js 使用了一个事件驱动.非阻塞式 I/O 的模型,使其轻量又高效. ...

  3. 新手容易混乱的String&plus;和StringBuffer,以及Java的方法参数传递方式。

    之前在交流群里和猿友们讨论string+和stringbuffer哪个速度快以及Java的方法参数传递的问题,引起了群里猿友的小讨论.最终LZ得出的结果是string+没有stringbuffer快, ...

  4. 使用PHP绘制统计图

    使用PHP画统计图的方法 第一种方法 <?php //最后一次修改:2004-6-21 //一个生成矩形图,曲线图的图形分析类 //作者:tonera //说明: //任何人可在任何场合*使用 ...

  5. 部署 外网 ASP&period;NET程序时, IIS安全性 配置 -摘自网络

    最近,和朋友们在聊及ASP.NET程序的安全性没有JAVA高,IIS(Internet Infomartion Server)的存在很多漏洞(以及新型蠕虫,例如Code Red 和Nimda),安全得 ...

  6. 【JAVA - SSM】之MyBatis动态SQL

    动态SQL就是在SQL语句中添加一些标签,以完成某些逻辑.通常用到的动态SQL标签有<if>.<choose>.<where>.<trim>.<s ...

  7. floyd&plus;动态规划 hdu-4571-Travel in time

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4571 题目大意: 有n个景点,每个点都有个游玩时间ci,游玩后得到的满意度si.给一个起点s和终点e ...

  8. Oracle EBS-SQL &lpar;BOM-17&rpar;&colon;检查8层BOM&period;sql

    define item1="1234567890" select a1.产品编码, a1.产品描述, '1层'         层数, a1.物料编码, a1.物料描述, a1.单 ...

  9. JVM的内存区域划分以及垃圾回收机制详解

    在我们写Java代码时,大部分情况下是不用关心你New的对象是否被释放掉,或者什么时候被释放掉.因为JVM中有垃圾自动回收机制.在之前的博客中我们聊过Objective-C中的MRC(手动引用计数)以 ...

  10. debug和release下PostThreadMessage的异同

    MFC中创建线程分为工作线程和UI线程.其中UI线程可以通过继承CWinThread进行创建. 创建函数如下: CWinThread *m_pRecogThread;//语音识别线程 m_pRecog ...