Skip to content

Implement Automatic DTO Mapping Feature... #3618

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Mouon opened this issue Sep 21, 2024 · 3 comments
Closed

Implement Automatic DTO Mapping Feature... #3618

Mouon opened this issue Sep 21, 2024 · 3 comments
Labels
status: duplicate A duplicate of another issue

Comments

@Mouon
Copy link

Mouon commented Sep 21, 2024

Implement Automatic DTO Mapping Feature

I am leaving an issue to learn from great people 🙏🏻 🙏🏻 🙏🏻

Issue

Implement Automatic DTO Mapping Feature
Description:
We need a feature to automatically convert entity lists obtained from @query into DTOs. The goal is to add logic that uses reflection to automatically map values from entity fields to DTO fields with the same names.
Objectives:

Implement a method for automatic mapping from entities to DTOs
Use reflection for field mapping Handle exceptions for mapping failures

Sample Code:

import ...

public class AutoMapper {
    @Nullable
    public static <D, E> D mapEntityToDto(Class<D> dtoClass, @Nullable E entity,
                                          MappingContext<? extends PersistentEntity<?, ?>, ? extends PersistentProperty<?>> mappingContext) throws Exception {
        Assert.notNull(dtoClass, "DTO class must not be null");
        Assert.notNull(mappingContext, "MappingContext must not be null");
        
        if (entity == null) {
            return null;
        }
        
        Constructor<D> constructor = dtoClass.getConstructor();
        D dtoInstance = constructor.newInstance();
        
        PersistentEntity<?, ?> persistentEntity = mappingContext.getPersistentEntity(entity.getClass());
        if (persistentEntity instanceof JpaPersistentEntity) {
            JpaPersistentEntity<?> jpaPersistentEntity = (JpaPersistentEntity<?>) persistentEntity;
            for (JpaPersistentProperty property : jpaPersistentEntity) {
                String propertyName = property.getName();
                Field dtoField = ReflectionUtils.findField(dtoClass, propertyName);
                if (dtoField != null) {
                    ReflectionUtils.makeAccessible(dtoField);
                    Object value = property.getGetter().invoke(entity);
                    ReflectionUtils.setField(dtoField, dtoInstance, value);
                }
            }
        }
        
        return dtoInstance;
    }
}

Benefits

Simplifies mapping process

Can be used with @query annotations, e.g.

@Query("SELECT new com.server.dto.gitHubIssue.GithubIssueListResponse$GithubIssue")

Note for Reviewers

I'm new to this and would greatly appreciate any guidance or suggestions for improvement. Thank you for your time and expertise! 🙏🏻

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Sep 21, 2024
@mp911de mp911de added the theme: projections Refinements around DTO and interface projections label Sep 23, 2024
@mp911de
Copy link
Member

mp911de commented Sep 23, 2024

For the time being, you can already use constructor expressions in your query. Meanwhile, we have a similar ticket in the issue tracker with #3076 to rewrite String-based queries into Constructor expressions so that the underlying JPA provider instantiates your class through a constructor.

That way, the constructed type maintains its integrity. In contrast, creating an empty object instance and populating its fields violates the principle of an integer object. At what state does the object become valid/usable and how do you even verify that state?

This specific concern addresses a class of potential bugs that we can eliminate by not introducing partially populated objects.

@Mouon
Copy link
Author

Mouon commented Sep 23, 2024

For the time being, you can already use constructor expressions in your query. Meanwhile, we have a similar ticket in the issue tracker with #3076 to rewrite String-based queries into Constructor expressions so that the underlying JPA provider instantiates your class through a constructor.

That way, the constructed type maintains its integrity. In contrast, creating an empty object instance and populating its fields violates the principle of an integer object. At what state does the object become valid/usable and how do you even verify that state?

This specific concern addresses a class of potential bugs that we can eliminate by not introducing partially populated objects.

Hello, mp911de,

Thank you for your comment! I agree that constructor expressions can currently be used. However, if an automatic DTO mapping feature is provided, we can add logic to verify that field names and types match, which would help prevent mapping failures.

A key point here is that the default behavior should be to create objects through the constructor and fill all fields. This will help maintain the integrity of the object.

Additionally, since there are already issues with partially populated objects being created in JPQL, I believe that an automatic DTO mapping feature could address this problem. If automatic mapping is implemented, users will be able to safely create objects using constructors that contain all fields of the DTO.

In this regard, could the automatic DTO mapping feature contribute to solving existing problems? I would also like to express that my main goal is to learn from your valuable experience and knowledge, mp911de.

(Instead of simply suggesting an opinion, my intention is more to gain insights from your expertise.)

@mp911de
Copy link
Member

mp911de commented Sep 23, 2024

an automatic DTO mapping feature is provided, we can add logic to verify that field names and types match, which would help prevent mapping failures.

I think that is doable in the course of #3076

A key point here is that the default behavior should be to create objects through the constructor and fill all fields. This will help maintain the integrity of the object.

That's the goal of the mentioned ticket.

Thanks for your response. Looking at your request and the thoughts behind it, I would close this ticket as duplicate of #3076.

@mp911de mp911de closed this as not planned Won't fix, can't repro, duplicate, stale Sep 23, 2024
@mp911de mp911de added status: duplicate A duplicate of another issue and removed status: waiting-for-triage An issue we've not yet triaged theme: projections Refinements around DTO and interface projections labels Sep 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: duplicate A duplicate of another issue
Projects
None yet
Development

No branches or pull requests

3 participants