【Web系列二十四】使用JPA简化持久层接口开发

目录

环境配置

1、引入依赖

配置文件

代码编写

实体类创建

JPA常用注解

Service与ServiceImpl

Service

ServiceImpl

Controller

Dao

三种实现Dao功能方式

1.继承接口,使用默认接口+实现

2.根据接口命名规则默认生成实现

3.自定义接口+实现(类似MyBatis)

多表关联

1.一对一关联

2.一对多、多对一

3.多对多

参考资料


Spring Data JPA

        Spring Data JPA 是Spring提供的一套简化JPA开发的持久层框架,根据实体类自动生成表 (注意库仍旧自己创建),按照约定好的【方法命名规则】写dao层接口,就可以在不写接口实现的情况下,实现对数据库的访问和操作。同时提供了很多除了CRUD之外的功能,如分页、排序、复杂查询等等。

        Spring Data JPA 可以理解为 JPA 规范的再次封装抽象,底层还是使用了 Hibernate 的 JPA 技术实现。

        SpringBoot集成新框架环境往往很容易:引入依赖,编写配置、[启用]、代码编写。

环境配置

1、引入依赖

        首先要引入jpa的依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

配置文件

spring:jpa:hibernate:ddl-auto: updateshow-sql: true
  • ddl-auto:自动创建表,有4个选项
    • create:每次启动将之前的表和数据都删除,然后重新根据实体建立表。
    • create-drop:比上面多了一个功能,就是在应用关闭的时候,会把表删除。
    • update:最常用的,第一次启动根据实体建立表结构,之后重启会根据实体的改变更新表结构,不删除表和数据。
    • validate:验证创建数据库表结构,只会和数据库中的表进行比较,不会创建新表,但是会插入新值,运行程序会校验实体字段与数据库已有的表的字段类型是否相同,不同会报错
  • show-sql:指运行时,是否在控制台展示sql

代码编写

和mybatis主要的区别在于JPA可以根据实体类自动创建表,并且会提供默认的DAO方法。

实体类创建

        创建一个models文件夹,并新建文件algo.java

package com.xxx.xxx.xxx.models;import lombok.Data;
import org.springframework.data.annotation.CreatedDate;import javax.persistence.*;
import java.util.Date;@Entity
@Table(name = "algo")
@Data
public class Algo {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)@Column(name = "id")private Integer id;@Column(name = "name", length = 200)private String name;@CreatedDate     @Column(name = "create_time", updatable = false, nullable = false)private Date createTime;}

JPA常用注解

注解作用
@Entity声明类为实体或表.
@Table声明表名。
@Basic指定非约束明确的各个字段。
@Embedded指定类或它的值是一个可嵌入的类的实例的实体的属性。
@Id指定的类的属性,用于识别(一个表中的主键)。
@GeneratedValue

指定如何标识属性可以被初始化,参数strategy有以下选项:

TABLE:使用一个特定的数据库表格存放主键。
SEQUENCE:根据底层数据库的序列来生成主键,条件是数据库支持序列。(Oracle)
IDENTITY:主键有数据库自动生成(主要是自动增长类型)。(MySQL)
AUTO:主键由程序控制。(默认)

@Transient指定该属性为不持久属性,即:该值永远不会存储在数据库中。
@AccessType这种类型的注释用于设置访问类型。如果设置@AccessType(FIELD),则可以直接访问变量并且不需要getter和setter,但必须为public。如果设置@AccessType(PROPERTY),通过getter和setter方法访问Entity的变量。
@JoinColumn指定一个实体组织或实体的集合。这是用在多对一和一对多关联。
@UniqueConstraint

指定的字段和用于主要或辅助表的唯一约束。

@ColumnResult参考使用select子句的SQL查询中的列名。
@ManyToMany定义了连接表之间的多对多一对多的关系。
@ManyToOne定义了连接表之间的多对一的关系。
@OneToMany定义了连接表之间存在一个一对多的关系。
@OneToOne定义了连接表之间有一个一对一的关系。
@NamedQueries指定命名查询的列表。
@NamedQuery指定使用静态名称的查询。

