有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

如何保持Java模型独立于JPA实体,同时避免代码重复

我的Java项目使用JPA作为持久性解决方案。当我阅读越来越多的JPA教程和指南时,我发现(也许为了简单起见),每个作者都使用实体类作为他们的模型类。就代码可扩展性和可维护性而言,这显然是一个糟糕的设计选择:更改持久性解决方案的决定将意味着对整个模型进行完全重构(或重写)

问题是,重写对应于每个实体类的模型类感觉不合适,也不雅观,因为如果没有JPA注释的话,所有的模型类都会和对应的实体类一样(在我个人的情况下)。把它们当作实体类实现的接口也感觉不对,因为当我可能需要用一个与实体不对应的类来扩展模型时,可能会出现不一致,或者,在Java中,用于表示@OneToMany@ManyToMany关系的泛型与抽象接口不(也不应该)协变

我现在将发布一些代码来举例说明我的担忧:

package com.depvin.pps.orm;

import javax.persistence.*;


@Entity
@DiscriminatorValue("E")
public class EmployeeEntity extends UserEntity {
    @ManyToMany
    @JoinTable(name = "EmployeeProject",
            joinColumns = @JoinColumn(name = "employee"),
            inverseJoinColumns = @JoinColumn(name = "project"))
    List<ProjectEntity> projects;

    public EmployeeEntity(String username) {
        super(username);
    }

    public List<ProjectEntity> getProjects() {
        return projects;
    }
}

考虑到我上面提到的问题,应该如何实现相应的模型类/接口


共 (2) 个答案

  1. # 1 楼答案

    在我看来,这显然是一个好的设计。实体模型类。它是(或应该是)作为域模型一部分的业务对象的表现形式

    您是对的,您应该而不是为持久性API构建模型。但在上面的例子中,我看不出你在哪里这样做。除了注释,但它们并不构成您的模型,它只是元数据。您甚至可以将其放入一个额外的映射文件中,并使用直接的模型类

    如果您的意思是从现有数据库创建模型类,而生成的类不表示业务模型,那么您应该考虑您的数据库模型

    您可以随时更改持久性解决方案,我不明白您为什么需要在这里坚持使用JPA。例如,从任何实体类创建一个JSON,只需要一些注释,这将是非常容易的

    最后一件事:如果没有在@OneToMany中定义targetEntity属性,那么JPA只使用集合的泛型类型

  2. # 2 楼答案

    JPA对象的注释是对象关系映射,因此JPA对象是对象关系映射的一部分

    您是对的,您经常将JPA对象视为项目体系结构中的模型对象。我并不是说这种解决方案在任何情况下都足够糟糕。但是,如果您想弄清楚,应该将对象关系映射层和业务层的两个方面分开。如果您这样做了,根据SRP,您可能有技术冗余,但没有语义冗余。SRP说,一个代码片段只应为一个目的进行更改。如果映射发生变化,那么ORM层就是正确的位置。如果业务规则发生更改,请转到模型层

    当然,您可能有代码在层之间传输数据。“字符串名称”可能出现在JPA对象和模型对象中。但它根本不是映射,而是缓存。缓存会造成冗余,让您感到不舒服。如果不想缓存,请将模型层委托给JPA层。但是将业务逻辑与JPA层分开

    毕竟:如果您有一个小项目,那么使用仅JPAOObject的解决方案就不会遇到任何实际问题。这一切都与大小。然后我推荐BusinessObject->;道->;JPAObject结构