Robert Strauch
Robert Strauch

Reputation: 12906

Mapping property names between DTO and entity for sorting in a Spring Pageable object

Description

Given a Spring Boot REST controller with a GET method:

Here is some basic code for illustration:

// User controller

public class UserController {

    UserRepository userRepository;

    @GetMapping("/users")
    public List<UserResponse> getUsers(Pageable pageable) {
        return userRepository.findAll(pageable).stream().map(UserMapper::toUserResponse);
    }
}

// User response

public class UserResponse {

    String userName;
}

// User entity

@Entity
public class UserEntity {

    String name;
}

Problem

A client would like to sort the results by the property name userName as defined in the UserResponse. As the corresponding field in the UserEntity is called name, the sorting does not work and results in an exception.

Questions

  1. Is it possible to perform some kind of mapping between the property names for sorting?
  2. I already use MapStruct which maps between the UserEntity and the UserResponse objects. Would it be possible to re-use this for the mapping of sort property names?

Upvotes: 1

Views: 207

Answers (3)

Alex
Alex

Reputation: 866

Just change change pageable to your own

final Pageable of = PageRequest.of(pageable.getPageNumber(), pageable.getPageSize(), Sort.by(pageable.getSort()
                .map(order -> order.getProperty().equals("name") ? new Order(order.getDirection(), "userName") : order)
                .toList()));
return userRepository.findAll(of).map(UserMapper::toUserResponse);

Upvotes: 0

Hocine KHEDDADJI
Hocine KHEDDADJI

Reputation: 1

try this, inside your UserMapper class :

@Mapping(source = "name", target = "userName")
UserResponse toUserResponse(UserEntity userEntity);

Upvotes: 0

Wladimir Diskowski
Wladimir Diskowski

Reputation: 650

You can use dynamic proxy:

Pageable proxyPageable = (Pageable) Proxy.newProxyInstance(
                this.getClass().getClassLoader(),
                new Class[] { Pageable.class },
                (proxy, method, methodArgs) -> {
                    if (method.getName().equals("getSort")) {
                        return Sort.by(
                        pageable.getSort().stream().map(order -> {
                            if (order.getProperty().equals("userName")) {
                                return new Sort.Order(order.getDirection(), "name");
                            }
                            return order;
                        }).toList());
                    } else {
                        return method.invoke(pageable, methodArgs);
                    }
                });

Upvotes: 0

Related Questions