jpa onetoone_拥抱开源从表设计到 JPA 实现

c776637ca13c4882613226e65301e347.png

long may the sunshine.

今天的我拿起键盘就是猛敲代码。

果然,十分钟后各种 JPA 报错开始了。跟新手党一样,看到一个错误就解决一个,没有好好思考为什么会出现这样的错误。fd7f64dc6fbc4cc545bc7ed6cf03442b.png

于是乎,遇到一个解决一个,解决一个又遇到一个,经过数十个报错的来回起伏。

敏锐的我发现苗头有些不对。全靠脑细胞的记忆,以及开始对第一个错误的解决过程开始模糊不清了。

最后,我采用了《数据库 ER 图》的方式,重新开始分析、梳理。

也就是本文的初衷。

当我写到最后的时候。我的 Junit 用例全部跑通了。赞。

以下是正文,稍微有点。。。。。。。。。。。。。长。


01 数据库 ER 图

ER 图概念

  1. 实体 entity:用矩形表示,数据模型中的数据对象。

  2. 属性 attribute:用椭圆形表示,数据对象所具有的属性(所具有的列)。其中唯一属性 unique attribute,用下划线表示。

  3. 关系 relationshop:用菱形表示,数据对象与数据对象之间的联系。

假设有两个实体集 A、B,它们有以下三种关联关系。

  1. 一对一 1:1

    1. A 的每个实体至多与 B 的一个实体有关系。

    2. B 的每个实体至多与 A 的一个实体有关系。

    3. 满足以上两点,即 A 与 B 的关系是一对一。

  2. 一对多 1:N

    1. A 的每个实体至少与 B 的 N(N>0)个实体有关系。

    2. B 的每个实体至多与 A 的一个实体有关系。

    3. 满足以上两点,即 A 与 B 的关系是一对多,B 与 A 的关系是多对一。

  3. 多对多 M:N

    1. A 的每个实体至少与 B 的 M(M>0)个实体有关系。

    2. B 的每个实体至少与 A 的 N(N>0)个实体有关系。

    3. 满足以上两点,即 A 与 B 的关系是多对多。


02 JPA 关联

在 JPA 中分别使用 @OneToOne、@OneToMany、@ManyToOne、@ManyToMany 注解表示一对一、一对多,多对一、多对多三种关联关系。

OneToOne

  1. targetEntity,作为关联目标的实体类。

  2. cascade,必须级联到关联目标的操作。

    1. ALL,级联所有操作。

    2. PERSIST,级联保存操作。

    3. MERGE,级联修改操作。

    4. REMOVE,级联删除操作。

    5. REFRESH,级联刷新操作。

    6. DETACH,级联分离操作。(2.0 版本开始支持)

  3. fetch,关联是延迟加载还是必须立刻获取。

  4. optional,关联是否为可选。

  5. mappedBy,拥有关系的字段。仅在关联的反侧(非所有权)指定此元素。

  6. orphanRemoval,是否将删除操作应用于已从关系中删除的实体,以及是否将删除操作级联到那些实体。

OneToMany

targetEntity、cascade、fetch、mappedBy、orphanRemoval

ManyToOne

targetEntity、cascade、fetch、orphanRemoval

ManyToMany

targetEntity、cascade、fetch、mappedBy

在以上关联注解的使用过程中,还需要 @JoinColumn 指定实体关联、元素集合的列。

例如:@ManyToOne@JoinColumn(name="ADDR_ID")public Address getAddress() { return address; }@OneToMany@JoinColumn(name="CUST_ID")public SetgetOrders() {return orders;}

03 分析

fcb2de934def6735825bc3961ed97d67.png

图 A - ER 图

本案例有四张数据库表,分别为导购员、商品数据、订单主数据,以及订单明细数据。(如上图所示)

导购员、商品数据是基础数据表,即不主动关联其他的实体集。

商品主数据,包含两种关联关系。

  1. 与导购员之间的关系是多对一。即 @ManyToOne,注意这里只需要级联刷新操作即可。

  2. 与订单明细数据的关系是一对多。即@OneToMany,注意这里需要级联保存、修改、删除、刷新所有的操作。

商品明细数据,也包含两种关联关系。

  1. 与商品数据之间的关系是多对一。即 @ManyToOne,注意这里只需要级联刷新操作即可。

  2. 与订单主数据的关系是多对一。即@ManyToOne,注意这里需要级联保存、修改、删除、刷新所有的操作。


04 示例代码

导购数据 UscGuideEntity