Service与ServiceImpl

Service

public interface AlgoService {//查询全部List<Algo> findAlgoList();//查询一条User findAlgoById(int id);//添加void insertAlgo(Algo algo);//删除void deleteAlgo(int id);//修改void updateAlgo(Algo algo);
}

ServiceImpl

        查询一条数据时没有直接使用User而是使用Optional< User >,这是由于Dao层直接使用了默认的方法。Optional 类是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。

        修改和添加都是save方法,修改时对象id有值,添加时id无值。

@Service
public class AlgoServiceImpl implements AlgoService {@Autowiredprivate AlgoRepository algoRepository;@Overridepublic List<Algo> findAlgoList() {return algoRepository.findAll();}@Overridepublic AlgofindAlgoById(int id) {//Optional 类是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。Optional<Algo> ao = algoMapper.findById(id);return ao.orElse(null);}@Overridepublic void insertAlgo(Algo algo) {algoRepository.save(algo);}@Overridepublic void deleteAlgo(int id) {algoRepository.deleteById(id);}@Overridepublic void updateAlgo(Algo algo) {Algo emp = algoRepository.findById(algo.getId()).orElse(null);assert emp != null;BeanUtils.copyProperties(algo,emp); //属性值拷贝algoRepository.save(emp);}
}

Controller

@RestController
public class JpaController {@Autowiredprivate AlgoService algoService;@PostMapping("/add")public Map<String,String> addAlgo(){Algo algo = new Algo();algo.setName("张三");algo.setPassword("123456");algo.setSex("男");algoService.insertAlgo(algo);Map<String,String> map = new HashMap<>();map.put("msg","操作成功");return map;}
}

Dao

        继承JpaRepository,它默认的提供了一些常见dao方法,主要是完成一些增删改查的操作。

@Repository
public interface AlgoRepository extends JpaRepository<Algo, Integer> {//约束1为实体类类型、约束2为主键类型
}

三种实现Dao功能方式

1.继承接口,使用默认接口+实现

接口作用
CrudRepository提供默认增删改查方法
PagingAndSortingRepositoryCRUD方法+分页、排序
JpaRepository针对关系型数据库优化

2.根据接口命名规则默认生成实现

        默认提供了常见方法,但仍可以根据命名规则自动生成方法。
        此表内容来源于官网:

Spring Data JPA - Reference Documentation

关键词示例JPQL片段
DistinctfindDistinctByLastnameAndFirstnameselect distinct …​ where x.lastname = ?1 and x.firstname = ?2
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
IsNull, NullfindByAge(Is)Null… 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
EndingWithfindByFirstnameEndingWith… where x.firstname like ?1
ContainingContaining… where x.firstname like ?1
OrderByfindByAgeOrderByLastnameDesc… where x.age = ?1 order by x.lastname desc
NotfindByLastnameNot… where x.lastname <> ?1
InfindByAgeIn(Collection ages)… where x.age in ?1
NotInfindByAgeNotIn(Collection ages)… where x.age not in ?1
TruefindByActiveTrue()… where x.active = true
FalsefindByActiveFalse()… where x.active = false
IgnoreCasefindByFirstnameIgnoreCase… where UPPER(x.firstname) = UPPER(?1)

3.自定义接口+实现(类似MyBatis)

