1

所以,我一直在努力熟悉 JPA 的继承特性,并且到目前为止我真的很喜欢它们。我最近想到的一件事是,它们实际上可以用于检索数据以外的其他用途。鉴于它可以根据鉴别器值获取子类,因此继承实际上是一种将配置字段转换为实现的便捷方式。在那个阶段,我的知识与经验的比率处于“刚好够危险/不足以始终意识到它的区域”,我认为最好问问这是否是个好主意。

以 PRODUCT 和 BILLTYPE 表为例。

Product:
int Id
int billtypeid

Billtype:
int id
varchar[15] description

Billtype 只是产品的一种计费策略(我们会说一些订单可能按重量计费,而另一些可能只是按箱计费)。在开票过程中,每种账单类型都需要使用不同的方法。Billtype 表可能只有少数条目,并且不应该变得非常大。

使用继承来子类化抽象的 Billtype 实体是否有意义,该实体还为发票代码所需的不同方法定义了一个接口?像这样的东西:

@Entity
@DiscriminatorColumn("description")
public abstract class BillType {
   // Getters, setters
   // Abstract methods that could be used elsewhere - ex:
   // BigDecimal calculateInvVal(...)
}


@Entity
@DiscriminatorValue("by case")
public class CaseBillType extends BillType {
   // Implementation of calculateInvVal - now when invoicing code needs this method, 
   // the right one is always associated with the current product!
}

这提供了一种方便的方法来将行为与数据库中表示配置数据的字段相关联,但将业务代码与实体混合在一起(在大多数情况下,这非常顽皮)。可能有一个设计模式来解决我的曲目中缺少的这个问题,但我真的很想避免写很多,“如果账单类型是这样,获取这个子类,如果账单类型是这样,等等“ 代码。

我从答案中寻找的是对这种技术的潜在缺点的解释,我可能看不到这将证明寻找该问题的另一种解决方案是合理的。

4

1 回答 1

2

如果可以在运行时添加、删除和修改帐单类型,而无需重新构建和重新部署应用程序的新版本,那么将产品与 BillType 实体链接是很有用的。您的示例并非如此。

因此,如果您拥有的是一组静态账单类型,每个都定义了由 BillType 子类封装的静态行为,那么您可以简单地使用 BillType 枚举。此枚举的每个实例都定义了自己的行为。为此,您不需要实体层次结构和附加表。

在 Product 实体中计算 InVal 的代码将完全相同:

BigDecimal computeInVal() {
    billType.calculateInVal(this);
}

获取所有账单类型的代码是

return BillType.values();

而不是以下代码将账单类型与产品相关联:

product.setBillType(em.find(BillType.class, ID_OF_CASE_BILL_TYPE));

你只会有

product.setBillType(BillType.BY_CASE);
于 2012-04-17T14:12:09.220 回答