最近見同事在作訂單和訂單材料快照這方面的業務,這其實就像淘寶上的商品,不過,這裏是材料商品了。它一共涉及到 五張表 :數據庫
於是,這裏面就涉及到一對一的關係。架構
雖然一對一的關係用的很少,但咱們有時也會設計這方面的數據表,不經常使用不表明不用。app
分表通常會使用一對一的關係,好比說用戶表和用戶擴展表。用戶表存儲用戶必填的信息,好比 帳號、性別、密碼、登陸時間、退出時間等。用戶擴展表就是用戶的擴展信息,好比愛好、暱稱等。用戶可填可不填的。數據若是都放在同一張表中運維人員會感受比較亂。運維
以下,是部分的用戶實體和用戶擴展實體的代碼:post
@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; }
用戶擴展信息是用戶的輔助信息,它們適合一對一的關係。fetch
全部的信息,如如下代碼。不重要的或設計公司機密的信息,就不在這裏展現了。編碼
這裏用戶能夠爲分材料商和經銷商,經過這個枚舉類CustomerTypeEnum肯定的。材料商和經銷商放在同一張表中,根據他們的類型,來確認是材料商和經銷商。hibernate
@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; 。。。 }
經銷商從材料商那邊購買了材料,經銷商的材料即來源於材料這張表。於是,這個經銷商材料只要關聯材料表便可。同時,還要有確認經銷商是哪一個經銷商,於是,須要一個用戶的外鍵,即經銷商材料的全部者。經銷商有本身的訂價規則,他須要定義一個市場價。code
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; 。。。 }
要想稱爲優秀的架構師,首先參考別人的架構,畢竟,他山之石,能夠攻玉嗎!!!
再接再礪,致奮鬥的本身!!!