JPA实战

news2024/11/29 12:40:19

常见 ORM 框架

**Mybatis(ibatis):**一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Ordinary Java Object,普通的 Java 对象)映射成数据库中的记录。
  Hibernate:一个开放源代码的对象关系映射框架,它对 JDBC 进行了非常轻量级的对象封装,它将 POJO 与数据库表建立映射关系,是一个全自动的 ORM 框架,hibernate 可以自动生成 SQL 语句,自动执行,使得 Java 程序员可以随心所欲的使用对象编程思维来操纵数据库。
  Jpa:Java Persistence API 的简称,中文名 Java 持久层 API,是 JDK 5.0 注解或 XML 描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。

一、Spring data JPA简介

Spring data JPA是Spring在ORM框架,以及JPA规范的基础上,封装的一套JPA应用框架,并提供了一整套的数据访问层解决方案。

二、Spring data JPA的功能

Spring data JPA的功能非常的强大,这里我们先跳过环境搭建这一步,来一睹Spring data JPA的“芳容”。

Spring data JPA提供给用户使用的,主要有以下几个接口:

  1. Repository:仅仅是一个标识,表明任何继承它的均为仓库接口类,方便Spring自动扫描识别
  2. CrudRepository:继承Repository,实现了一组CRUD相关的方法
  3. PagingAndSortingRepository:继承CrudRepository,实现了一组分页排序相关的方法
  4. JpaRepository:继承PagingAndSortingRepository,实现一组JPA规范相关的方法
  5. JpaSpecificationExecutor:比较特殊,不属于Repository体系,实现一组JPA Criteria查询相关的方法。

三、Spring Data JPA对事务的支持

默认情况下,Spring Data JPA 实现的方法都是使用事务的。针对查询类型的方法,其等价于 @Transactional(readOnly=true);增删改类型的方法,等价于 @Transactional。可以看出,除了将查询的方法设为只读事务外,其他事务属性均采用默认值。

如果用户觉得有必要,可以在接口方法上使用 @Transactional 显式指定事务属性,该值覆盖 Spring Data JPA 提供的默认值。同时,开发者也可以在业务层方法上使用 @Transactional 指定事务属性,这主要针对一个业务层方法多次调用持久层方法的情况。持久层的事务会根据设置的事务传播行为来决定是挂起业务层事务还是加入业务层的事务。

四、JPA自定义SQL

顾名思义,就是根据方法的名字,就能创建查询

只要继承了JpaRepository<Object,Integer>接口就可以实现自定义SQL,对于简单的查询使用这种查询是最好不过的了

KeywordSampleJPQL snippet
AndfindByLastnameAndFirstname… where x.lastname = ?1 and x.firstname = ?2
OrfindByLastnameOrFirstname… where x.lastname = ?1 or x.firstname = ?2
Is,EqualsfindByFirstname,findByFirstnameIs,findByFirstnameEquals… where x.firstname = ?1
BetweenfindByStartDateBetween… where x.startDate between ?1 and ?2
LessThanfindByAgeLessThan… where x.age < ?1
LessThanEqualfindByAgeLessThanEqual… where x.age ⇐ ?1
GreaterThanfindByAgeGreaterThan… where x.age > ?1
GreaterThanEqualfindByAgeGreaterThanEqual… where x.age >= ?1
AfterfindByStartDateAfter… where x.startDate > ?1
BeforefindByStartDateBefore… where x.startDate < ?1
IsNullfindByAgeIsNull… where x.age is null
IsNotNull,NotNullfindByAge(Is)NotNull… where x.age not null
LikefindByFirstnameLike… where x.firstname like ?1
NotLikefindByFirstnameNotLike… where x.firstname not like ?1
StartingWithfindByFirstnameStartingWith… where x.firstname like ?1(parameter bound with appended %)
EndingWithfindByFirstnameEndingWith… where x.firstname like ?1(parameter bound with prepended %)
ContainingfindByFirstnameContaining… where x.firstname like ?1(parameter bound wrapped in%)
OrderByfindByAgeOrderByLastnameDesc… where x.age = ?1 order by x.lastname desc
NotfindByLastnameNot… where x.lastname <> ?1
InfindByAgeIn(Collection<Age> ages)… where x.age in ?1
NotInfindByAgeNotIn(Collection<Age> age)… where x.age not in ?1
TruefindByActiveTrue()… where x.active = true
FalsefindByActiveFalse()… where x.active = false
IgnoreCasefindByFirstnameIgnoreCase… where UPPER(x.firstame) = UPPER(?1)