        使用注解方式 @Query

使用 @Query()注解来生成sql语句,注意此注解默认value属性值与myBatis有点不同,它使用的是JPQL。

如果想使value值为原生SQL,则添加属性:nativeQuery = true 即可。

表名映射:可以直接使用表对应类名,如果想用表名:#{#entityName}
参数映射:?n表示第n个参数、:参数名(参数可用@Param指定)

#{#entityName}:SPEL表达式,实体类使用了@Entity后,它的值为实体类名,如果@Entity的name属性有值,则它的值为该name值。
@Modifying:标记仅映射参数的方法。
@Transactional:开启事务,并将只读改为非只读。

@Repository
//约束1为实体类、约束2为主键
public interface AlgoRepository extends JpaRepository<Algo,Integer> {//添加:使用了原生sql@Transactional//开启事务为非只读@Modifying@Query(value = "insert into jpa_test(name, userId) values(:#{#algo.name}, :#{#algo.userId}) ", nativeQuery = true)void addAlgo(@Param("algo") Algo algo);//删除@Transactional(timeout = 10)@Modifying@Query("delete from Algo where id=:id")void deleteAlgoById(@Param("id") Integer id);//修改@Transactional(timeout = 10)@Modifying@Query("update Algo u set u.name=:#{#algo.name}, u.createTime=:#{#algo.createTime}, u.userId=:#{#algo.userId} where u.id=:#{#algo.id}")void updateAlgo (@Param("algo")Algo algo);//查询一条@Query("select u from Algo u where u.id=?1 ")User findAlgoById(Integer id);//查询全部@Query("select u from Algo u")List<Algo> findAllAlgo();
}

        对象属性的绑定:使用 @Param(映射名) 注解 + :#{#映射名.属性}

多表关联

JPA中一般只需要创建关联性即可,默认方法会自动关联查询。

1.一对一关联

        两张表a、b,a的每条对应着b最多一条数据。

在这里插入图片描述

         jpa实现如下:

/*** 表A*/
@Entity
@Table(name = "a")
public class A{@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String name;@OneToOne(cascade = {CascadeType.ALL})//一对一关系,级联删除@JoinColumn(name="b",referencedColumnName = "id")//关联 b的id字段private B b;
}/*** 表B*/
@Entity
@Table(name = "b")
public class B{@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String name;
}

        上面是A级联B,即可以通过A查到B,如果想通过B查到A则需要为B添加级联属性。

2.一对多、多对一

        一对多: 两张表A、B,A的一条记录对应B的多条记录,B每条只能对应1个A。A对B的关系为一对多;B对 A的关系为多对一。

在这里插入图片描述

       jpa实现如下:

/*** 球员表*/
@Entity//球员表
@Table(name = "sportmans")
public class SportMan implements Serializable {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private long id;private String sportManName;@ManyToOne(cascade = {CascadeType.MERGE,CascadeType.PERSIST})@JoinColumn(name="duty")  //库中添加的外键字段private Duty duty;}/*** 位置表*/
@Data
@Entity
@Table(name = "dutys")
public class Duty implements Serializable {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private long id;private String dutyName;@JsonIgnore//不反向查询//级联保存、更新、删除,删除时会删除所有球员@OneToMany(mappedBy = "duty",cascade = CascadeType.ALL,fetch = FetchType.LAZY)private List<SportMan> sportManList;}

        不使用@JsonIgnore注解时,查询球员,球员里关联出位置,位置反向关联球员,会无限递归查询,因此添加此注解,防止此字段被查出来时自动回查。 

3.多对多

        两张表A、B,一条A记录对应多条B,一条B记录对应多条A。

在这里插入图片描述

        jpa实现如下:

/*** 表A*/
@Entity
@Table(name = "a")
public class A{@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String name;@ManyToMany(cascade = {CascadeType.ALL})@JoinColumn(name="b",referencedColumnName = "id")//关联 b的id字段private B b;}/*** 表B*/
@Entity
@Table(name = "b")
public class B{@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String name;@ManyToMany(cascade = {CascadeType.ALL})@JoinColumn(name="a",referencedColumnName = "id")//关联 a的id字段private A a;}

参考资料

SpringBoot 一文搞懂Spring JPA_springboot jpa_马踏飞燕&lin_li的博客-CSDN博客

使用springJpa创建数据库表_jpa可以动态创建数据库表吗_阿圣同学的博客-CSDN博客