package cn.live.opos.center.entity;// 省略 import/** * usc_guide. *  * @author chenxinjie * @date 2020-08-01 */@Entity@Table(name = "usc_guide", uniqueConstraints = { @UniqueConstraint(columnNames = "no") })public class UscGuideEntity implements Serializable {  private static final long serialVersionUID = -5648617800765002770L;  @Id  @GeneratedValue(strategy = GenerationType.AUTO, generator = "jpa-uuid")  @GenericGenerator(name = "jpa-uuid", strategy = "org.hibernate.id.UUIDGenerator")  @Column(name = "id", length = 36)  private String id;  @Column(name = "no", length = 20, nullable = false)  private String no;  @Column(name = "name", length = 40, nullable = false)  private String name;  @Column(name = "gender", columnDefinition = "int default 0", nullable = false)  private int gender;  @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")  @Temporal(TemporalType.TIMESTAMP)  @Column(name = "ts", columnDefinition = "timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP() ON UPDATE CURRENT_TIMESTAMP()", nullable = false)  private Date ts;  // 省略 get/set 方法}

商品数据 PscSkuEntity

package cn.live.opos.center.entity;// 省略 import@Entity@Table(name = "psc_sku", uniqueConstraints = { @UniqueConstraint(columnNames = "sku") })public class PscSkuEntity implements Serializable {  private static final long serialVersionUID = 8904367725209990433L;  @Id  @GeneratedValue(strategy = GenerationType.AUTO, generator = "jpa-uuid")  @GenericGenerator(name = "jpa-uuid", strategy = "org.hibernate.id.UUIDGenerator")  @Column(name = "id", length = 36)  private String id;  @Column(name = "sku", length = 50, nullable = false)  private String sku;  @Column(name = "product_no", length = 40, nullable = false)  private String productNo;  @Column(name = "product_name", length = 100, nullable = false)  private String productName;  @Column(name = "color_no", precision = 4, scale = 0, nullable = false)  private int colorNo;  @Column(name = "color_name", nullable = false)  private String colorName;  @Column(name = "size_no", precision = 4, scale = 0, nullable = false)  private int sizeNo;  @Column(name = "size_name", nullable = false)  private String sizeName;  @Column(name = "tag_price", precision = 10, scale = 0, nullable = false)  private int tagPrice;  @Column(name = "retail_price", precision = 10, scale = 0, nullable = false)  private int retailPrice;  @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")  @Temporal(TemporalType.TIMESTAMP)  @Column(name = "ts", columnDefinition = "timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP() ON UPDATE CURRENT_TIMESTAMP()", nullable = false)  private Date ts;  // 省略 get/set 方法}

订单主数据 OscOrderEntity

package cn.live.opos.center.entity;// 省略 import@Entity@EntityListeners(AuditingEntityListener.class)@Table(name = "osc_order", uniqueConstraints = { @UniqueConstraint(columnNames = "order_no") })public class OscOrderEntity implements Serializable {  private static final long serialVersionUID = -4409502876337140593L;  @Id  @GeneratedValue(strategy = GenerationType.AUTO, generator = "jpa-uuid")  @GenericGenerator(name = "jpa-uuid", strategy = "org.hibernate.id.UUIDGenerator")  @Column(name = "id", length = 36)  private String id;  @Column(name = "order_no", length = 40, nullable = false)  private String orderNo;  @CreatedDate  @JsonFormat(pattern = "yyyy-MM-dd")  @Temporal(TemporalType.DATE)  @Column(name = "order_date", nullable = false)  private Date orderDate;  /**   * 1: sell of goods. 2: return of goods.   */  @Column(name = "order_type", nullable = false)  private int orderType;  @Column(name = "order_status", nullable = false)  private int orderStatus;  @Column(name = "num", precision = 5, scale = 0, nullable = false)  private int num;  @Column(name = "total", precision = 10, scale = 0, nullable = false)  private int total;  @Column(name = "guide_no", length = 20, nullable = false)  private String guideNo;  @LastModifiedDate  @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")  @Temporal(TemporalType.TIMESTAMP)  @Column(name = "ts", columnDefinition = "timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP() ON UPDATE CURRENT_TIMESTAMP()", nullable = false)  private Date ts;  @OneToMany(targetEntity = OscOrderItemEntity.class, cascade = CascadeType.ALL, fetch = FetchType.EAGER)  @JoinColumn(name = "order_no", referencedColumnName = "order_no", insertable = false, updatable = false)  private List orderItems;  @ManyToOne(targetEntity = UscGuideEntity.class, cascade = CascadeType.REFRESH)  @JoinColumn(name = "guide_no", referencedColumnName = "no", insertable = false, updatable = false)  private UscGuideEntity guideEntity;  // 省略 get/set 方法}

订单明细数据 OscOrderItemEntity