五、JPA拥有哪些注解呢?

注意:JPA是可以根据实体类属性自动生成表的,只要加入下面几个注解

@Entity
@Table(name = “”)
@Column(name = “”)

注解解释
@Entity声明类为实体或表。
@Table声明表名。
@Id指定的类的属性,用于识别(一个表中的主键)。
@GeneratedValue指定如何标识属性可以被初始化,例如自动、手动、或从序列表中获得的值。
@Column指定持久属性栏属性。
@Transient指定的属性,它是不持久的,即:该值永远不会存储在数据库中。
@Basic指定非约束明确的各个字段。
@Embedded指定类或它的值是一个可嵌入的类的实例的实体的属性。
@SequenceGenerator指定在@GeneratedValue注解中指定的属性的值。它创建了一个序列。
@TableGenerator指定在@GeneratedValue批注指定属性的值发生器。它创造了的值生成的表。
@AccessType这种类型的注释用于设置访问类型。如果设置@AccessType(FIELD),则可以直接访问变量并且不需要getter和setter,但必须为public。如果设置@AccessType(PROPERTY),通过getter和setter方法访问Entity的变量。
@JoinColumn指定一个实体组织或实体的集合。这是用在多对一和一对多关联。
@UniqueConstraint指定的字段和用于主要或辅助表的唯一约束。
@ColumnResult参考使用select子句的SQL查询中的列名。
@ManyToMany定义了连接表之间的多对多一对多的关系。
@ManyToOne定义了连接表之间的多对一的关系。
@OneToMany定义了连接表之间存在一个一对多的关系。
@OneToOne定义了连接表之间有一个一对一的关系。
@NamedQueries指定命名查询的列表。
@NamedQuery指定使用静态名称的查询。

了解了注解之后我们来看看如何使用吧

六、SQL能力

1. JPA有两种SQL查询方式

因为接口继承了JpaRepository<Object,Integer>接口,所以接口可以实现里面的所有方法

JPA的查询语言是面向对象而非面向数据库的,他以面向对象的自然语法构造查询语句,可以看成是Hibernate HQL的等价物。JPA定义了独特的JPQL(Java Persistence Query Language),JPQL是EJB QL的一种扩展,它是针对实体的一种查询语言,操作对象是实体,而不是关系数据库的表,而且能够支持批量更新和修改、JOIN、GROUP BY、Having 等通常只有SQL才能够提供的高级查询特性,甚至还能够支持子查询。

原生SQL

原生SQL,顾名思义就是数据库原原本本的SQL语句,可以把SQL语句复制出来到数据库直接运行

/**
  * 获取用户信息
  * nativeQuery = true:使用sql查询
  * nativeQuery = false:使用jpql查询,默认就是false
  */
@Query(value = "select * from users where username=?", nativeQuery = true)
Users findByUsername(String username);

JPQL查询

JPQL查询使用的是实体类属性

@Query(value = "select u.id,u.name from users u where u.username=?")
Users findByUsername(String username);
注意:使用如下SQL需要定义实体类构造函数,并且参数顺序一致
@Query("select new com.example.demo.entity.TestDemo(t.id,t.username,t.testTime) from  TestDemo t")
List<TestDemo> testAll();

2. 传参方式

下表索引传参
@Query ( "select u from users u where id>?1 and username like %?2%" )
List <User > selectUserByParam ( Long id , String name );