 【Spring JPA总结】@GeneratedValue注解介绍 - 简书 (jianshu.com)

spring boot 中使用 jpa(详细操作)_springboot jpa_熬菜的博客-CSDN博客

Spring Boot+JPA_springboot+jpa_火恐龙的博客-CSDN博客

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

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

相关文章

汽车类 ±0.25°C SPI 温度传感器,TMP126EDBVRQ1、TMP126EDCKRQ1、TMP127EDBVRQ1引脚配置图

一、概述 TMP126-Q1 是一款精度为 0.25C 的数字温度传感器 &#xff0c; 支持的环境温度范围为 -55C 至 175C 。TMP126-Q1 具 有 14 位 &#xff08; 有符号 &#xff09; 温度分辨率(0.03125C/LSB)&#xff0c;并且可在 1.62V 至 5.5V 的电源电压范围内工作。TMP126-Q1 具有转…

同创永益入选首批“金融数字韧性与混沌工程实践试点机构”

8月16日下午&#xff0c;由北京国家金融科技认证中心、北京国家金融标准化研究院联合主办的“传递信任 服务发展”金融科技标准认证生态大会在太原成功举办。中国金融电子化集团有限公司党委书记、董事长周逢民&#xff0c;中国科学院院士冯登国&#xff0c;中国工商银行首席技…

Unity 粒子特效遮罩(ParticleMask)

1.需求&#xff1a; 游戏中粒子特效能实现非常好的效果&#xff0c;但是由于粒子特效是独立的系统&#xff0c;Unity自带的Mask普通的遮罩&#xff0c;遮不住粒子特效。 2.实现原理&#xff1a; 通过shader把超出范围的粒子纹理(Texture)&#xff0c;改成透明颜色&#xff0…

Python安装指南(Windows版)

安装python环境 官网下载地址&#xff1a; Download Python | Python.org 我选择3.10.4版本&#xff0c;当然你也可以选择其他版本 安装 安装完成&#xff0c;需要验证是否安装成功。 打开CMD窗口&#xff0c;输入python命令&#xff0c;如果进入如下python窗口则安装成功&…

docker打包vue vite前端项目

打包vue vite 前端项目 1.打包时将测试删除 2.修改配置 3.打包项目 npm run build 显示成功&#xff08;黄的也不知道是啥&#xff09; 打包好的前端文件放入 4.配置 default.conf upstream wms-app {server 你自己的ip加端口 ;server 192.168.xx.xx:8080 ; } server { …

怎样将几个pdf合并?

在日常工作中&#xff0c;我们经常需要处理大量的PDF文件。有时候&#xff0c;我们需要将多个PDF文件合并成一个文件&#xff0c;以便于快速传输或方便查阅。虽然PDF文件本身不能进行编辑&#xff0c;但是借助专业的PDF编辑软件&#xff0c;我们可以轻松地实现将多个PDF文件合并…

推荐两款开源的绘制流程图软件

一句话导读 目前流程图绘制软件非常多&#xff0c;包括本机安装的、web端的都有&#xff0c;如Visio、Graphviz、processOn等等。但是几乎都是收费的。本文给大家介绍两款优秀的开源免费的流程图绘制软件。 目录 一句话导读 一、draw.io 二、Meta2d.js ​1.为什么使用 2.…

4、DVWA——文件包含

文章目录 一、文件包含概述二、low2.1 源码分析2.2 通关分析 三、medium3.1 源码分析3.2 通关思路 四、high4.1 源码分析4.2 通关思路 五、impossible 一、文件包含概述 文件包含是指当服务器开启allow_url_include选项时&#xff0c;就可以通过php的某些特性函数&#xff08;i…

Java“牵手”京东商品详情数据,京东API接口申请指南

京东平台商品详情接口是开放平台提供的一种API接口&#xff0c;通过调用API接口&#xff0c;开发者可以获取京东商品的标题、价格、库存、月销量、总销量、库存、详情描述、图片等详细信息 。 获取商品详情接口API是一种用于获取电商平台上商品详情数据的接口&#xff0c;通过…

JVM调优指令参数

常用命令查找文档站点&#xff1a;https://docs.oracle.com/javase/8/docs/technotes/tools/unix/index.html -XX:PrintFlagsInitial 输出所有参数的名称和默认值&#xff0c;默认不包括Diagnostic和Experimental的参数。可以配合 -XX:UnlockDiagnosticVMOptions和-XX:UnlockEx…

【Locomotor运动模块】抓取:按朝向抓取(Orientation Handler)案例

文章目录 案例原理 案例 左右手柄抓宝剑时&#xff0c;宝剑的朝向不同 L35 一个手柄对应一个抓取点 原理 1、左右手柄分别抓取的是宝剑上的不同抓取点——GenericOrientation Handle通用朝向把手 它是我们设置“按朝向抓取”&#xff08;Orientation Handler&#xff09;时&…

项目一:基于YOLOv7的输电线路销钉缺失检测项目

1. YOLOv7模型介绍 YOLOv7是目标检测算法YOLO&#xff08;You Only Look Once&#xff09;的第七个版本&#xff0c;也是目前较流行的YOLO算法版本之一。 YOLOv8主要结构&#xff1a; 1. Backbone网络&#xff1a;采用CSPDarknet53作为主干网络&#xff0c;在不增加参数数量…

【牛客网题目】合并两个排序的链表

目录 描述 题目分析 描述 输入两个递增的链表&#xff0c;单个链表的长度为n&#xff0c;合并这两个链表并使新链表中的节点仍然是递增排序的。 数据范围&#xff1a;0≤n≤1000&#xff0c;1000≤节点值≤1000 要求&#xff1a;空间复杂度 O(1)&#xff0c;时间复杂…

自然语言处理的多行业应用

在我们小时候&#xff0c;甚至是我们会走路或说话之前&#xff0c;就已经在察觉周围发出的声音了。我们倾听其他人发出的声响和声音。我们将声音组合成有意义的词语&#xff0c;例如“母亲”和“门”&#xff0c;并学习解读周围人的面部表情&#xff0c;以加深我们对词组的理解…

现浇钢筋混泥土楼板施工岗前安全VR实训更安全高效

建筑行业天天与钢筋混凝土砼在&#xff0c;安全施工便成了企业发展的头等大事。 当今社会&#xff0c;人人都奉行生命无价&#xff0c;安全至上。可工地安全事故频繁发生&#xff0c;吞噬掉多少宝贵生命。破坏了多小个家庭?痛定死痛&#xff0c;为了提高施工人员的安全意识。 …

密度图及山脊图绘图基础

文章目录 3 种绘制密度图方法对比多组数据、同一个核函数渐变颜色填充“山脊”图同一坐标系中多个密度图的绘制 Seaborn 的 kdeplot() 函数是 Python 中绘制密度图的方式之一&#xff0c;Matplotlib 在现阶段则没有具体的绘制密度图的函数&#xff0c;一般是结合 Scipy 库中的 …

使用多进程的方式改写聊天程序(有名管道)

目录 1、思路2 、步骤 1、思路 2 、步骤 步骤1&#xff1a;创建两个管道 makefifo fifo1 fifo2步骤2&#xff1a;编写talkA.c文件 #include<stdio.h> #include<stdlib.h> #include<string.h> #include<sys/types.h> #include<sys/stat.h> #in…

智慧排水监测系统,科技助力城市排水治理

城市里&#xff0c;人们每天通过道路通行&#xff0c;人多&#xff0c;路窄&#xff0c;都会拥堵。同样&#xff0c;下雨天&#xff0c;雨水通过雨篦汇集、管道输送&#xff0c;最终排出去&#xff0c;当雨水过大&#xff0c;或者管道过窄&#xff0c;或者管道不通畅&#xff0…

工控上位机程序为什么只能用C语言?

工控上位机程序并不只能用C#开发&#xff0c;实际上在工业自动化领域中&#xff0c;常见的上位机开发语言包括但不限于以下几种&#xff1a;C#: C#是一种常用的编程语言&#xff0c;在工控领域中被广泛使用。它具有良好的面向对象特性和丰富的类库支持&#xff0c;可以实现高性…

C++--动态规划其他问题

1.一和零 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 给你一个二进制字符串数组 strs 和两个整数 m 和 n 。 请你找出并返回 strs 的最大子集的长度&#xff0c;该子集中 最多 有 m 个 0 和 n 个 1 。 如果 x 的所有元素也是 y 的元素&#xff0…