资讯专栏INFORMATION COLUMN

商品、订单、购物车和订单商品快照的关系,初步了解成为架构师的思想

hover_lew / 4565人阅读

摘要:订单快照,比如我们昨天购买的商品材料,其当时的零售价是元,但今天就变成了元。此时我们在网页上看到的材料价格是元,而我们付款的时候是元。商家是退给我们多少钱呢元,还是元当然,是元,而不是元。这元存储在哪里呢就是订单快照表。

导读

最近见同事在做订单和订单材料快照这方面的业务,这其实就像淘宝上的商品,不过,这里是材料商品了。它一共涉及到 五张表

材料表,材料的详细信息

订单表,用户购买材料时的记录表

购物车,待付款材料

用户表,谁购买了材料

订单材料快照表,这就是订单和材料的快照

因而,这里面就涉及到一对一的关系。

一对一的关系

虽然一对一的关系用的不多,但我们有时也会设计这方面的数据表,不常用不代表不用。

分表一般会使用一对一的关系,比如说用户表和用户扩展表。用户表存储用户必填的信息,比如 账号、性别、密码、登录时间、退出时间等。用户扩展表就是用户的扩展信息,比如爱好、昵称等。用户可填可不填的。数据如果都放在同一张表中运维人员会感觉比较乱。

如下,是部分的用户实体和用户扩展实体的代码:

用户表的部分数据
@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;
    
    。。。

}
总结

要想称为优秀的架构师,首先参考别人的架构,毕竟,他山之石,可以攻玉吗!!!

再接再厉,致奋斗的自己!!!

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/73677.html

相关文章

  • 50个关于MongoDB模型设计技巧

    摘要:另一个时间点的一致性很重要,对于难以协调不一致的应用程序。应该将模式设计为按应用程序单元进行查询。 #1:速度优先使用嵌入数据,完整性优先使用引用数据 多个文档使用的数据可以使用嵌入(非规范化)或引用(规范化)。非规范化并不一定比规范化更好,反之亦然:每种方式都有自己的权衡,你应该选择最适合你的应用程序的方式。 非规范化可能导致数据不一致:假设您想要将图1-1中的苹果更改为梨。如果更新...

    sf190404 评论0 收藏0
  • Laravel 教程 - 实战 iBrand 开源电商 API 系统

    摘要:最佳实践良好的编码规范单元测试持续集成文档,从一开始就形成良好的编码习惯。真实的电商业务所有的业务需求来自真实的客户,并且线上良好运营中。 重要通知: Laravel + 小程序的开源电商版本源码已经在 github 上拉,欢迎提交 issue 和 star :) 开源电商 Server 端: Laravel API源码 开源电商 client 端:小程序源码 iBrand 简介...

    iOS122 评论0 收藏0
  • PHP面试题

    摘要:质量高在设计时,可重用现有的,在以前的项目的领域中已被测试过的类使系统满足业务需求并具有较高的质量。代码块捕获异常,并创建一个包含异常信息的对象。这样可以解决超卖的问题,但是会导致文件得开销很大。 6.你们公司是使用什么框架? 答:我们公司采用的是TP框架,运用的mysql+apache+php进行开发,因为TP框架是一个免费开源的,轻量级的php开发框架,而且是我们中国人自己开发的,...

    ls0609 评论0 收藏0
  • UML统一建模语言

    摘要:什么是全称是又称统一建模语言或标准建模语言。于是乎,为了统一起来,就有了组织对象管理组织,这个组织让这种描述需求设计的语言统一了,就称作是了。 什么是UML? UML全称是:Unified Modeling Language 又称统一建模语言或标准建模语言。 是一个支持模型化和软件系统开发的图形化语言,为软件开发的所有阶段提供模型化和可视化支持,包括由需求分析到规格,到构造和配置。它是...

    ninefive 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<