@param 命名参数传参
@Query ( "select u from users u where id>:id and username like :name" )
List <User > selectUserByParam ( @param('id') Long id ,  @param('name') String name );

3. 动态SQL

是不是跟Mybatis的动态SQL有点相识,只不过这里是判断是否为空,为空了就不会往下走了,不为空就执行SQL将参数传进去进行查询

@Query("select t from  TestDemo t where ((?1 is null or ?1 = '') or (?2 is null or ?2 = '') or (t.testTime between ?1 and ?2)) ")
Page<TestDemo> testAll1(String startTime, String endTime, Pageable pageable);

4. 两表联合分页查询

注意JPA原生SQL和Pageable配合会报错

JPA原生SQL和Pageable配合报错解决:https://blog.csdn.net/ITKidKid/article/details/130167244

这里只是做个示例,随便写的,具体根据实际情况开发

数据访问层 testRepository 接口

@Query("select new com.example.demo.vo.UserAddressVo(u.id,a.province,a.city,a.area) from  User u inner join Address a on u.id = a.userId")
Page<UserAddressVo> pageAll(Pageable pageable);

业务逻辑层 testServiceImpl 接口实现类

testRepository.pageAll(PageRequest.of(page - 1, limit, Sort.Direction.DESC, "createDate"));

七、项目实战

1. 导入依赖

<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>
<!--mysql-->
<dependency>
	<groupId>mysql</groupId>
	<artifactId>mysql-connector-java</artifactId>
	<version>8.0.28</version>
</dependency>
<dependency>
	<groupId>org.projectlombok</groupId>
	<artifactId>lombok</artifactId>
	<version>1.18.26</version>
	<scope>compile</scope>
</dependency>

2. 生成代码

JPA代码生成:https://www.cnblogs.com/cl-rr/p/10397107.html

可以使用eazycode代码生成器生成代码,也可以使用我上面的这个链接,不过有些地方需要补全

3. 代码编写

控制层
/**
 * (TestDemo)表控制层
 *
 * @author makejava
 * @since 2023-04-26 14:32:35
 */
@RestController
@RequestMapping("/testDemo")
public class TestDemoController {
	@GetMapping("/testAll")
	public RespBean testAll(@RequestParam(required = false) String startTime,
                                                    @RequestParam(required = false) String endTime) {
		return RespBean.success("成功",testDemoService.testAll(startTime,endTime));
	}
}

业务逻辑层
接口方法
public interface TestDemoService  {
	List<TestDemo> testAll(String startTime, String endTime);
}
接口方法实现   
@Service
public class TestDemoServiceImpl implements TestDemoService {    
    @Autowired
    private TestDemoRepository rep;
    @Override
    public List<TestDemo> testAll(String startTime, String endTime) {
        return rep.testAll(startTime,endTime);
    }
}

业务访问层
@Repository
public interface TestDemoRepository extends JpaRepository<TestDemo, Integer> {
    @Query("select new com.example.demo.entity.TestDemo(t.id,t.username,t.testTime) from  TestDemo t where ((?1 is null or ?1 = '') or (?2 is null or ?2 = '') or (t.testTime between ?1 and ?2)) ")
    List<TestDemo> testAll(String startTime, String endTime);
}

看下结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IV2dz79j-1682650502112)(E:\PRD\Images\image-20230428102649500.png)]

Java全局日期类型转换配置:https://blog.csdn.net/ITKidKid/article/details/130421992

感谢:https://blog.csdn.net/wujiaqi0921/article/details/78789087

https://www.cnblogs.com/cl-rr/p/10397107.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/474006.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【深圳】IBM V3500存储维修 更换控制器故障

冠峰科技-爱科技爱分享 今天给大家分享的是深圳.福田区一个电商客户公司一台IBM Storwize v3500存储控制器故障从远程诊断 收集日志 分析结果的实际案例&#xff0c;如图所示通过存储管理口登陆进去后直接看到少了一个控制器&#xff0c; 按照惯例&#xff0c;还是得登陆到服…

