前言

spring data JPA是spring团队打造的sping生态全家桶的一部分,本身内核使用的是hibernate核心源码,用来作为了解java持久层框架基本构成的样本是再好不过的选择。最近闲来无事,构建了一个demo工程,用来阅读spring data JPA源码,这对于宏观了解持久层框架的基本工作、微观分析spring data JPA的原理和优缺点、避免使用过程中采坑,将会有一定的帮助。

基本工程搭建

spring data JPA的使用需要依托于web框架,最简单快速的方式就是使用https://start.spring.io/构建一个包含spring data JPA的spring boot项目,只需要在引导的对应SQL的菜单中选中Spring Data Jpa和响应数据库的Driver即可,目前无论是idae还是eclipse都支持采用这种方式。上述方法的实质还是在最终生成的spring boot项目的pom.xml中加入了相关的依赖,所以也可以直接生成由maven管理的spring boot项目,然后pom.xml中:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.8.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.example</groupId><artifactId>jpademo</artifactId><version>0.0.1-SNAPSHOT</version><name>jpademo</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>com.querydsl</groupId><artifactId>querydsl-jpa</artifactId></dependency><dependency><groupId>com.querydsl</groupId><artifactId>querydsl-apt</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin><plugin><groupId>com.mysema.maven</groupId><artifactId>apt-maven-plugin</artifactId><version>1.1.3</version><executions><execution><goals><goal>process</goal></goals><configuration><outputDirectory>target/generated-sources/apt</outputDirectory><processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor></configuration></execution></executions></plugin></plugins></build></project>

其中,spring-boot-starter-web是spring boot框架依赖,spring-boot-starter-data-jpa是Spring Data Jpa依赖,我使用的Mysql数据库,所以引入了mysql-connector-java。 querydsl-jpa和querydsl-apt是在JPA基础上使用querydsl的依赖,可以不引入。最后lombok广泛使用的懒癌工具包。 接下来当然是构建一个数据源,本地需要安装mysql,这部分我就不细说了。数据库安装完成后,创建一个test库,建song表,建表语句:

