Spring学习笔记(八)Spring Data JPA学习
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这个类的继承关系可以看到下面这张图
而在JpaRepository,PagingAndSortingRepository,QueryByExampleExecutor,这三个接口上我们都能发现这个注解@NoRepositoryBean,这个注解到底有上面用呢?
我们来看下官网的解释:
上面这段话大致的意思是:只要在相应的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这个类的继承关系:
可以发现,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)中的方法。
代码如下:
定义接口:
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);
}
定义接口实现类
//要实现 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干点事儿");
} }
自定义一个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;
}
}
}
启动类代码,注意上面的注解
@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学习的更多相关文章
- Spring实战第五章学习笔记————构建Spring Web应用程序
Spring实战第五章学习笔记----构建Spring Web应用程序 Spring MVC基于模型-视图-控制器(Model-View-Controller)模式实现,它能够构建像Spring框架那 ...
- Spring实战第八章学习笔记————使用Spring Web Flow
Spring实战第八章学习笔记----使用Spring Web Flow Spring Web Flow是一个Web框架,它适用于元素按规定流程运行的程序. 其实我们可以使用任何WEB框架写流程化的应 ...
- Java架构师之路 Spring学习笔记(一) Spring介绍
前言 这是一篇原创的Spring学习笔记.主要记录我学习Spring4.0的过程.本人有四年的Java Web开发经验,最近在面试中遇到面试官总会问一些简单但我不会的Java问题,让我觉得有必要重新审 ...
- Spring 源码学习笔记10——Spring AOP
Spring 源码学习笔记10--Spring AOP 参考书籍<Spring技术内幕>Spring AOP的实现章节 书有点老,但是里面一些概念还是总结比较到位 源码基于Spring-a ...
- Spring 源码学习笔记11——Spring事务
Spring 源码学习笔记11--Spring事务 Spring事务是基于Spring Aop的扩展 AOP的知识参见<Spring 源码学习笔记10--Spring AOP> 图片参考了 ...
- go微服务框架kratos学习笔记八 (kratos的依赖注入)
目录 go微服务框架kratos学习笔记八(kratos的依赖注入) 什么是依赖注入 google wire kratos中的wire Providers injector(注入器) Binding ...
- 【opencv学习笔记八】创建TrackBar轨迹条
createTrackbar这个函数我们以后会经常用到,它创建一个可以调整数值的轨迹条,并将轨迹条附加到指定的窗口上,使用起来很方便.首先大家要记住,它往往会和一个回调函数配合起来使用.先看下他的函数 ...
- Learning ROS forRobotics Programming Second Edition学习笔记(八)indigo rviz gazebo
中文译著已经出版,详情请参考:http://blog.csdn.net/ZhangRelay/article/category/6506865 Learning ROS forRobotics Pro ...
- python3.4学习笔记(八) Python第三方库安装与使用,包管理工具解惑
python3.4学习笔记(八) Python第三方库安装与使用,包管理工具解惑 许多人在安装Python第三方库的时候, 经常会为一个问题困扰:到底应该下载什么格式的文件?当我们点开下载页时, 一般 ...
- Go语言学习笔记八: 数组
Go语言学习笔记八: 数组 数组地球人都知道.所以只说说Go语言的特殊(奇葩)写法. 我一直在想一个人参与了两种语言的设计,但是最后两种语言的语法差异这么大.这是自己否定自己么,为什么不与之前统一一下 ...
随机推荐
- 【Jenkins】参数化引用
我们在Jenkins里设置了参数如下 1. Jenkins中引用 shell引用 $env windows bat引用 %env% 在git等源码管理时,调用参数的格式${env} 2. jmete ...
- Go gRPC进阶-go-grpc-middleware使用(八)
前言 上篇介绍了gRPC中TLS认证和自定义方法认证,最后还简单介绍了gRPC拦截器的使用.gRPC自身只能设置一个拦截器,所有逻辑都写一起会比较乱.本篇简单介绍go-grpc-middleware的 ...
- Java的自动装箱
JDK5的新特性自动装箱:把基本类型转换为包装类类型自动拆箱:把包装类类型转换为基本类型 注意一个小问题: 在使用时,Integer x = null;代码就会出现NullPointerExcepti ...
- java 容器(collection)--ArrayList 常用方法分析 源码分析
ArrayList 介绍 打开jdk源码看看官方文档的介绍 粗糙的翻译下大致意思是: List接口的可调整大小的数组实现.实现了所有可选的列表操作,并允许所有元素,包括 null .除了实现List接 ...
- 算法笔记刷题2(codeup 1928)
又磕了一晚上,多点测试真的很烦 ,完全不知道错哪里,后来发现是我变量名命名不规范导致自己晕了填错了,其实思路还是对的 我觉得书上的做法也还行,但我不太喜欢用二维数组,所以拿以前写的算天数的程序改装了一 ...
- UDO、TCP、HTTP、websocket
如图:
- tp3.2 事务 和 tp5.0事务
tp3.2: 来源:https://www.kancloud.cn/thinkphp-development/tp323/423369 和: https://blog.csdn.net/mengzuc ...
- JavaScript--'data-'的用法(1)
HTML5为我们提供了一个强大的功能,前段也也能实现后台数据库的效果,例如data-xxx <a href="#myModal" data-industry_id=" ...
- 如何给 Visual Studio 的输出程序添加版本信息
出处:https://stackoverflow.com/questions/284258/how-do-i-set-the-version-information-for-an-existing-e ...
- [SketchUp]-绘制自己的家
[SketchUp]-绘制自己的家 softsketchuphome 简介 最近已经完成了 毕业论文, 等待盲审的过程中, 将过去几年做的东西也都一一整理了, 硬盘中好几个不敢动的文件夹 也都可以删除 ...