Generics 如果我使用带有泛型方法的facade类来访问jpaapi,我应该如何为特定类型提供额外的处理?

Generics 如果我使用带有泛型方法的facade类来访问jpaapi,我应该如何为特定类型提供额外的处理?,generics,jakarta-ee,jpa,dao,service-layer,Generics,Jakarta Ee,Jpa,Dao,Service Layer,假设我正在使用JavaEE规范制作一个相当简单的web应用程序,我听说这是可能的。在这个应用程序中,我只有大约10个域/数据对象,它们由JPA实体表示。Architecturally,我会考虑JPA API来执行一个DAO的角色。当然,我不想在UI JSF中直接使用EntityManager,我需要管理事务,所以我将这些任务委托给所谓的服务层 更具体地说,我希望能够在单个DataService类(通常也称为CrudService)中使用泛型方法处理这些任务。参见Adam Bien的这篇文章,了解

假设我正在使用JavaEE规范制作一个相当简单的web应用程序,我听说这是可能的。在这个应用程序中,我只有大约10个域/数据对象,它们由JPA实体表示。Architecturally,我会考虑JPA API来执行一个DAO的角色。当然,我不想在UI JSF中直接使用EntityManager,我需要管理事务,所以我将这些任务委托给所谓的服务层

更具体地说,我希望能够在单个DataService类(通常也称为CrudService)中使用泛型方法处理这些任务。参见Adam Bien的这篇文章,了解示例界面:

我的项目与那篇文章的不同之处在于我不能使用EJB,所以我的服务类本质上只是命名为bean,我手动处理事务。无论如何,我想要的是一个单一的接口,用于对我的数据对象执行简单的CRUD操作,因为为每种数据类型使用不同的类会导致大量重复和/或不必要的代码

理想情况下,我的视图将能够使用以下方法

public <T> List<T> findAll(Class<T> type) { ... }
检索数据。使用JSF,它可能看起来像这样:

<h:dataTable value="#{dataService.findAll(data.class)}" var="d">
  ...
</h:dataTable>
同样,在验证表单后,我的控制器可以使用以下方法提交数据:

public <T> void add(T entity) { ... }
当然,您可能真的想要返回一些对调用方有用的东西

在任何情况下,如果您的数据可以以这种方式被视为同质的,那么这种方法都很有效。唉,当您需要在将某些对象传递给JPA之前对它们执行额外的处理时,它就会崩溃

例如,假设我正在与书籍和作家打交道,他们之间有着多对多的关系。每本书都有一组ID引用其作者,每个作者都有一组ID引用其书籍。通常情况下,JPA可以为您管理这种关系,但在某些情况下它不能。例如,google app engine JPA提供商不支持这种关系。因此,例如,当我保存一本新书时,我可能需要更新相应的作者实体

那么,我的问题是,是否有一种优雅的方式来处理这个问题,或者我是否应该重新考虑我整个设计的合理性。以下是我看到的几种处理方法:

instanceof运算符。当需要特殊处理时,我可以使用它来针对某些类。也许可维护性会受到影响,代码也不漂亮,但如果只有10个左右的域对象,它也不会那么糟糕。。。可以吗

为每个实体类型(即BookService和AuthorService)创建不同的服务。如果需要特殊处理,所有服务都将从泛型DataService基类继承并重写方法。在这一点上,您也可以将其称为DAOs


和往常一样,我感谢你的帮助。如果需要任何澄清,请告诉我,因为我省略了许多较小的细节。

服务层主要是基于事务的需要,以及每个用例的特定业务逻辑的需要。让它变得通用没有多大意义,伊姆霍。每个实体都有一个服务也没有多大意义,仍然是这样:一些实体紧密地联系在一起,不能仅仅由服务独立地创建或更新。大多数服务涉及多个实体

服务层,顾名思义,是为上面的表示层提供服务的。因此,它不应该让一些通用接口与应用程序需要执行的实际操作脱节。它应该提供UI层需要的服务。我发现基于用例或相关用例组而不是实体来划分服务更符合逻辑。我还发现,更合理的做法是开始实现UI层,查看它需要什么服务,并实现这些服务,而不是设计通用服务,然后开始实现UI层,并陷入常见的陷阱之一:

很多服务都没有任何用处,它们被实现了,但从未被使用过 UI层开始为每个按钮单击调用N个低级服务,忘记了事务完整性,并且包含了应该在服务层中的逻辑。
谢谢你的回复!听上去,你是说我应该为我的数据建立逻辑的、聚合的组,并根据这些组和UI需求提供服务。如果你不介意举一个更具体的例子,那么如果你创建了一个众所周知的书店网站,你会如何解决作者/书籍的困境呢?您可以创建AuthorBook或内容服务,但我不确定这些名称。我最初的目标是最大限度地减少重复代码,这就是我转向通用数据访问类的原因。例如createBook服务,它采用GUI中输入的标题、GUI中输入的ISBN以及从多选框中选择的参数中的一组作者ID。
此服务将检查ISBN是否格式正确且唯一,使用em.find或em.getReference从数据库中获取作者,创建一个新的图书实体实例,使用找到的作者填充其作者集合,保存图书,并返回创建的图书,以便GUI可以重定向到图书详细信息页面,使用其生成的ID作为URL参数。我最感兴趣的是您将这种方法放在哪个类中。更具体地说,您需要在服务类上划定边界,以保持高内聚性。