从零开始 Spring Boot 52:@Embedded 和 @Embeddable

从零开始 Spring Boot 52:@Embedded 和 @Embeddable

spring boot

图源:简书 (jianshu.com)

这篇文章会介绍@Embedded@Embeddable两个注解在 JPA 中的用法。

简单示例

先看一个示例:

@AllArgsConstructor
@Builder
@Data
@Entity
@Table(name = "user_student")
@Accessors(chain = true)
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
public class Student {@Id@GeneratedValue(strategy = GenerationType.AUTO)@EqualsAndHashCode.Includeprivate Long id;@Column(length = 25, nullable = false)private String name;@Column(length = 50, nullable = false)private String address;@Column(length = 25)private String contactsName;@Column(length = 50)private String contactsAddress;@Column(length = 15)private String contactsPhone;public Student() {}
}

这里使用了 Lombok 相关注解(比如@Builder)帮助构建实体类,详细内容可以阅读我的相关文章。

user_student是一个学生表,其中的contacts_开头的字段保存联系人信息,这体现在实体类中就是以contacts开头的属性。

测试用例:

@Test
@SneakyThrows
void testAddNewStudent() {Student newStudent = Student.builder().address("宁安大街101号").name("icexmoon").contactsName("lalala").contactsAddress("北京大街100号").contactsPhone("123456789").build();studentRepository.save(newStudent);Assertions.assertNotNull(newStudent.getId());ObjectMapper om = new ObjectMapper();var json = om.writeValueAsString(newStudent);System.out.println(json);
}

这样做并没有什么问题,但Student这个实体类并不具备良好的“结构化”,换言之我们很难将其中的联系人部分进行代码重用。

因此,接下来我们要想办法将Student中的联系人部分信息提取出来单独作为一个类型存在,这可以借助 JPA 的@Embedded@Embeddable注解完成。

@Embedded 和 @Embeddable

先定义一个联系人类:

@Embeddable
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Contacts {private String name;private String address;private String phone;
}

使用@Embedded@Embeddable“改造”Student类:

@AllArgsConstructor
@Builder
@Data
@Entity
@Table(name = "user_student2")
@Accessors(chain = true)
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
public class Student2 {@Id@GeneratedValue(strategy = GenerationType.AUTO)@EqualsAndHashCode.Includeprivate Long id;@Column(length = 25, nullable = false)private String name;@Column(length = 50, nullable = false)private String address;@Embedded@AttributeOverrides({@AttributeOverride(name = "name", column = @Column(name = "contacts_name", length = 25)),@AttributeOverride(name = "address", column = @Column(name = "contacts_address", length = 50)),@AttributeOverride(name = "phone", column = @Column(name = "contacts_phone", length = 15))})private Contacts contacts;public Student2() {}
}

这里的@Embeddable注解表明该类可以被“嵌入”到一个实体类中,充当某些字段的映射。@Embedded注解表明这里嵌入了一个用@Embeddable标记的类。

就像以前学习 MyBastis 时在一个 MapperSet 中嵌入另一个 MapperSet 时需要指定字段映射关系,这里同样需要指定,这体现在 @AttributeOverrides注解中包含的多条@AttributeOverride注解。其name属性表示的是被嵌入的类型的属性名称,column属性表示的是对应的数据库表结构中的字段信息。

如果缺省@AttributeOverrides@AttributeOverride注解,默认会用被嵌入的类型(这里是Contacts)的属性名称作为表结构字段名进行映射。但显然这里是行不通的,会报错(因为联系人的姓名与学生的姓名都会映射到同一个name字段)。

现在实体类变得更加“结构化”,这点在测试用例中构建新对象时体现的很明显:

@Test
@SneakyThrows
void testAddNewStudent() {Student2 newStudent = Student2.builder().address("宁安大街101号").name("icexmoon").contacts(Contacts.builder().name("lalala").address("北京东路100号").phone("123456789").build()).build();student2Repository.save(newStudent);Assertions.assertNotNull(newStudent.getId());ObjectMapper om = new ObjectMapper();var json = om.writeValueAsString(newStudent);System.out.println(json);
}

输出的 JSON 串也能更清楚地观察到结构化的好处。

The End,谢谢阅读。

本文的完整示例代码可以从这里获取。

参考资料

  • Jpa @Embedded and @Embeddable | Baeldung

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

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

相关文章