CREATE TABLE `song` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` char(10) DEFAULT NULL,`year` int(11) DEFAULT NULL,`length` int(11) DEFAULT NULL,`type` varchar(64) DEFAULT NULL,PRIMARY KEY (`id`)
)
接着项目中application.properties中设置数据库配置:
#driver配置
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#数据库配置
spring.datasource.url=jdbc:mysql://localhost:3306/test?useSSL=false&allowPublicKeyRetrieval=true
spring.datasource.username=root
spring.datasource.password=123456
#jpa配置
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update

spring.jpa.hibernate.ddl-auto是最有意思的一个配置,一不小心可能造成删库的悲惨结果。

  • create:每次运行该程序,没有表格会新建表格,表内有数据会清空。
  • create-drop:每次程序结束的时候会清空表。
  • update:每次运行程序,没有表格会新建表格,表内有数据不会清空,只会更新
  • validate:运行程序会校验数据与数据库的字段类型是否相同,不同会报错

这里的是否有表格是以应用中配置的Entity实体为依据的,这意味着应用能够根据自身的Entity实体来影响表的创建和表的结构。千言万语汇成一句话,千万不要配置为create。 最后需要在应用中配置相应的实体Entity和实体的Repository。项目目录整体文件结构如下:

其中:

  • JpademoApplication.java:spring boot应用入口
  • TestController.java: 测试用controller接口
  • Song.java: 对应song表的实体类Entity
  • SongRepository: 对应实体类Song的Repository接口

Song实体定义:

@Entity  //定义为实体类
@Table(name = "song")  //映射表配置
@DynamicInsert         //支持动态插入
@DynamicUpdate         //支持动态更新
//以下为lombok懒癌注解
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Song {@Id              //主键id@GeneratedValue  //主键自动生成private Long id;private String name;private Integer year;private Integer length;private String type;
}

Jpa实体Entity对应了持久层的表数据,Song实体的定义,就对应了本地mysql数据test库中的song表。而对表数据的增删改查操作,可以通过Repository实现。

public interface SongRepository extends JpaRepository<Song,Integer>{Song findById(Long id);Song getById(Long id);Song queryByIdAndYear(Long id, Long year);void deleteById(Long id);
}

SongRepository继承JpaRepository接口,默认实现了诸如save(S entity)、findAll()、count()、delete(T entity)之类的方法,同时也支持子类通过名字拓展自定义新的查询或其他操作数据的方式,比如我在上面定义的find、get、query By id或者 IdAndYear,就是通过id或者year组合查询。虽然这种通过名字来拓展新的操作数据接口的方法看起来比较蠢,但是具体到实现原理还是值得探讨一番的。

基本使用

了解一个事物基本原理,首先需要全面的了解事物的外在功能。对于spirng data jpa,主要的数据操作方式有使用Repository和使用EntityManager这两种形式。
@Slf4j
@RestController
public class TestController {@Resourceprivate EntityManager entityManager;@Resourceprivate SongRepository songRepository;@GetMapping("/")public List<Song> test() {return repositoryList();}public List<Song> repositoryList() {//Repository方式List<Song> songs = songRepository.findAll();return songs;}@Transactionalpublic void repositorySave() {Song song = new Song();song.setName("MyHeart");song.setLength(230);song.setYear(2020);songRepository.save(song);}@Transactionalpublic void entityManagerMerge() {//EntityManager方式Song song = new Song();song = new Song();song.setName("Journey");song.setLength(230);song.setYear(2020);entityManager.merge(song);}public List<Song> hqlList() {//hql方式Query query = entityManager.createQuery("select s as ss from Song s");List<Song> songs = query.getResultList();return  songs;}public List<Song> sqlList() {//sql方式Query nativeQuery = entityManager.createNativeQuery("select * from song s where name LIKE 'MyHeart'");List<Song> songs = nativeQuery.getResultList();return songs;}
}

Repository提供标准Crud接口,也支持按照规范的命名标准自定义接口,这些在上文已经介绍过了。EntityManager方式其实是Repository的底层实现,这种方式提供了创建CriteriaQuery(上例没有展示)、hql 的Query、SQL的Query,通过Query完成最终和数据库的交互。从上例可以看出hql形式和sql比较类似,只是hql在“select s as ss from Song s”语句中,使用了面向对象的封装,这里Song对应的是实体Song,而不表名。原生NativeQuery对应的就是原生Sql查询。 除此之外,Repository也提供非规范命名的接口查询,本质也是使用EntityManager的hql和sql方式。在Repository的接口方法上可以使用@Query注解,并定义相应的hql或者sql的语句,查询条件需要和接口方法的入参一致,查询结果对应接口方法的返回参数。 实际上,spring data jpa提供了一个sql演化的基本思路,即从sql到hql再到结合实体使用的Repository。但是实体很难解决关系型数据库表数据的join问题,在《java数据库持久层框架基础:为什么不是JPA?》这篇文章中,我提到了可以使用querydsl解决联表问题,实际上spring data jpa也有自己的方案,即在单个实体中定义映射集合。简单解释来说,假设一个表对应实体类Person,Person包含一个集合属性Head,Head对应的是另一个表中的数据。Person实体中使用

@JoinTable(name = "head", joinColumns = { @JoinColumn(nullable = false, name = "item_id", referencedColumnName = "id") })

实现联表。但这种方式存在复杂的级联关系,在更新、插入和删除操作中极其难以处理。

作者:孙新【滴滴出行软件开发工程师】


  • 现在注册滴滴云,得10000元立减红包
  • 8月特惠,1C2G1M云服务器 9.9元/月限时抢
  • 滴滴云使者专属特惠,云服务器低至68元/年
  • 输入大师码【7886】,GPU全线产品9折优惠

滴滴云-为开发者而生​www.didiyun.com

滴滴云使者​www.didiyun.com

spring data jpa从入门到精通_Spring Data JPA的简单入门相关推荐

  1. 黑客零基础入门教程:「黑客攻防实战从入门到精通(第二版)」堪称黑客入门天花板

    前言 您知道在每天上网时,有多少黑客正在浏览您计算机中的重要数据吗﹖黑客工具的肆意传播,使得即使是稍有点计算机基础的人,就可以使用简单的工具对网络中一些疏于防范的主机进行攻击,在入侵成功之后,对其中的 ...

  2. jpa 动态查询条件 数组_Spring data jpa 复杂动态查询方式总结

    一.Spring data jpa 简介 首先JPA是Java持久层API,由Sun公司开发, 希望整合ORM技术,实现天下归一.  诞生的缘由是为了整合第三方ORM框架,建立一种标准的方式,目前也是 ...

  3. 《HFSS电磁仿真设计从入门到精通》一第2章 入门实例——T形波导的内场分析和优化设计...

    本节书摘来自异步社区<HFSS电磁仿真设计从入门到精通>一书中的第2章,作者 易迪拓培训 , 李明洋 , 刘敏,更多章节内容可以访问云栖社区"异步社区"公众号查看 第2 ...

  4. python从入门到精通视频教程百度云-python从入门到精通视频教程百度云资源

    python从入门到精通视频教程百度云资源来源 : 华清远见 2019-05-24 随着新技术的不断推进,在未来无论我们是要进入网页开发.数据分析.机器学习.人工智能还是无人车云计算等领域,Pytho ...

  5. python入门到精通需要学多久-Python从入门到精通只需要一个月就够了!

    对于许多未曾涉足计算机编程的领域「小白」来说,深入地掌握 Python 看似是一件十分困难的事.其实,只要掌握了科学的学习方法并制定了合理的学习计划,Python 从 入门到精通只需要一个月就够了! ...

  6. 电脑教程从入门到精通_HALCON机器视觉软件零基础入门学习到精通实用教学视频教程...

    HALCON零基础入门到精通实用教学视频教程 在科技技术和电子信息技术发展的当代,最火的肯定就是人工智能和机器人设计了,机器视觉应用自然也是火爆的不行.HALCON是德国公司开发的机器视觉软件,是公认 ...

  7. c++从入门到精通_资料下载:从入门到精通,手把手教你学DSP

    学习一个东西首先是了解它,比如DSP到底是什么?用在什么地方?怎么用?和单片机特点有那些相同与不同?开发需要注意什么?想了解清楚这些问题自然就清楚比较清楚的认识DSP.DSP,因为它是用来做数据处理, ...

  8. android手机游戏开发从入门到精通_unity3d游戏开发如何从入门到精通?

    对于游戏爱好者来说,unity3d想必大家都不陌生,unity3d和虚幻4算是现在最主流的游戏开发引擎,当然,Unity 3D 游戏开发引擎目前之所以炙手可热,与其完善的技术以及丰富的个性化功能密不可 ...

  9. python从入门到精通 明日科技 电子书-Python从入门到精通(明日科技出版) 源代码+课件+视频 全套...

    明日科技 - Python从入门到精通 ├──视频讲解 │ ├──01 │ │ ├──1.1 Python简介.mp4 │ │ ├──1.2.1 开发环境概述.mp4 │ │ ├──1.2.2 安装P ...

最新文章

  1. 赠书福利 | Tidio AI 趋势报告:约42%受访者能够接受机器人伴侣
  2. 二十三、死锁的处理策略---避免死锁(银行家算法)
  3. flowvisor 命令_mininet+FlowVisor+OpenDayLight环境搭建及实验一
  4. has_a php,PHP has encountered a Stack overflow问题解决方法
  5. 哈工大|NLP数据增强方法?我有15种
  6. ES6_字符串模板以及其使用
  7. Photon服务器引擎入门
  8. linux7.1怎么安装vnc,51CTO博客-专业IT技术博客创作平台-技术成就梦想
  9. VS Code离线安装C/C++插件cpptools-linux-aarch64.vsix
  10. 《SpringBoot实战》笔记1
  11. Filter(过滤器)Listene(监听器)笔记
  12. UE4 创建地形失败:Unreal Engine 4 Crash Reporter
  13. 中国移动光猫外接一个路由器的方法
  14. mysql星期几转为英文_MySQL如何获取一个指定日期所对应的的星期几(英文星期信息-dayname函数)呢?...
  15. 耗时8个小时用纯HTML和CSS写成的学成在线
  16. 谈谈如何判断一个Pop序列是否是一个Push序列的Pop顺序
  17. 关于windows微软账号登陆不进去的问题
  18. 搜索的实例——水管工游戏
  19. Android使用SimpleDateFormat不同手机有时格式化手机不准确
  20. springboot+vue练手级项目,真实的在线博客系统

热门文章

  1. eclipse的菜单栏消失问题解决
  2. “System.Transactions.Diagnostics.DiagnosticTrace”的类型初始值设定项引发异常。
  3. nvm 装 nodejs 重启终端失效的解决方法
  4. matplotlib安装错误依赖问题解决
  5. win10安装JDK cmd中可以运行java,但不能用javac,解决方案
  6. 导出Excel出现“异常来自 HRESULT:0x800A03EC”错误的解决方法(已验证)
  7. IO异常 java.net.SocketException: Connection reset
  8. Amqp整合com.rabbitmq.client.ShutdownSignalException: channel error; protocol method异常处理
  9. Windows Android SDK下载安装,配置,异常问题解决教程
  10. 如何在div中将绝对定位的元素居中?