TraxX
TraxX

Reputation: 382

Using a Single DTO object for projection

I'm having trouble about having to use a single DTO object or a DTO object for every Entity object. For example I have 3 classes: Book, Author and Publisher.

Book.java

@Entity
@Table(name = "tbl_book")
public class Book {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    @Column(name = "description")
    private String description;

    other different fields...
}

Author.java

@Entity
@Table(name = "tbl_author")
public class Book {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    @Column(name = "description")
    private String description;

    other different fields...
}

Publisher.java

@Entity
@Table(name = "tbl_publisher")
public class Book {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    @Column(name = "description")
    private String description;

    other different fields...
}

and MyDTO.java

public class MyDTO {
    private Long id;
    private String description;

    constructor id, description...
    getters and setters...
}

I want to select only specific fields (id and description) with EntityManager:

em.createQuery("SELECT NEW MyDTO(id,description) FROM Book");

But my question is should I use a single DTO object(which is MyDTO) for all projection? Something like:

em.createQuery("SELECT NEW MyDTO(id,description) FROM Author");
em.createQuery("SELECT NEW MyDTO(id,description) FROM Publisher");

Tutorials about using DTO for projection just saying use DTO for read and use Entity for write but they are not telling about having a single object DTO or not. Will you please provide an example why single DTO or why DTO for every Entity. Thank you!

Upvotes: 1

Views: 1804

Answers (2)

Veselin Davidov
Veselin Davidov

Reputation: 7081

In my opinion create a DTO for each field. Having a single DTO couples your objects a lot. For example if in Book class you change the description to something else all your code will not work anymore.

Even if you start with thinking of a good name for the DTO you will see the problem. "MyDTO" doesn't sounds good and doesn't show its purpose but you won't be able to think of a meaningful name.

And last but not least there is the single responsibility principle that is a good thing and having one DTO to present multiple objects kind of breaks it. It's not a good practice and breaks the SOLID principle to have one class that represents different types of objects. If your projects share some common properties it's better to have separate classes and create an Interface for the common part. That's just standard OOP design. It's not related to DTOs

That's just my opinion. I might be wrong.

Also creating the DTOs like that in the JPQL query kind of makes it hard coded and harder to maintain. You can do something like:

.setResultTransformer( Transformers.aliasToBean( PostDTO.class ) ) 

for your query or there are other ways to do it.

Upvotes: 1

HBo
HBo

Reputation: 633

I've been working with DTOs for a while now, and here's some things I can share:

  • Try building a DTO hierarchy based on your needs (abstract classes and/or interfaces)
  • Even if your BookDTO 'just' extends a superclass (AbstractIdDescriptionDTO for instance), it's always more readable (IMO), and it's less tedious to maintain, and you can't misinterpret an object for another
  • I never use the new DTO syntax, I implemented an automatic converter instead

Upvotes: 2

Related Questions