【小沐学Unity3d】Unity播放视频(VideoPlayer组件)

文章目录 1、简介2、脚本播放示例3、界面播放示例3.1 2d界面全屏播放3.2 2d界面部分区域播放3.3 3d模型表面播放 结语 1、简介 使用视频播放器组件可将视频文件附加到游戏对象,然后在运行时在游戏对象的纹理上播放。 视频播放器 (Video Player) 组件: 属性功能Sourc…

Mysql锁机制介绍

Mysql锁机制 锁是计算机协调多个进程或线程并发访问某一资源的机制。 在数据库中,除传统的计算资源(如CPU、RAM、I/O等)的争用以外,数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性、有效性是所有数据库必须解决的一个问题&#xff0…

【算法】最长递增子序列:动态规划贪心+二分查找

文章目录 最长递增子序列解法一:动态规划解法二:LIS 和 LCS 的关系解法三:贪心 二分查找 相关题目673. 最长递增子序列的个数 https://leetcode.cn/problems/number-of-longest-increasing-subsequence/1964. 找出到每个位置为止最长的有效障…

理解mysql数据库

1.MySQL 在 Centos 7环境安装 1.1 卸载不要的环境 ps ajx |grep mariadb # 先检查是否有 mariadb 存在 systemctl stop mariadb.service # 停⽌ mariadb 服务 ps ajx |grep mariadb # 再 检查是否有 mariadb 存在 1.2 删除多余的安装包 rpm -qa | grep mysql #查看默认安装…

Unity内置渲染管线升级URP教程

简介 URP全称为Universal Render Pipeline(通用渲染管线),可以提供更加灵活的渲染方案,通过添加Render Feature实现各种渲染效果。并且可以针对移动平台进行专门的优化,同时还提供了SRPBatcher提高渲染效率。Unity的一些工具,比如…

《项目实战》构建SpringCloud alibaba项目(三、构建服务方子工程store-user-service)

系列文章目录 构建SpringCloud alibaba项目(一、构建父工程、公共库、网关) 构建SpringCloud alibaba项目(二、构建微服务鉴权子工程store-authority-service) 构建SpringCloud alibaba项目(三、构建服务方子工程stor…

95道MongoDB面试题

1、mongodb是什么? MongoDB 是由 C语言编写的,是一个基于分布式文件存储的开源数据库系统。 再高负载的情况下,添加更多的节点,可以保证服务器性能。 MongoDB 旨在给 WEB 应用提供可扩展的高性能数据存储解决方案。 MongoDB 将数…

前端技术栈 - ES6 - Promise -模块化编程

文章目录 🕛ES6⚡let变量⚡const常量⚡数组解构⚡对象解构⚡模板字符串⚡对象声明简写⚡对象方法简写⚡对象运算符扩展⚡箭头函数⚡作业布置 🕐Promise⚡需求分析⚡传统ajax回调嵌套⚡promise改进⚡promise异常捕获⚡promise链式调用⚡promise代码重排优…

Spark 3.4.x Server Client模式下的数据传输实现

背景 在Spark中python和jvm的通信杂谈–ArrowConverter中,我们提到Spark 3.4.x中是Client和Server之间的数据传输是采用Arrow IPC的,那具体是怎么实现的呢? 分析 直接上代码ClientE2ETestSuite test("createDataFrame from complex t…

Redis————主从架构

主从架构搭建 单机多实例 粗制一份redis.conf文件 将相关配置修改为如下值: port 与主节点端口后不相同即可 pidfile pid进程号保存文件pidfile的路径 logfile 日志文件名称 dir 指定数据存放目录 #需要注释掉bind #bind 127.0.0.1(bind绑定的是自己机…

Git使用与配置

Git分布式版本控制工具 一、Git安装与配置 Git基本配置 打开Git Bash 设置用户信息 # 配置用户名和用户邮箱 git config --global user.name xxx git config --global user.email xxxxx.com查看用户信息 # 查看用户名和用户邮箱 git config --global user.name git config --g…

【前端|CSS系列第1篇】CSS零基础入门之CSS的基本概念和选择器

欢迎来到CSS零基础入门系列的第一篇博客!在这个系列中,我们将一起学习CSS(层叠样式表)的基础知识,探索如何为网页添加样式和布局。本篇博客将重点介绍CSS的基本概念和选择器,帮助你理解CSS的核心概念。 1.…