package cn.live.opos.center.entity;// 省略 import@Entity@EntityListeners(AuditingEntityListener.class)@Table(name = "osc_order_item", uniqueConstraints = {    @UniqueConstraint(columnNames = { "order_no", "sku" }) })public class OscOrderItemEntity implements Serializable {  private static final long serialVersionUID = -7331381906879927968L;  @Id  @GeneratedValue(strategy = GenerationType.AUTO, generator = "jpa-uuid")  @GenericGenerator(name = "jpa-uuid", strategy = "org.hibernate.id.UUIDGenerator")  @Column(name = "id", length = 36)  private String id;    @Column(name = "order_no", length = 40, nullable = false)  private String orderNo;  @Column(name = "sku", length = 50, nullable = false)  private String sku;  @Column(name = "num", precision = 5, scale = 0, nullable = false)  private int num;  @Column(name = "tag_price", precision = 10, scale = 0, nullable = false)  private int tagPrice;  @Column(name = "retail_price", precision = 10, scale = 0, nullable = false)  private int retailPrice;  @Column(name = "total", precision = 10, scale = 0, nullable = false)  private int total;  @LastModifiedDate  @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")  @Temporal(TemporalType.TIMESTAMP)  @Column(name = "ts", columnDefinition = "timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP() ON UPDATE CURRENT_TIMESTAMP()", nullable = false)  private Date ts;  @ManyToOne(targetEntity = OscOrderEntity.class, cascade = CascadeType.ALL)  @JoinColumn(name = "order_no", referencedColumnName = "order_no", insertable = false, updatable = false)  private OscOrderEntity orderEntity;  @ManyToOne(targetEntity = PscSkuEntity.class, cascade = CascadeType.REFRESH)  @JoinColumn(name = "sku", referencedColumnName = "sku", insertable = false, updatable = false)  private PscSkuEntity skuEntity;  // 省略 get/set 方法}

05 效果

62612e8556a1530a834d049f70635d85.png

使用 JPA 查询一个订单主数据,JPA 会自动将配置好的其他表的数据实体自动查询出来。

也就是,省略了查询导购员、订单明细数据、商品数据三条 SQL 语句。

PS. 完整示例代码,见 https://github.com/FoamValue/oPos.git


06 小结

今天先写到这里。

夜深了,让我们下周再见。?

这个周末,又一次成功“强迫”自己学习。

感谢各位小伙伴的阅读,这里是一个技术人的学习与分享。

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

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

相关文章

python 数据流中的移动平均值_剑指Offer-41-数据流中的中位数

题目题目描述如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。 例如,[2,3,4] 的中…

vue 全局键盘_如何解决ios input框唤起软键盘不灵敏问题?

为什么移动端点击事件要加300ms延迟呢?早在 2007 年初,苹果公司在发布首款 iPhone 前夕,遇到一个问题:当时的网站都是为大屏幕设备所设计的。于是苹果的工程师们做了一些约定,应对 iPhone 这种小屏幕浏览桌面端站点的问…

css一个盒子里可以装3个图片并排吗_John: CSS浮动与清除浮动属性详解(CSS float clear)...

CSS里的浮动,可以让元素脱离标准流,从左上角或右上角依次贴边排列。下面这个案例将会帮我们了解浮动的基本情况。下面这段代码块,外面是一个大div,里面包含着3个div,第一个左浮动,后两个无浮动。//style样式…

连接驱动_在jdbc中完成对于jdbc参数、jdbc变量,加载驱动,创建连接的封装

JDBC简介JDBC中文含义:Java数据库连接,英文全称:Java Database Connectivity。它是Java语言中用来规范访问数据库的接口,提供了放多接口方法,例如查询 、更新、插入、删除等方法。另外一点要注意的是:JDBC是…

tensorflow 保存训练loss_tensorflow2.0保存和加载模型 (tensorflow2.0官方教程翻译)

最新版本:https://www.mashangxue123.com/tensorflow/tf2-tutorials-keras-save_and_restore_models.html英文版本:https://tensorflow.google.cn/alpha/tutorials/keras/save_and_restore_models翻译建议PR:https://github.com/mashangxue/t…

layui导入模板数据_数据可视化图表 教程echarts,第一讲

1我们写web项目,展示数据的地方,可能会使用到图表。今天就讲这个玩意。本教程暂时定为 三讲:(随后情况,如果有新的研究,会有所更新!)第一讲 饼图的使用第二讲 柱状图的使用第三讲 拆线图的使用此教程希望…

出发a标签_以用户标签为例,复盘B端产品的需求挖掘方法论

阅读指南受众人群:B端初级产品经理阅读收获:B端产品需求挖掘的一些技巧;了解用户标签/画像的一些业务知识。手上负责一个和数据方面有关的B端系统,在日常的产品规划当中,没有关于“用户标签”方面的规划,突…

字符ascii码值转换_没想到 Unicode 字符还能这样玩?

