Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DTOs and entities which implements the same interface

I have the next maven projects:

  • project-model : I have JPA entities
  • project-rest : Spring data, spring rest based on spring boot
  • project-client : Jersey clients to consume the rest services
  • project-web : Only jsf web application
  • project-desktop : Java Fx desktop application
  • project-android : Mobile application which consumes my Rest web services.

I'm planing to remove the JPA entities from the project-model and place there only DTO's pojos and interfaces and place my JPA entities in the rest project in order to remove the jpa dependencies from the project-model. This is because I don't want to have JPA dependencies in the project-android, project-web and project-desktop.

I was thinking to follow the next schema:

   @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
   {}

And if I need to convert from Entities to DTO's use mapstruct or Selma.

But I'm not sure if this is the best practice because I have problems in my code like the next:

@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 + " ]";
    }

}

And as You can see in the entity I have getters and setters using the shared interface, and I think that It could provoke problems, I thought to override the getters using the entity but I can't override the setters.

I cant do this:

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

But I can't do this :

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

    }

Do you see a better solution or could you give me your point of view :)

thanks

like image 791
Alejandro Agapito Bautista Avatar asked Oct 24 '25 03:10

Alejandro Agapito Bautista


1 Answers

Based on past experience, I do not think it is a good idea to use an interface that is shared between the DTO model and the JPA model.

You are in essence tightly coupling your DTO model to your JPA model with this approach.

I would rather have them loosely coupled and use a separate framework to copy between these two models. This will need to be powered by a meta model (could be derived from JPA) to walk and copy the data from one model to another based on the getters and setters.

like image 51
codedabbler Avatar answered Oct 26 '25 17:10

codedabbler