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

时间:2015-11-28 09:27:50

标签: java jpa architecture modularity

我的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 个答案:

答案 0 :(得分:3)

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

你是对的,你应该为持久性API构建你的模型。但我在上面的例子中没有看到你这样做的地方。除了注释,但那些不构成你的模型,它只是元数据。你甚至可以把它放到一个额外的映射文件中,并且可以有直接的模型类。

如果您的意思是从现有数据库创建模型类,并且结果类不表达业务模型,那么您应该考虑数据库模型。

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

最后一件事:如果您未在targetEntity中定义@OneToMany属性,则JPA仅使用集合的泛型类型。

答案 1 :(得分:0)

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

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

当然,您可能拥有在各层之间传输数据的代码。 A&#34;字符串名称&#34;可能出现在JPA-Object和Model-Object中。但它根本不是映射,它的缓存。缓存会使冗余变得令您感到不舒服。如果您不想缓存,请将模型层委托给JPA-Layer。但是将业务逻辑与JPA-Layer分开。

毕竟:如果你有一个小项目,你就不会遇到只有JPAObject的解决方案的任何实际问题。这一切都有尺寸。然后我推荐BusinessObject - &gt; DAO - &gt; JPAObject结构。