解密DDD:高内聚对象组的维护之道( 四 )

【解密DDD:高内聚对象组的维护之道】每种策略保存一条数据后,数据库表activity_matcher数据如下图所示:

解密DDD:高内聚对象组的维护之道

文章插图
其中:
  1. activity_type 用于区分当前数据对应的策略类型;
  2. VipLevel类型下,只有 status 和 levels 生效,服务于 VipLevelMatcher,其他全部为 null;
  3. SpecifyUser 类型下,只有 status 和 user_ids 生效,服务于 SpecifyUserMatcher,其他全部为 null;
  4. Sex类型下,只有 status 和 sex 生效,服务于 SexMatcher,其他全部为 null;
单表继承策略,最大的优点便是简单,但由于父类实体和子类实体共用一张表,因此表中会有很多空字段,造成浪费 。
3.2.2. Joined 策略Joined策略,父类实体和子类实体分别对应数据库中不同的表,子类实体的表中只存在其扩展的特殊属性,父类的公共属性保存在父类实体映射表中 。
它的使用涉及几个关键注解:
  1. @Inheritance(strategy = InheritanceType.JOINED),添加在父类实体,用于说明当前使用的是 Joined 策略;
  2. @PrimaryKeyJoinColumn(name="子类主键列名称"),添加在子类实体,用于说明使用哪个列来关联父类;
相关实体代码如下:
// 父类@Entity@Table(name = "activity_joined_matcher")// 当前策略为Joined策略@Inheritance(strategy = InheritanceType.JOINED)@Datapublic abstract class BaseActivityMatcher implements ActivityMatcher {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private ActivityMatcherStatus status = ActivityMatcherStatus.ENABLE;}// SpecifyUserMatcher 实现类@Entity@Table(name = "user_joined_matcher")@PrimaryKeyJoinColumn(name = "matcher_id")public class SpecifyUserMatcherextends BaseActivityMatcherimplements ActivityMatcher {// 省略属性和方法}// SexMatcher 实现类@Entity(name = "JoinedSexMatcher")@Table(name = "sex_joined_matcher")@PrimaryKeyJoinColumn(name = "matcher_id")public class SexMatcherextends BaseActivityMatcherimplements ActivityMatcher {// 省略属性和方法}// VipLevelMatcher 实现类@Entity(name = "JoinedVipLevelMatcher")@Table(name = "vip_joined_matcher")@PrimaryKeyJoinColumn(name = "matcher_id")public class VipLevelMatcherextends BaseActivityMatcherimplements ActivityMatcher {// 省略属性和方法}每种策略保存一条数据后,各个表数据如下:
activity_joined_matcher 如下:
解密DDD:高内聚对象组的维护之道

文章插图
user_joined_matcher 如下:
解密DDD:高内聚对象组的维护之道

文章插图
sex_joined_matcher 如下:
解密DDD:高内聚对象组的维护之道

文章插图
vip_joined_matcher 如下:
解密DDD:高内聚对象组的维护之道

文章插图
具有以下特点:
  1. 主表存储各个子类共享的父类数据;
  2. 子表通过字段与主表相关联;
  3. 主表有所有子表的数据,每个子表只有他特有的数据;
从表数据上可以看出,Joined策略可以减少冗余的空字段,但是查询时需要多表连接,效率较低 。
3.2.3. 每个实体一个表策略TABLE_PER_CLASS 策略,父类实体和子类实体每个类分别对应一张数据库中的表,子类表中保存所有属性,包括从父类实体中继承的属性 。
它的使用主要涉及以下几个点:
  1. @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS),添加在父类实体,用于说明当前使用的是 TABLE_PER_CLASS 策略;
  2. @GeneratedValue(strategy = GenerationType.AUTO) 不要使用IDENTITY,需要保障每个子类的 id 都不重复;
  3. 抽象父类不需要表与之对应,非抽象父类也需要表用于存储;
相关实体代码如下:
// 父类@Entity// 当前策略为 TABLE_PER_CLASS 策略@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)@Datapublic abstract class BaseActivityMatcher implements ActivityMatcher {@Id@GeneratedValue(strategy = GenerationType.AUTO)private Long id;// 省略属性和方法}// SpecifyUserMatcher 实现类@Entity@Table(name = "user_per_class_matcher")public class SpecifyUserMatcherextends BaseActivityMatcherimplements ActivityMatcher {// 省略属性和方法}// SexMatcher 实现类@Entity@Table(name = "sex_per_class_matcher")public class SexMatcherextends BaseActivityMatcherimplements ActivityMatcher {// 省略属性和方法}// VipLevelMatcher 实现类@Entity@Table(name = "vip_per_class_matcher")public class VipLevelMatcherextends BaseActivityMatcherimplements ActivityMatcher {// 省略属性和方法}


推荐阅读