linux智能网关4G离散数据采集分析HDMI广告牌

数字城市的4G边缘计算网关是一种具有强大处理能力、智能控制和现场数据采集能力的计算设备。其主要特点包括以下方面&#xff1a; 系统平台&#xff1a;基于Linux或Debian系统&#xff0c;可灵活开发各种应用程序。IO接口&#xff1a;2DI、2DO数字输入输出接口&#xff0c;可以…

JAVASE的全面总结

&#xff08;未完待续&#xff09; 五、子类与继承 5.1 子类与父类 继承是一种由已有的类创建新类的机制。利用继承&#xff0c;我们可以先创建一个共有属性的一般类&#xff0c;根据该一般类再创建具有特殊属性的新类&#xff0c;新类继承一般类的状态和行为&#xff0c;并…

golang - switch

switch 的使用 switch 语句用于基于不同条件执行不同操作&#xff0c;&#xff0c;直每一个 case 分支都是唯一的&#xff0c;从上到下逐一测试到匹配为止匹配项后面也不需要再加 break switch 表达式 {case 表达式1, 表达式2, ... :语句块1case 表达式2, 表达式3, ... :语句块…

Linux LD链接器 -静、动库编译or链接

文章目录 程序链接动态链接静态链接 目标文件链接打包为动态打包为静态总结 动态链接- 动态链接&#xff1a;在运行、加载时&#xff0c;在内存中完成链接的过程- 动态共享库&#xff1a;用于动态链接的系统库、特性是可以加载无需重定位的代码 got表(Global Offset Table)延时…

SpringBoot核心配置全面总结

目录 1、application. properties核心文件 2、 application.yml配置文件&#xff08;推荐配置风格&#xff09; 3、SpringBoot多环境配置 4、SpringBoot自定义配置 1&#xff09;Value注解 2&#xff09; ConfigurationProperties 5. 远程配置中心&#xff08;目前生产…

http协议(一)/应用层

学习目标&#xff1a;⭐理解应用层的作用&#xff0c;理解协议&#xff0c;理解序列化和反序列化&#xff0c;并且实现网络版计算器⭐HTTP协议。⭐手写一个简单的http协议。 应用层 我们写的一个个解决实际问题, 满足我们日常需求的网络程序, 都是在应用层。 协议/序列化与反…

第三节:支持向量机分类预测

0、介绍 监督学习&#xff08;英语&#xff1a;Supervised learning&#xff09;是机器学习中最为常见、应用最为广泛的分支之一。本次实验将带你了解监督学习中运用十分广泛的支持向量机&#xff0c;并学会使用 scikit-learn 来构建预测模型&#xff0c;用于解决实际问题。 知…

都什么年代了,还在用Excel和ACCESS做应用系统?快来学Eversheet

表格用的越久&#xff0c;就越头疼 稍微有规模的企业&#xff0c;各种表格都会多如牛毛&#xff0c;一堆堆的&#xff0c;有时候这里一张&#xff0c;那里一张&#xff0c;容易整乱&#xff0c;更容易丢失。不管你是用WPS还是用Excel&#xff0c;有些问题你还是依旧解决不了。…

【VM服务管家】VM4.x算法模块开发_4.1 开发配置类

目录 4.1.1 算法开发&#xff1a;算法模块的开发流程4.1.2 参数操作&#xff1a;获取与设置模块参数的方法4.1.3 文件交互&#xff1a;文件交互操作的配置方法4.1.4 输出显示&#xff1a;设置输出并显示在VM界面的方法4.1.5 模板配置&#xff1a;模板配置界面的实现方法4.1.6 命…

中文译英文 模型

Helsinki-NLP/opus-mt-zh-en Hugging FaceWe’re on a journey to advance and democratize artificial intelligence through open source and open science.https://huggingface.co/Helsinki-NLP/opus-mt-zh-en?text%E6%88%91%E5%8F%AB%E6%B2%83%E5%B0%94%E5%A4%AB%E5%86%8…

