SpringDataJPA系列(6)Entiry注解使用

2024-09-06 06:52

本文主要是介绍SpringDataJPA系列(6)Entiry注解使用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

SpringDataJPA系列(6)Entiry注解使用

JPA协议规定

  • 实体是直接进行数据库持久化操作的领域对象,必须通过 @Entity 注解进行标示
  • 实体必须有一个 public 或者 protected 的无参数构造方法
  • 实体里面必须要有一个主键,主键标示的字段可以是单个字段,也可以是复合主键字段
  • 持久化映射的注解可以标示在 Entity 的字段 field 上,也可以将持久化注解运用在 Entity 里面的 get/set 方法上
//字段上
@Column(length = 20, nullable = false)
private String userName;
//get/set上
@Column(length = 20, nullable = false)
public String getUserName(){return userName;
}

详细的协议地址:https://download.oracle.com/otn-pub/jcp/persistence-2_2-mrel-spec/JavaPersistence.pdf

Entiry注解

有哪些Entity注解,可以打开@Entity注解所在的包一窥究竟:
在这里插入图片描述
差不多有100多个注解…
这里只提及一些最常见的,包括 @Entity、@Table、@Access、@Id、@GeneratedValue、@Enumerated、@Basic、@Column、@Transient、@Lob、@Temporal 等。

  • @Entity:定义对象将会成为被 JPA 管理的实体,必填,将字段映射到指定的数据库表中,使用起来很简单,直接用在实体类上面即可
  • @Table:指定数据库的表名,表示此实体对应的数据库里面的表名,非必填,默认表名和 entity 名字一样
  • @Access:指定 entity 里面的注解是写在字段上面,还是 get/set 方法上面生效,非必填。当实体里面的第一个注解出现在字段上或者 get/set 方法上面,就以第一次出现的方式为准
  • @Id:定义属性为数据库的主键,一个实体里面必须有一个主键,但不一定是这个注解,可以和 @GeneratedValue 配合使用或成对出现
  • @GeneratedValue:主键生成策略,共有四个值
    在这里插入图片描述
  • @Enumerated:这个注解很好用,因为它对 enum 提供了下标和 name 两种方式,用法直接映射在 enum 枚举类型的字段上
//有一个枚举类,用户的性别
public enum Gender {MAIL("男性"), FMAIL("女性");private String value;private Gender(String value) {this.value = value;}
}
//实体类@Enumerated的写法如下
@Entity
@Table(name = "tb_user")
public class User implements Serializable {@Enumerated(EnumType.STRING)@Column(name = "user_gender")private Gender gender;.......................
}

这时候插入两条数据,数据库里面的值会变成 MAIL/FMAIL,而不是“男性” / 女性。

  • @Basic:表示属性是到数据库表的字段的映射。如果实体的字段上没有任何注解,默认即为 @Basic。也就是说默认所有的字段肯定是和数据库进行映射的,并且默认为 Eager 类型
  • @Transient:该属性并非一个到数据库表的字段的映射,表示非持久化属性
  • @Column:定义该属性对应数据库中的列名
  • @Temporal:设置 Date 类型的属性映射到对应精度的字段(日期、时间、日期时间)

注解生成技巧

在这里插入图片描述

生成的结果示例如下:

在这里插入图片描述

联合主键

@IdClass 做联合主键

可以通过 javax.persistence.EmbeddedId 和 javax.persistence.IdClass 两个注解实现联合主键的效果。
第一步:新建一个 UserInfoID 类里面是联合主键。

public class UserInfoID implements Serializable {private String name,telephone;
}

第二步:再新建一个 UserInfo 的实体,采用 @IdClass 引用联合主键类。

@IdClass(UserInfoID.class)
public class UserInfo {private Integer ages;@Idprivate String name;@Idprivate String telephone;
}

使用示例:

 userInfoRepository.save(UserInfo.builder().ages(1).name("jack").telephone("123456789").build());
Optional<UserInfo> userInfo = userInfoRepository.findById(UserInfoID.builder().name("jack").telephone("123456789").build());

资源库仍然按照标准DQM方式进行名称查询,实际上表的主键是 primary key (name, telephone),而 Entity 里面不再是一个 @Id 字段了。

@Embeddable 和@EmbedId

第一步:在我们上面例子中的 UserInfoID 里面添加 @Embeddable 注解。

@Embeddable
public class UserInfoID implements Serializable {private String name,telephone;
}

第二步:改一下我们刚才的 User 对象,删除 @IdClass,添加 @EmbeddedId 注解:

public class UserInfo {private Integer ages;@EmbeddedIdprivate UserInfoID userInfoID;@Column(unique = true)private String uniqueNumber;
}

使用情况和上面@IdClass 的类似,那么 @IdClass 和 @EmbeddedId 的区别是什么?在使用的时候,Embedded 用的是对象,而 IdClass 用的是具体的某一个字段,二者的JPQL 也会不一样。

继承关系的实现

在 Java 面向对象的语言环境中,@Entity 之间的关系多种多样,而根据 JPA 的规范,我们大致可以将其分为以下几种:

  • 纯粹的继承,和表没关系,对象之间的字段共享。利用注解 @MappedSuperclass,协议规定父类不能是 @Entity
    在这里插入图片描述

  • 单表多态问题,同一张 Table,表示了不同的对象,通过一个字段来进行区分。利用@Inheritance(strategy = InheritanceType.SINGLE_TABLE)注解完成,只有父类有 @Table

