java - 实现相同接口(interface)的 DTO 和实体

标签 java android spring hibernate jpa

我有下一个 Maven 项目:

  • project-model :我有 JPA 实体
  • project-rest : Spring data, spring rest 基于spring boot
  • project-client : 泽西客户端消费其余服务
  • project-web : 只有 jsf web 应用程序
  • project-desktop:Java Fx 桌面应用
  • project-android:使用我的 Rest 网络服务的移动应用程序。

我计划从项目模型中删除 JPA 实体并仅放置 DTO 的 pojo 和接口(interface)并将我的 JPA 实体放在其余项目中以便从项目模型中删除 jpa 依赖项。这是因为我不想在 project-androidproject-webproject-desktop 中有 JPA 依赖项。

我想遵循下一个模式:

   @JsonSerialize(as=CountryDto.class)
   @JsonDeserialize(as=CountryDto.class)
   public interface ICountry extends Serializable
   {}

   @Entity
   @Table(name = "COUNTRY")
   @JsonSerialize(as=Country.class)
   @JsonDeserialize(as=Country.class)
   public class Country implements ICountry
   {}

   public class CountryDto implements ICountry
   {}

如果我需要从实体转换为 DTO,请使用 mapstruct 或 Selma。

但我不确定这是否是最佳实践,因为我的代码中存在如下问题:

@JsonSerialize(as=CityDto.class)
@JsonDeserialize(as=CityDto.class)
public interface ICity extends Serializable
{

    public Integer getIdCity();

    public void setIdCity(Integer idCity);

    public String getName();

    public void setName(String name);

    public ICountry getCountryId();

    public void setCountryId(ICountry countryId);

}


public class CityDto implements ICity
{

    private static final long serialVersionUID = -6960160473351421716L;

    private Integer idCity;
    private String name;
    private CountryDto countryId;

    public CityDto()
    {
        // TODO Auto-generated constructor stub
    }

    public CityDto(Integer idCity, String name, CountryDto countryId)
    {
        super();
        this.idCity = idCity;
        this.name = name;
        this.countryId = countryId;
    }
    public CityDto(Integer idCity, String name)
    {
        super();
        this.idCity = idCity;
        this.name = name;
    }

    @Override
    public Integer getIdCity()
    {
        return idCity;
    }

    @Override
    public void setIdCity(Integer idCity)
    {
        this.idCity = idCity;
    }

    @Override
    public String getName()
    {
        return name;
    }

    @Override
    public void setName(String name)
    {
        this.name = name;
    }

    @Override
    public ICountry getCountryId()
    {
        return countryId;
    }

    @Override
    public void setCountryId(ICountry countryId)
    {
        this.countryId = (CountryDto) countryId;
    }

}


@Entity
@Table(name = "CITY")
@JsonSerialize(as=City.class)
@JsonDeserialize(as=City.class)
public class City implements ICity
{

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ID_CITY")
    private Integer idCity;

    @Basic(optional = false)
    @NotNull
    @Size(min = 1, max = 100)
    @Column(name = "NAME")
    private String name;

    @JoinColumn(name = "COUNTRY_ID", referencedColumnName = "ID_COUNTRY")
    @ManyToOne(optional = false)
    private Country countryId;

    private static final long serialVersionUID = 1L;

    public City()
    {
    }

    public City(Integer idCity)
    {
        this.idCity = idCity;
    }

    public City(Integer idCity, String name)
    {
        this.idCity = idCity;
        this.name = name;
    }

    @Override
    public Integer getIdCity()
    {
        return idCity;
    }

    @Override
    public void setIdCity(Integer idCity)
    {
        this.idCity = idCity;
    }

    @Override
    public String getName()
    {
        return name;
    }

    @Override
    public void setName(String name)
    {
        this.name = name;
    }

    @Override
    public ICountry getCountryId()
    {
        return countryId;
    }

    @Override
    public void setCountryId(ICountry countryId)
    {
        this.countryId = (Country) countryId;

    }

    @Override
    public int hashCode()
    {
        int hash = 0;
        hash += (idCity != null ? idCity.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object)
    {
        // TODO: Warning - this method won't work in the case the id fields are
        // not set
        if (!(object instanceof City))
        {
            return false;
        }
        City other = (City) object;
        if ((this.idCity == null && other.idCity != null) || (this.idCity != null && !this.idCity.equals(other.idCity)))
        {
            return false;
        }
        return true;
    }

    @Override
    public String toString()
    {
        return "com.neology.ebreeder.model.entities.City[ idCity=" + idCity + " ]";
    }

}

正如您在实体中看到的那样,我有使用共享接口(interface)的 getter 和 setter,我认为这可能会引发问题,我想使用实体覆盖 getter,但我无法覆盖 setter。

我不能这样做:

 @Override
    public Country getCountryId()
    {
        return countryId;
    }

但是我不能这样做:

@Override
    public void setCountryId(Country countryId)
    {
        this.countryId = (Country) countryId;

    }

你有没有更好的解决方案或者你能给我你的观点:)

谢谢

最佳答案

根据过去的经验,我认为使用 DTO 模型和 JPA 模型之间共享的接口(interface)不是一个好主意。

您实际上是通过这种方法将 DTO 模型与 JPA 模型紧密耦合。

我宁愿让它们松散耦合,并使用单独的框架在这​​两个模型之间进行复制。这将需要由元模型(可以从 JPA 派生)提供支持,以根据 getter 和 setter 将数据从一个模型复制到另一个模型。

关于java - 实现相同接口(interface)的 DTO 和实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30743649/

相关文章:

android - 未找到 Android SDK。尝试设置 ANDROID_SDK_ROOT 环境变量

java - 通过合并自定义 HTTP header 支持每个浏览器多个 session

java - Spring Security - 授权服务器的主体与资源服务器不同

java - Android - 错误的第一个参数类型和 ' android.supportv4.app.Fragment'

java - 将所有微服务的 Swagger 集中在一个地方

java - 谁在 Spring MVC 中设置请求内容类型

java - 运行时错误解决办法

java - 如何将现有的 SOAP 请求发送到现有的 WSDL

java - 如何延迟 Eclipse 错误警告

java - 如何在Android中创建 'Always on top overlay'