商品、订单、购物车和订单商品快照的关系,初步了解成为架构师的思想
有志者,事竟成!如果你在学习数据库,那么本文《商品、订单、购物车和订单商品快照的关系,初步了解成为架构师的思想》,就很适合你!文章讲解的知识点主要包括MySQL、Java,若是你对本文感兴趣,或者是想搞懂其中某个知识点,就请你继续往下看吧~
导读
最近见同事在做订单和订单材料快照这方面的业务,这其实就像淘宝上的商品,不过,这里是材料商品了。它一共涉及到 五张表 :
- 材料表,材料的详细信息
- 订单表,用户购买材料时的记录表
- 购物车,待付款材料
- 用户表,谁购买了材料
- 订单材料快照表,这就是订单和材料的快照
因而,这里面就涉及到一对一的关系。
一对一的关系
虽然一对一的关系用的不多,但我们有时也会设计这方面的数据表,不常用不代表不用。
分表一般会使用一对一的关系,比如说用户表和用户扩展表。用户表存储用户必填的信息,比如 账号、性别、密码、登录时间、退出时间等。用户扩展表就是用户的扩展信息,比如爱好、昵称等。用户可填可不填的。数据如果都放在同一张表中运维人员会感觉比较乱。
如下,是部分的用户实体和用户扩展实体的代码:
用户表的部分数据
@Entity @Table(name = "core_user") public class User { /** * 用户名,唯一 */ @NotEmpty(message = "用户名不能为空") @Column(length = 100, unique = true, nullable = false) private String username; /** * 密码 */ @Column(nullable = false, length = 66) private String password; /** * 用户扩展表 */ @OneToOne(mappedBy = "user", fetch = FetchType.LAZY, cascade = CascadeType.ALL) private UserExt userExt; 。。。。 }
用户扩展表的部分数据
@Entity @Table(name = "core_user_ext") public class UserExt implements Serializable { @OneToOne @PrimaryKeyJoinColumn private User user; /** * 自我介绍 */ @Lob @Basic(fetch = FetchType.LAZY) @Column(name = "introduce", columnDefinition = "text") private String introduce; /** * 性别 */ @Enumerated(EnumType.STRING) @Column(name = "gender", length = 20) private GenderEnum gender; /** * 昵称 */ @Column(name = "nick_name", length = 66) private String nickName; /** * 真实姓名 */ @Column(name = "real_name", length = 100) private String realName; /** * 头像 */ @ManyToOne @JoinColumn(name = "head_image") private Picture headImage; /** * 联系地址 */ @Column(name = "address", length = 200) private String address; /** * 邮政编码 */ @Column(name = "postal_code") private String postalCode; @Column(name = "qq", length = 66) private String qq; /** * 身高 */ @Column(length = 3) private Integer height; /** * 喜欢的运动 */ @Column(name = "loved_sports", length = 255) private String lovedSports; /** * 喜欢的电影 */ @Column(name = "loved_movies", length = 255) private String lovedMovies; /** * 喜欢的音乐 */ @Column(name = "loved_musics", length = 255) private String lovedMusics; /** * 喜欢的食物 */ @Column(name = "loved_foods", length = 255) private String lovedFoods; /** * 喜欢的书 */ @Column(name = "loved_books", length = 255) private String lovedBooks; /** * 喜欢的游戏 */ @Column(name = "loved_games", length = 255) private String lovedGames; }
用户扩展信息是用户的辅助信息,它们适合一对一的关系。
详解客户材料(商品)、用户材料(商品)、订单、购物车、用户、和订单商品快照
- 用户,是谁购买了这个商品,这是我们需要知道的。
- 材料商材料(材料商的商品),因为,我们这个平台主要是售卖装修材料的,其分为两部分。一部分是材料商在平台上挂出他们的材料,材料商下的经销商购买材料。他们购买材料后,这就涉及另一部分,即经销商挂出他们的材料。这时才卖给用户,因而,对于经销商来说,还要有一个市场零售价。
- 经销商材料(经销商的商品):正如上面所说,我是经销商,从材料商那边购买了产品,然后,在我的这部分平台上售卖,此时,用户从我这边购买了,然后将其加入到购物车中。
- 订单,即为我们在购买装修材料时所生成的一条购买记录。
- 购物车,即为我们已经选好了商品,暂时还没有进行付款,只是暂存起来,这也是一条记录。等我们付款的时候,就从购物车中付款了。
- 订单快照,比如我们昨天购买的商品材料,其当时的零售价是25元,但今天就变成了40元。我们拿到材料后,感觉不大合适,于是,申请退还材料。此时我们在网页上看到的材料价格是40元,而我们付款的时候是25元。商家是退给我们多少钱呢?25元,还是40元?当然,是25元,而不是40元。这25元存储在哪里呢?就是订单快照表。我们在付款的那一刻,不管是直接购买的付款,还是从购物车中的购买,就会生成一条订单材料快照表。快照表有哪些信息:一个购物车的外键,订单的外键,装修材料的中必须让用户知道的信息等。装修材料从某种意义上来说,其也是一种一对一的关系,商品和快照找那个所存储的主要的材料信息。
所有的信息,如以下代码。不重要的或设计公司机密的信息,就不在这里展示了。
用户表
这里用户可以为分材料商和经销商,通过这个枚举类CustomerTypeEnum确定的。材料商和经销商放在同一张表中,根据他们的类型,来确认是材料商和经销商。
@Entity @Table(name = "core_user") public class User{ /** * 用户名,唯一 */ @NotEmpty(message = "用户名不能为空") @Column(length = 100, unique = true, nullable = false) private String username; /** * 密码 */ @Column(nullable = false, length = 66) private String password; /** * 最近登录ip */ @Column(name = "last_login_ip", length = 64) private String lastLoginIP; 。。。。
材料商材料
因为材料商是一个实体,我们这里只要关联材料商的外键即可,而且还是一对多的关系。因为,材料表中某一个材料商的记录不止一条。其次,还要有材料类型,材料类型表是树结构的,类型下面还有子类型。这里也是一对多的关系。
public class Material extends BaseObj { /** * 所属品类 */ @ManyToOne @JoinColumn(name = "material_category_id") private MaterialCategory materialCategory; /** * 名称 */ private String name; /** * 供应商 */ @ManyToOne @JoinColumn(name = "supplier_id") private Supplier supplier; /** * 品牌 */ @ManyToOne @JoinColumn(name = "material_brand_id") private MaterialBrand materialBrand; /** * 成本价 */ @Column(name = "cost_price", precision = 12, scale = 2) private BigDecimal costPrice; /** * 零售价 */ @Column(name = "retail_price", precision = 12, scale = 2) private BigDecimal retailPrice; /** * 单位 */ @ManyToOne @JoinColumn(name = "unit_code") private DataDict unit; 。。。 }
经销商材料
经销商从材料商那边购买了材料,经销商的材料即来源于材料这张表。因而,这个经销商材料只要关联材料表即可。同时,还要有确认经销商是哪个经销商,因而,需要一个用户的外键,即经销商材料的所有者。经销商有自己的定价规则,他需要定义一个市场价。
public class UserMaterial extends BaseObj { /** * 材料 */ @ManyToOne @JoinColumn(name = "material_id") private Material material; /** * 所有者 */ @ManyToOne @JoinColumn(name = "owner_id") private User owner; /** * 市场价 */ @Column(name = "market_price", precision = 12, scale = 2) private BigDecimal marketPrice; 。。。 }
订单
我们从经销商那边购买了材料,此时,有条购买记录,这就是订单。谁发起的订单,也就是说,谁购买的这个材料,因而,需要用户的外键。
public class Order extends BaseObj { /** * 收货地址 */ @ManyToOne @JoinColumn(name = "work_site_id") private WorkSite workSite; /** * 订单编号 */ @Column(name = "order_no") private String orderNo; /** * 订单状态 */ @Enumerated(EnumType.STRING) private OrderStatusEnum status; /** * 订单备注 */ @Column(name = "remark", columnDefinition = "longtext") private String remark; /** * 下单时间 */ @Column(name = "generate_time") private Date generateTime; /** * 提交时间 */ @Column(name = "submit_time") private Date submitTime; /** * 买家 */ @ManyToOne @JoinColumn(name = "buyer_id") private User buyer;
购物车
我们已经选好了材料,但还没有确认付不付款,于是,先在购物车存着,想起来就付款。加入到购物车的材料是经销商的材料,因而,购物车需要存储经销商的外键。同时,还要确认是谁加入的购物车,因而购物车需要用户的外键。这都是一对多的关系。同时,需要确认,这个购物车是否被使用。
public class ShoppingCart extends BaseObj { /** * 用户材料 */ @ManyToOne @JoinColumn(name = "user_material_id") private UserMaterial userMaterial; /** * 数量 */ @Column(name = "num", precision = 12, scale = 2) private Double num = 1.0; /** * 金额 */ @Column(name = "amount", precision = 12, scale = 2) private BigDecimal amount; /** * 所有者 */ @ManyToOne @JoinColumn(name = "owner_id") private User owner; /** * 是否被使用 */ @Enumerated(EnumType.STRING) @Column(name = "is_used") private BooleanEnum isUsed = NO; }
订单材料快照表
这里,我们只要存储订单快照的id,而不是订单快照的对象?为什么呢?首先,对于用户来说,购买装修材料时,这个购物车是不常用的,因为,他们一旦看中了,就会直接购买的。其次,如果我们存储的是对象,用户每次加载购物车时,都要从数据库中遍历当前id的购物车的数据库的字段值,然后通过hibernate的反射封装到购物车的对象中。所以说呢,无疑是减缓了效率,这样不好。
需要订单的外键,订单和订单快照虽然是一对一的关系,一个订单一个订单快照。也就是说,当用户生成订单时,就会有个订单快照。用户查看其购买记录(订单记录)的材料信息时,材料信息不是来源于用户材料表,而是来源于用户订单快照表。还有,用户退还材料时,经销商要查看用户当前购买的材料信息。这就用到了订单材料快照表。
public class OrderMaterialSnapshot extends BaseObj { /** * 购物车id */ @Column(name = "shopping_cart_id") private Long shoppingCartId; /** * 订单 */ @ManyToOne @JoinColumn(name = "order_id") private Order order; /** * 状态 */ @Enumerated(EnumType.STRING) @Column(name = "status") private OrderMaterialStatusEnum status; /** * 购买数量 */ @Column(name = "num", precision = 12, scale = 2) private Double num = 1.0; /** * 退货数量 */ @Column(name = "refund_num") private Double refundNum = 0.0; /** * 购买总金额 */ @Column(name = "amount", precision = 12, scale = 2) private BigDecimal amount; /** * 接单时间 */ @Column(name = "receive_time") private Date receiveTime; /** * 发货时间 */ @Column(name = "deliver_time") private Date deliverTime; /** * 收货时间 */ @Column(name = "receipt_time") private Date receiptTime; /** * 所属品类 */ @ManyToOne @JoinColumn(name = "material_category_id") private MaterialCategory materialCategory; /** * 名称 */ private String name; /** * 品牌 */ @OneToOne @JoinColumn(name = "material_brand_id") private MaterialBrand materialBrand; /** * 型号 */ private String model; /** * 零售价 */ @Column(name = "retail_price", precision = 12, scale = 2) private BigDecimal retailPrice; /** * 会员单价(材料商零售价*会员折扣) */ @Column(name = "vip_unit_price", precision = 12, scale = 2) private BigDecimal vipUnitprice; /** * 市场价 */ @Column(name = "market_price", precision = 12, scale = 2) private BigDecimal marketPrice; /** * 单位 */ @ManyToOne @JoinColumn(name = "unit_code") private DataDict unit; 。。。 }
总结
要想称为优秀的架构师,首先参考别人的架构,毕竟,他山之石,可以攻玉吗!!!
再接再厉,致奋斗的自己!!!
以上就是本文的全部内容了,是否有顺利帮助你解决问题?若是能给你带来学习上的帮助,请大家多多支持golang学习网!更多关于数据库的相关知识,也可关注golang学习网公众号。

- 上一篇
- 地理位置geo处理之mysql函数

- 下一篇
- 数据库的常用操作
-
- 长情的钢笔
- 这篇博文太及时了,细节满满,很有用,mark,关注楼主了!希望楼主能多写数据库相关的文章。
- 2023-03-06 09:24:34
-
- 数据库 · MySQL | 21小时前 | 索引 数据类型 字符集 存储引擎 CREATETABLE
- MySQL新建表操作指南与建表技巧
- 462浏览 收藏
-
- 数据库 · MySQL | 1个月前 | 条件判断
- CASEWHEN条件判断的嵌套使用详解与实战场景分析
- 469浏览 收藏
-
- 数据库 · MySQL | 1个月前 | java php
- CSV文件批量导入MySQL的性能优化秘籍大揭秘
- 289浏览 收藏
-
- 数据库 · MySQL | 1个月前 |
- GaleraCluster多主集群配置与冲突解决攻略
- 239浏览 收藏
-
- 数据库 · MySQL | 1个月前 | 窗口函数实战
- MySQL窗口函数实战案例深度剖析
- 315浏览 收藏
-
- 数据库 · MySQL | 1个月前 | 自定义函数
- MySQL插件开发入门:自定义函数(UDF)编写指南
- 184浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 508次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 497次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 484次学习
-
- 笔灵AI生成答辩PPT
- 探索笔灵AI生成答辩PPT的强大功能,快速制作高质量答辩PPT。精准内容提取、多样模板匹配、数据可视化、配套自述稿生成,让您的学术和职场展示更加专业与高效。
- 16次使用
-
- 知网AIGC检测服务系统
- 知网AIGC检测服务系统,专注于检测学术文本中的疑似AI生成内容。依托知网海量高质量文献资源,结合先进的“知识增强AIGC检测技术”,系统能够从语言模式和语义逻辑两方面精准识别AI生成内容,适用于学术研究、教育和企业领域,确保文本的真实性和原创性。
- 25次使用
-
- AIGC检测-Aibiye
- AIbiye官网推出的AIGC检测服务,专注于检测ChatGPT、Gemini、Claude等AIGC工具生成的文本,帮助用户确保论文的原创性和学术规范。支持txt和doc(x)格式,检测范围为论文正文,提供高准确性和便捷的用户体验。
- 30次使用
-
- 易笔AI论文
- 易笔AI论文平台提供自动写作、格式校对、查重检测等功能,支持多种学术领域的论文生成。价格优惠,界面友好,操作简便,适用于学术研究者、学生及论文辅导机构。
- 42次使用
-
- 笔启AI论文写作平台
- 笔启AI论文写作平台提供多类型论文生成服务,支持多语言写作,满足学术研究者、学生和职场人士的需求。平台采用AI 4.0版本,确保论文质量和原创性,并提供查重保障和隐私保护。
- 35次使用
-
- golang MySQL实现对数据库表存储获取操作示例
- 2022-12-22 499浏览
-
- 搞一个自娱自乐的博客(二) 架构搭建
- 2023-02-16 244浏览
-
- B-Tree、B+Tree以及B-link Tree
- 2023-01-19 235浏览
-
- mysql面试题
- 2023-01-17 157浏览
-
- MySQL数据表简单查询
- 2023-01-10 101浏览