摘要:訂單快照,比如我們昨天購買的商品材料,其當(dāng)時的零售價是元,但今天就變成了元。此時我們在網(wǎng)頁上看到的材料價格是元,而我們付款的時候是元。商家是退給我們多少錢呢元,還是元當(dāng)然,是元,而不是元。這元存儲在哪里呢就是訂單快照表。
導(dǎo)讀
最近見同事在做訂單和訂單材料快照這方面的業(yè)務(wù),這其實就像淘寶上的商品,不過,這里是材料商品了。它一共涉及到 五張表 :
材料表,材料的詳細(xì)信息
訂單表,用戶購買材料時的記錄表
購物車,待付款材料
用戶表,誰購買了材料
訂單材料快照表,這就是訂單和材料的快照
因而,這里面就涉及到一對一的關(guān)系。
一對一的關(guān)系雖然一對一的關(guān)系用的不多,但我們有時也會設(shè)計這方面的數(shù)據(jù)表,不常用不代表不用。
分表一般會使用一對一的關(guān)系,比如說用戶表和用戶擴(kuò)展表。用戶表存儲用戶必填的信息,比如 賬號、性別、密碼、登錄時間、退出時間等。用戶擴(kuò)展表就是用戶的擴(kuò)展信息,比如愛好、昵稱等。用戶可填可不填的。數(shù)據(jù)如果都放在同一張表中運(yùn)維人員會感覺比較亂。
如下,是部分的用戶實體和用戶擴(kuò)展實體的代碼:
用戶表的部分?jǐn)?shù)據(jù)@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; /** * 用戶擴(kuò)展表 */ @OneToOne(mappedBy = "user", fetch = FetchType.LAZY, cascade = CascadeType.ALL) private UserExt userExt; 。。。。 }用戶擴(kuò)展表的部分?jǐn)?shù)據(jù)
@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; /** * 聯(lián)系地址 */ @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; /** * 喜歡的運(yùn)動 */ @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; }
用戶擴(kuò)展信息是用戶的輔助信息,它們適合一對一的關(guān)系。
詳解客戶材料(商品)、用戶材料(商品)、訂單、購物車、用戶、和訂單商品快照用戶,是誰購買了這個商品,這是我們需要知道的。
材料商材料(材料商的商品),因為,我們這個平臺主要是售賣裝修材料的,其分為兩部分。一部分是材料商在平臺上掛出他們的材料,材料商下的經(jīng)銷商購買材料。他們購買材料后,這就涉及另一部分,即經(jīng)銷商掛出他們的材料。這時才賣給用戶,因而,對于經(jīng)銷商來說,還要有一個市場零售價。
經(jīng)銷商材料(經(jīng)銷商的商品):正如上面所說,我是經(jīng)銷商,從材料商那邊購買了產(chǎn)品,然后,在我的這部分平臺上售賣,此時,用戶從我這邊購買了,然后將其加入到購物車中。
訂單,即為我們在購買裝修材料時所生成的一條購買記錄。
購物車,即為我們已經(jīng)選好了商品,暫時還沒有進(jìn)行付款,只是暫存起來,這也是一條記錄。等我們付款的時候,就從購物車中付款了。
訂單快照,比如我們昨天購買的商品材料,其當(dāng)時的零售價是25元,但今天就變成了40元。我們拿到材料后,感覺不大合適,于是,申請退還材料。此時我們在網(wǎng)頁上看到的材料價格是40元,而我們付款的時候是25元。商家是退給我們多少錢呢?25元,還是40元?當(dāng)然,是25元,而不是40元。這25元存儲在哪里呢?就是訂單快照表。我們在付款的那一刻,不管是直接購買的付款,還是從購物車中的購買,就會生成一條訂單材料快照表??煺毡碛心男┬畔ⅲ阂粋€購物車的外鍵,訂單的外鍵,裝修材料的中必須讓用戶知道的信息等。裝修材料從某種意義上來說,其也是一種一對一的關(guān)系,商品和快照找那個所存儲的主要的材料信息。
所有的信息,如以下代碼。不重要的或設(shè)計公司機(jī)密的信息,就不在這里展示了。
這里用戶可以為分材料商和經(jīng)銷商,通過這個枚舉類CustomerTypeEnum確定的。材料商和經(jīng)銷商放在同一張表中,根據(jù)他們的類型,來確認(rèn)是材料商和經(jīng)銷商。
@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; 。。。。
因為材料商是一個實體,我們這里只要關(guān)聯(lián)材料商的外鍵即可,而且還是一對多的關(guān)系。因為,材料表中某一個材料商的記錄不止一條。其次,還要有材料類型,材料類型表是樹結(jié)構(gòu)的,類型下面還有子類型。這里也是一對多的關(guān)系。
public class Material extends BaseObj { /** * 所屬品類 */ @ManyToOne @JoinColumn(name = "material_category_id") private MaterialCategory materialCategory; /** * 名稱 */ private String name; /** * 供應(yīng)商 */ @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; 。。。 }
經(jīng)銷商從材料商那邊購買了材料,經(jīng)銷商的材料即來源于材料這張表。因而,這個經(jīng)銷商材料只要關(guān)聯(lián)材料表即可。同時,還要有確認(rèn)經(jīng)銷商是哪個經(jīng)銷商,因而,需要一個用戶的外鍵,即經(jīng)銷商材料的所有者。經(jīng)銷商有自己的定價規(guī)則,他需要定義一個市場價。
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; 。。。 }
我們從經(jīng)銷商那邊購買了材料,此時,有條購買記錄,這就是訂單。誰發(fā)起的訂單,也就是說,誰購買的這個材料,因而,需要用戶的外鍵。
public class Order extends BaseObj { /** * 收貨地址 */ @ManyToOne @JoinColumn(name = "work_site_id") private WorkSite workSite; /** * 訂單編號 */ @Column(name = "order_no") private String orderNo; /** * 訂單狀態(tài) */ @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;
我們已經(jīng)選好了材料,但還沒有確認(rèn)付不付款,于是,先在購物車存著,想起來就付款。加入到購物車的材料是經(jīng)銷商的材料,因而,購物車需要存儲經(jīng)銷商的外鍵。同時,還要確認(rèn)是誰加入的購物車,因而購物車需要用戶的外鍵。這都是一對多的關(guān)系。同時,需要確認(rèn),這個購物車是否被使用。
public class ShoppingCart extends BaseObj { /** * 用戶材料 */ @ManyToOne @JoinColumn(name = "user_material_id") private UserMaterial userMaterial; /** * 數(shù)量 */ @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,而不是訂單快照的對象?為什么呢?首先,對于用戶來說,購買裝修材料時,這個購物車是不常用的,因為,他們一旦看中了,就會直接購買的。其次,如果我們存儲的是對象,用戶每次加載購物車時,都要從數(shù)據(jù)庫中遍歷當(dāng)前id的購物車的數(shù)據(jù)庫的字段值,然后通過hibernate的反射封裝到購物車的對象中。所以說呢,無疑是減緩了效率,這樣不好。
需要訂單的外鍵,訂單和訂單快照雖然是一對一的關(guān)系,一個訂單一個訂單快照。也就是說,當(dāng)用戶生成訂單時,就會有個訂單快照。用戶查看其購買記錄(訂單記錄)的材料信息時,材料信息不是來源于用戶材料表,而是來源于用戶訂單快照表。還有,用戶退還材料時,經(jīng)銷商要查看用戶當(dāng)前購買的材料信息。這就用到了訂單材料快照表。
public class OrderMaterialSnapshot extends BaseObj { /** * 購物車id */ @Column(name = "shopping_cart_id") private Long shoppingCartId; /** * 訂單 */ @ManyToOne @JoinColumn(name = "order_id") private Order order; /** * 狀態(tài) */ @Enumerated(EnumType.STRING) @Column(name = "status") private OrderMaterialStatusEnum status; /** * 購買數(shù)量 */ @Column(name = "num", precision = 12, scale = 2) private Double num = 1.0; /** * 退貨數(shù)量 */ @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; /** * 發(fā)貨時間 */ @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; 。。。 }總結(jié)
要想稱為優(yōu)秀的架構(gòu)師,首先參考別人的架構(gòu),畢竟,他山之石,可以攻玉嗎?。。?/p>
再接再厲,致奮斗的自己?。?!
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/73677.html
摘要:另一個時間點(diǎn)的一致性很重要,對于難以協(xié)調(diào)不一致的應(yīng)用程序。應(yīng)該將模式設(shè)計為按應(yīng)用程序單元進(jìn)行查詢。 #1:速度優(yōu)先使用嵌入數(shù)據(jù),完整性優(yōu)先使用引用數(shù)據(jù) 多個文檔使用的數(shù)據(jù)可以使用嵌入(非規(guī)范化)或引用(規(guī)范化)。非規(guī)范化并不一定比規(guī)范化更好,反之亦然:每種方式都有自己的權(quán)衡,你應(yīng)該選擇最適合你的應(yīng)用程序的方式。 非規(guī)范化可能導(dǎo)致數(shù)據(jù)不一致:假設(shè)您想要將圖1-1中的蘋果更改為梨。如果更新...
摘要:最佳實踐良好的編碼規(guī)范單元測試持續(xù)集成文檔,從一開始就形成良好的編碼習(xí)慣。真實的電商業(yè)務(wù)所有的業(yè)務(wù)需求來自真實的客戶,并且線上良好運(yùn)營中。 重要通知: Laravel + 小程序的開源電商版本源碼已經(jīng)在 github 上拉,歡迎提交 issue 和 star :) 開源電商 Server 端: Laravel API源碼 開源電商 client 端:小程序源碼 iBrand 簡介...
摘要:質(zhì)量高在設(shè)計時,可重用現(xiàn)有的,在以前的項目的領(lǐng)域中已被測試過的類使系統(tǒng)滿足業(yè)務(wù)需求并具有較高的質(zhì)量。代碼塊捕獲異常,并創(chuàng)建一個包含異常信息的對象。這樣可以解決超賣的問題,但是會導(dǎo)致文件得開銷很大。 6.你們公司是使用什么框架? 答:我們公司采用的是TP框架,運(yùn)用的mysql+apache+php進(jìn)行開發(fā),因為TP框架是一個免費(fèi)開源的,輕量級的php開發(fā)框架,而且是我們中國人自己開發(fā)的,...
摘要:什么是全稱是又稱統(tǒng)一建模語言或標(biāo)準(zhǔn)建模語言。于是乎,為了統(tǒng)一起來,就有了組織對象管理組織,這個組織讓這種描述需求設(shè)計的語言統(tǒng)一了,就稱作是了。 什么是UML? UML全稱是:Unified Modeling Language 又稱統(tǒng)一建模語言或標(biāo)準(zhǔn)建模語言。 是一個支持模型化和軟件系統(tǒng)開發(fā)的圖形化語言,為軟件開發(fā)的所有階段提供模型化和可視化支持,包括由需求分析到規(guī)格,到構(gòu)造和配置。它是...
閱讀 3162·2021-10-27 14:16
閱讀 2960·2021-09-24 10:33
閱讀 2373·2021-09-23 11:21
閱讀 3286·2021-09-22 15:14
閱讀 890·2019-08-30 15:55
閱讀 1751·2019-08-30 15:53
閱讀 1857·2019-08-29 11:14
閱讀 2246·2019-08-28 18:11