在这里插入图片描述

  • 多表多态,每一个子类一张表,父类的表拥有所有公用字段。通过@Inheritance(strategy = InheritanceType.JOINED)注解完成,父类和子类都是表,有公用的字段在父表里面
    在这里插入图片描述

  • Object 的继承,数据库里面每一张表是分开的,相互独立不受影响。通过@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)注解完成,父类(可以是一张表,也可以不是)和子类都是表,相互之间没有关系。

在这里插入图片描述

@Inheritance 的这种使用方式会逐渐被淘汰,因为这样的表的设计很复杂,本应该在业务层面做的事情(多态),而在 datasoure 的表级别做了。所以在 JPA 中使用这个的时候你就会想:“这么复杂的东西,我直接用 Mybatis 算了。”其实它们是一样的,只是我们使用的思路不对。

我个人建议第一种情况,项目中会经常碰到,其它三种除非是老项目中维护需要,不建议如此使用了。

这篇关于SpringDataJPA系列(6)Entiry注解使用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1141313

相关文章

Java中switch-case结构的使用方法举例详解

《Java中switch-case结构的使用方法举例详解》:本文主要介绍Java中switch-case结构使用的相关资料,switch-case结构是Java中处理多个分支条件的一种有效方式,它... 目录前言一、switch-case结构的基本语法二、使用示例三、注意事项四、总结前言对于Java初学者

Golang使用minio替代文件系统的实战教程

《Golang使用minio替代文件系统的实战教程》本文讨论项目开发中直接文件系统的限制或不足,接着介绍Minio对象存储的优势,同时给出Golang的实际示例代码,包括初始化客户端、读取minio对... 目录文件系统 vs Minio文件系统不足:对象存储:miniogolang连接Minio配置Min

使用Python绘制可爱的招财猫

《使用Python绘制可爱的招财猫》招财猫,也被称为“幸运猫”,是一种象征财富和好运的吉祥物,经常出现在亚洲文化的商店、餐厅和家庭中,今天,我将带你用Python和matplotlib库从零开始绘制一... 目录1. 为什么选择用 python 绘制?2. 绘图的基本概念3. 实现代码解析3.1 设置绘图画

使用Python实现大文件切片上传及断点续传的方法

《使用Python实现大文件切片上传及断点续传的方法》本文介绍了使用Python实现大文件切片上传及断点续传的方法,包括功能模块划分(获取上传文件接口状态、临时文件夹状态信息、切片上传、切片合并)、整... 目录概要整体架构流程技术细节获取上传文件状态接口获取临时文件夹状态信息接口切片上传功能文件合并功能小

Golang使用etcd构建分布式锁的示例分享

《Golang使用etcd构建分布式锁的示例分享》在本教程中,我们将学习如何使用Go和etcd构建分布式锁系统,分布式锁系统对于管理对分布式系统中共享资源的并发访问至关重要,它有助于维护一致性,防止竞... 目录引言环境准备新建Go项目实现加锁和解锁功能测试分布式锁重构实现失败重试总结引言我们将使用Go作

Linux使用nohup命令在后台运行脚本

《Linux使用nohup命令在后台运行脚本》在Linux或类Unix系统中,后台运行脚本是一项非常实用的技能,尤其适用于需要长时间运行的任务或服务,本文我们来看看如何使用nohup命令在后台... 目录nohup 命令简介基本用法输出重定向& 符号的作用后台进程的特点注意事项实际应用场景长时间运行的任务服

Python3中Sanic中间件的使用

《Python3中Sanic中间件的使用》Sanic框架中的中间件是一种强大的工具,本文就来介绍Python3中Sanic中间件的使用,具有一定的参考价值,感兴趣的可以了解一下... 目录Sanic 中间件的工作流程中间件的使用1. 全局中间件2. 路由中间件3. 异常处理中间件4. 异步中间件5. 优先级

SpringBoot使用注解集成Redis缓存的示例代码

《SpringBoot使用注解集成Redis缓存的示例代码》:本文主要介绍在SpringBoot中使用注解集成Redis缓存的步骤,包括添加依赖、创建相关配置类、需要缓存数据的类(Tes... 目录一、创建 Caching 配置类二、创建需要缓存数据的类三、测试方法Spring Boot 熟悉后,集成一个外

Redis分布式锁使用及说明

《Redis分布式锁使用及说明》本文总结了Redis和Zookeeper在高可用性和高一致性场景下的应用,并详细介绍了Redis的分布式锁实现方式,包括使用Lua脚本和续期机制,最后,提到了RedLo... 目录Redis分布式锁加锁方式怎么会解错锁?举个小案例吧解锁方式续期总结Redis分布式锁如果追求

使用JavaScript操作本地存储

《使用JavaScript操作本地存储》这篇文章主要为大家详细介绍了JavaScript中操作本地存储的相关知识,文中的示例代码讲解详细,具有一定的借鉴价值,有需要的小伙伴可以参考一下... 目录本地存储:localStorage 和 sessionStorage基本使用方法1. localStorage