【Java入门合集】第一章Java概述

【Java入门合集】第一章Java概述 博主&#xff1a;命运之光 专栏&#xff1a;JAVA入门 学习目标 1.理解JVM、JRE、JDK的概念&#xff1b; 2.掌握Java开发环境的搭建,环境变量的配置&#xff1b; 3.掌握Java程序的编写、编译和运行&#xff1b; 4.学会编写第一个Java程序&#x…

Python 科研绘图可视化(后处理)Matplotlib - RGBAxes

Introduction 科研可视化是将数据和信息转化为可视化形式的过程&#xff0c;旨在通过图形化展示数据和信息&#xff0c;使得科研工作者能够更好地理解和分析数据&#xff0c;并从中发现新的知识和洞见。科研可视化可以应用于各种领域&#xff0c;如生物学、物理学、计算机科学…

一文带你入门C++类和对象【十万字详解,一篇足够了】

本文字数较多&#xff0c;建议电脑端访问。不多废话&#xff0c;正文开始 文章目录 ———————————————【类和对象 筑基篇】 ———————————————一、前言二、面向过程与面向对象三、结构体与类1、C中结构体的变化2、C中结构体的具体使用3、结构体 --&…

3.6 Linux shell脚本编程(概念、变量、语句)

目录 shell脚本概述 shell脚本编写步骤 第一个shell脚本文件 shell脚本变量 变量的介绍 变量的作用 变量的命名要求 变量的分类 用户自定义变量 取值 用户自定义变量-数组 只读变量 位置变量与预定义变量 环境变量 shell语句 shell程序 说明性语句&#xff08…

MATLAB连续时间信号的实现和时域基本运算(八)

1、实验目的&#xff1a; 1&#xff09;熟悉常用连续时间信号的实现方法&#xff1b; 2&#xff09;掌握连续时间信号的时域基本运算&#xff1b; 3&#xff09;掌握实现基本函数及其运算的函数的使用方法&#xff1b; 4&#xff09;加深对信号基本运算的理解。 2、实验内容&am…

【VM服务管家】VM4.0平台SDK_2.4 结果获取类

目录 2.4.1 数据结果&#xff1a;通过流程输出或模块输出获取数据结果的方法2.4.2 流程运行&#xff1a;所有流程运行结束的回调方法2.4.3 模块回调&#xff1a;所有模块运行结束的回调方法2.4.4 加密狗回调&#xff1a;获取加密狗状态的回调方法2.4.5 方案加载&#xff1a;方案…

STM32物联网实战开发(4)——基本定时器

我使用的是正点原子的阿波罗F429开发板&#xff0c;他有14个定时器&#xff0c;本次实验使用STM32F429的基本定时器6作定时&#xff0c;在中断中每隔1秒翻转LED电平状态。 1.CubeMX初始化定时器 先开启定时器6 再对定时器6的参数进行配置&#xff0c;将定时器6定时时间配置为…

记一次SSRF漏洞的学习和利用

导语&#xff1a;本文主要记录一次我们在复盘嘶吼网站渗透报告时遇到的一个SSRF漏洞。 1.前言 本文主要记录一次我们在复盘嘶吼网站渗透报告时遇到的一个SSRF漏洞。此漏洞并结合腾讯云的API接口&#xff0c;可以获取大量嘶吼服务器的敏感信息。利用这些敏感信息&#xff0c;又…

阿里测试8年,肝到P8只剩他了····

在阿里工作了8年&#xff0c;工作压力大&#xff0c;节奏快&#xff0c;但是从技术上确实得到了成长&#xff0c;尤其是当你维护与大促相关的系统的时候&#xff0c;熬到P7也费了不少心思&#xff0c;小编也是个爱学习的人&#xff0c;把这几年的工作经验整理成了一份完整的笔记…