最近见同事在做订单和订单材料快照这方面的业务,这其实就像淘宝上的商品,不过,这里是材料了。它一共涉及到 五 张表:
因而,这里面就涉及到一对一的关系。
虽然一对一的关系用的不多,但我们有时也会设计这方面的数据表,不常用不代表不用。
我们一般做分表会使用一堆的关系,比如说用户表和用户快照表。用户表存储用户必填的信息,碧如 账号、性别、密码、登录时间、退出时间等等。用户扩展表就是用户的扩展信息,比如爱好、昵称、等等。是用户可填可不填的。如果数据都放在同一张表中,会感觉比较乱的。如代码所示:
@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;
}
用户扩展信息是用户的辅助信息,它们适合一对一的关系。
这里用户可以为分材料商和经销商,通过这个枚举类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;
。。。
}
要想称为优秀的架构师,首先参考别人的架构,毕竟,他山之石,可以攻玉吗!!!
再接再厉,致奋斗的自己!!!