如何解决这个问题:当使用JPA持久化时,应用程序模型和引擎模型不匹配?

如何解决这个问题:当使用JPA持久化时,应用程序模型和引擎模型不匹配?,jpa,model,presentation,mismatch,Jpa,Model,Presentation,Mismatch,标题可能看起来很混乱,但用几句话来描述这个问题并不容易。让我解释一下情况: 我们有一个web应用程序项目和一个计算引擎项目。web应用程序收集用户输入并使用引擎生成一些结果,并向用户表示。用户输入、引擎输出和其他数据都将使用JPA持久化到DB 引擎输入和输出由树状结构中的对象组成,例如: Class InputA { String attrA1; List<InputB> inputBs; } Class InputB { String attrB1; List&l

标题可能看起来很混乱,但用几句话来描述这个问题并不容易。让我解释一下情况:

我们有一个web应用程序项目和一个计算引擎项目。web应用程序收集用户输入并使用引擎生成一些结果,并向用户表示。用户输入、引擎输出和其他数据都将使用JPA持久化到DB

引擎输入和输出由树状结构中的对象组成,例如:

Class InputA {
  String attrA1;
  List<InputB> inputBs;
}

Class InputB {
  String attrB1;
  List<InputC> inputCs;
}

Class InputC {
  String attrC1;
}
在JavaOO世界中,这是可行的,我们可以在InputA中存储InputBx的列表,并且由于继承,我们可以在InputBx中存储InputCx的列表

但是,当使用JPA持久化扩展对象时,我们遇到了麻烦

首先,它需要engine项目使它们的类成为JPA实体。发动机本身工作正常,它接受正确的输入并产生正确的输出。当另一个项目试图持久化模型时,强迫他们的模型成为JPA实体并不是件好事

其次,当使用InputA作为条目时,JPA不接受继承的对象。从JPA的角度来看,它只知道InputA包含一个InputB列表,不可能在InputA的对象中持久化/检索InputBx列表

在试图解决这一问题时,我们提出了两个想法,但没有一个让我们满意:

想法1: 使用组合而不是继承,因此我们仍然保留原始Input,其树结构包括InputB和InputUTC:

    Class InputBx{
      String attrBx1;
      InputB inputB;
    }
    Class InputCx{
      String attrCx1;
      InputC inputC;
    }
因此,可以顺利地检索原始输入对象树,并且需要使用树中的InputB和InputUTC对象作为引用来检索InputBx和InputCx对象

好的方面是,无论对原始输入类树的结构做了什么更改(例如更改属性名、在类中添加/删除属性),扩展类InputBx和InputCx及其属性都会自动同步

缺点是这种结构增加了对数据库的调用,并且该模型在应用程序后端和前端都不容易使用。每当我们需要InputB或InputUTC的相关信息时,我们都需要手动编码来搜索InputBx和InputCx的对应对象

想法2: 手动创建镜像类,以形成与原始输入类类似的结构。因此,我们创建了:

    Class InputAx {
      String attrA1;
      List<InputBx> inputBs;
    }

    Class InputBx {
      String attrB1;
      List<InputCx> inputCs;
      String attrBx1;
    }

    Class InputCx {
      String attrC1;
      String attrCx1;
    }
我们可以使用它作为web应用程序的模型,也可以使用JPA实体。以下是我们可以得到的:

现在引擎项目可以自由设置,它不需要绑定到其他项目如何持久化这些输入/输出对象。引擎项目现在是独立的

JPA持久性工作非常流畅,不需要额外调用数据库

后端和前端UI只需使用此模型即可轻松获取原始输入对象和相关信息。当尝试使用引擎执行计算时,我们可以使用映射机制在原始对象和扩展对象之间进行转换

缺点也很明显:

类结构中存在重复,从OO的角度来看,这是不需要的

当将其视为减少数据库调用的DTO时,在本地传输中使用DTO时,可以将其称为反模式

结构不会自动与原始模型同步。因此,如果对原始模型进行了任何更改,我们也需要手动更新此模型。如果一些开发人员忘记了这样做,就会有一些不容易发现的缺陷

我正在寻找以下帮助:

是否存在任何现有的良好/最佳实践或模式来解决我们遇到的类似情况?或者我们应该避免的任何反模式?欢迎参考网络文章

如果可能的话,您能否从OO设计、持久性实践、您的经验等方面对想法1和想法2进行评论


我将非常感谢你的帮助。

嗯,当事情如此抽象时,我很难想象你在做什么。你能告诉我你代表的是什么样的数据吗?尼尔,很高兴在这里见到你。我使用抽象类是因为我认为这类问题是泛型的。例如,可以是这样的映射:InputA=City,InputB=TravelAgent,InputUTC=TravelPlan,InputBx包含TravelAgent的流程说明,InputCx包含其他TravelPlan调整。引擎只需要InputA InputB和InputUTC中的信息,UI将显示所有信息,包括InputBx和InputCx中的信息。
    Class InputAx {
      String attrA1;
      List<InputBx> inputBs;
    }

    Class InputBx {
      String attrB1;
      List<InputCx> inputCs;
      String attrBx1;
    }

    Class InputCx {
      String attrC1;
      String attrCx1;
    }