脚本之家你与百万开发者在一起来源 | 程序通事(ID:US_stocks)如若转载请联系原公众号上周的时候,朋友圈的直升飞机不知道为什么就火了,很多朋友开着各种花式飞机带着起飞。图片来自网络还没来得及了解咋回事来着,这个直升飞机就?…

右键菜单无响应_被流氓软件玩坏了?这两个清理工具拯救你凌乱的右键菜单。...

Hello 这里是一周进步我们写了四年近2000篇的干货文章,还分享了许多实用的神器工具,一路以来,感谢大家的支持与陪伴~文 / 一周进步 安哥拉如果你和我们一样,是一个喜欢在电脑上安装各种各样的软件的人,你的电脑右键菜…

jsp mysql源码_jsp+servlet+mysql员工管理系统源代码下载

jspservletmysql员工管理系统项目截图注册页面登录页面添加员工编辑员工员工列表数据库建表语句/*Navicat MySQL Data TransferSource Server : localhostSource Server Version : 50509Source Host : localhost:3306Source Database : wdhdbTarget Server Type : MYSQLTarget …

vs里安装了mysql吗_vs2017安装 MySQL for Visual Studio 1.2.

vs2017安装想在win7EF6 VS2017 MySQL 但是安装MySQL for Visual Studio 1.2.7 时一直安装不上去,如下:Action 9:40:05: InstallFinalize.1: Action 9:40:05: DeleteRegKeyAndExtensionsFile_VS2013.1: Action 9:40:06: DeleteRegKeyAndExtensionsFile_…

mysql数据库优化语句_mysql数据库优化语句

mysql优化语句数据库语句: Ddl(数据定义语言) alter create drop Dml(数据操作语言) inset delete update www.2cto.com Dtl(数据事务语言) conmmit rollback savepoint Select Dcl(数据控制语句) grant赋权限 revoke回收 Mysql数据库优化: 1、 数据库表…

json模拟数据怎么用_在使用axios获取自己模拟的json数据是踩到的坑

最近在使用Vue仿写一个网易云音乐的单页面应用,当页面布局什么的写完后,然后就准备用axios获取后台数据渲染页面了,当然,我自己写的,并没有后台,所以,我就自己写json文件,然后弄prox…

mysql架构深入_mysql性能优化2:深入认识mysql体系架构

前言本文将重点梳理mysql的体系架构,便于了解mysql的实现原理。Mysql体系结构Client Connectors 接入方 支持协议很多Management Serveices & Utilities 系统管理和控制工具,mysqldump、 mysql复制集群、分区管理等Connection Pool 连接池&#xff1…

mysql租车管理系统_基于java实现租车管理系统

概述基于java swing JFrame 的图书馆管理系统,租车,还车,管理员管理用户,付款等。部分代码public class Login extends JFrame {private static final long serialVersionUID 1L;/*** 登录窗体*/public Login() {setDefaultClo…

java 1的阶乘之和_1-20的阶乘之和(java)

import java.math.BigInteger;public class Factorial {//2)求1&#xff01;2&#xff01;……20&#xff01;public static void main(String[] args){BigInteger sumBigInteger.ZERO;for(BigInteger iBigInteger.ONE;i.intValue()<20;){ii.add(BigInteger.ONE);sumsum.add…

java构建json_Java构造和解析Json数据的两种方法详解一

在www.json.org上公布了很多JAVA下的json构造和解析工具&#xff0c;其中org.json和json-lib比较简单&#xff0c;两者使用上差不多但还是有些区别。下面首先介绍用json-lib构造和解析Json数据的方法示例。用org.son构造和解析Json数据的方法详解请参见我下一篇博文&#xff1a…

java final被覆盖_java中的final的使用

1、final类不能被继承&#xff0c;因此final类的成员方法没有机会被覆盖&#xff0c;默认都是final的。在设计类时候&#xff0c;如果这个类不需要有子类&#xff0c;类的实现细节不允许改变&#xff0c;并且确信这个类不会再被扩展&#xff0c;那么就设计为final类。(什么时候…

wordcount.java_mapreduce中wordcount的java实现

用java模拟词频统计。有3个文件&#xff1a;text1: hello worldtext2:hello hadooptext3:hello mapreduce对上面的文件进行词频统计&#xff1a;结果应该是&#xff1a;hello:3; hadoop:1; world:1; mapreduce:1代码实现如下&#xff1a;package count;import java.ut…

java程序回滚之后在哪看_Java在触发事务回滚之后为什么会再一次回到Servlet开始的地方重新走一次流程?...

代码流程前台点击"提交订单"进入BaseServlet.classBaseServlet.class分发至子类OrderServlet.class的submitOrder()方法submitOrder()调用Service层的submitOrder()方法.关键是Service层submitOrder()中使用了事务回滚. 这里调用了Dao层两个方法: fun01()和fun02(), …