Это хороший способ пользователя dao при сборке dto в объект или нет?

У меня есть объект User, который имеет отношение к другим объектам (Order, Profile). Когда я собираю объект из dto и обратно, мне также нужно собрать объект order и profile.

Сущность пользователя:

@Table(name = "user_info")
@Entity
@Getter
@Setter
public class User implements Serializable {
    private static final long serialVersionUID = 1789771068899105277L;
    @Id
    @GeneratedValue
    @Column(name = "userId",columnDefinition = "BINARY(16)")
    private UUID userId ;
    @Column(name = "login", unique = true, length = 20)
    private String login;
    @Column(name = "userPassword", length = 100)
    private String password;
    @Column(name = "userEmail", unique = true, length = 320)
    private String userEmail;


    @OneToOne(mappedBy = "user", cascade = CascadeType.ALL,
            fetch = FetchType.LAZY, optional = false)
    private Profile profile;

    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
    private Set<Role> roles = new HashSet<>();

    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Order> orders = new ArrayList<>();

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        User user = (User) o;
        return Objects.equals(getUserId(), user.getUserId());
    }

    @Override
    public int hashCode() {
        return Objects.hash(getUserId());
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder("User{");
        sb.append("userId=").append(userId);
        sb.append(", login='").append(login).append(''');
        sb.append(", password='").append(password).append(''');
        sb.append(", userEmail="").append(userEmail).append("'');
        sb.append('}');
        return sb.toString();
    }
}




    @Override
    public int hashCode() {
        return Objects.hash(getId(), getUserAuthority());
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder("Role{");
        sb.append("id=").append(id);
        sb.append(", userAuthority='").append(userAuthority).append(''');
        sb.append(", user=").append(user);
        sb.append('}');
        return sb.toString();
    }
}

Например, если мне нужно преобразовать объект User в Dto, мне нужен ассемблер:

public interface Assembler <E,D>{
    D mergeAggregateIntoDto(E entity);
    E mergeDtoIntoAggregate(D dto);
}
@Service
public class UserAssembler implements Assembler<User, UserDto>{
    @Autowired
    private CarDao carDao;

    @Override
    public UserDto mergeAggregateIntoDto(User entity) {
      UserDto userDto = new UserDto();
      userDto.setUserId(entity.getUserId());
      userDto.setUserEmail(entity.getUserEmail());
      userDto.setLogin(entity.getLogin());
      userDto.setPassword(entity.getPassword());
      userDto.setProfile(mergeAggregateIntoDto(entity.getProfile()));
      userDto.setRoles(entity.getRoles().stream().map(this::mergeAggregateIntoDto).collect(Collectors.toSet()));
      userDto.setOrders(entity.getOrders().stream().map(this::mergeAggregateIntoDto).collect(Collectors.toList()));

      return userDto;
    }

    @Override
    public User mergeDtoIntoAggregate(UserDto dto) {
        User user = new User();
        Map<UUID,Car> uuidCarMap = getCars(dto);
        Profile profile = mergeDtoIntoAggregate(dto.getProfile());
        profile.setUser(user);
        user.setUserId(dto.getUserId());
        user.setUserEmail(dto.getUserEmail());
        user.setLogin(dto.getLogin());
        user.setPassword(dto.getPassword());
        user.setProfile(profile);
        user.setRoles(dto.getRoles().stream().map(roleDto->{
            Role role = mergeDtoIntoAggregate(roleDto);
            role.setUser(user);
            return role;
        }).collect(Collectors.toSet()));
        user.setOrders(dto.getOrders().stream().map(orderDto -> {
            Order order = mergeDtoIntoAggregate(orderDto);
            order.setUser(user);
            order.setCar(uuidCarMap.get(orderDto.getCarId()));
            return order;
        }).collect(Collectors.toList()));
        return user;
    }

    private Map<UUID, Car> getCars(UserDto userDto){
        List<UUID> carIds = userDto.getOrders().stream().map(OrderDto::getCarId).collect(Collectors.toList());
        List<Car> cars = carDao.findByIds(carIds);
        return cars.stream().collect(Collectors.toMap(Car::getCarId, Function.identity()));
    }

    private ProfileDto mergeAggregateIntoDto(Profile profile){
        ProfileDto profileDto = new ProfileDto();
        profileDto.setProfileId(profile.getProfileId());
        profileDto.setUserId(profile.getUser().getUserId());
        profileDto.setAccountBalance(profile.getAccountBalance());
        profileDto.setUserFirstName(profile.getUserFirstName());
        profileDto.setUserSurName(profile.getUserSurName());
        profileDto.setUserRegistrationDate(profile.getUserRegistrationDate());
        return profileDto;
    }
    private Profile mergeDtoIntoAggregate(ProfileDto profileDto){
        Profile profile = new Profile();
        profile.setProfileId(profileDto.getProfileId());
        profile.setAccountBalance(profileDto.getAccountBalance());
        profile.setUserFirstName(profileDto.getUserFirstName());
        profile.setUserSurName(profileDto.getUserSurName());
        profile.setUserRegistrationDate(profileDto.getUserRegistrationDate());
        return profile;
    }

    private RoleDto mergeAggregateIntoDto(Role role){
        RoleDto roleDto = new RoleDto();
        roleDto.setId(role.getId());
        roleDto.setUserAuthority(role.getUserAuthority());
        roleDto.setUserId(role.getUser().getUserId());
        return roleDto;
    }
    private Role mergeDtoIntoAggregate(RoleDto roleDto){
        Role role = new Role();
        role.setUserAuthority(roleDto.getUserAuthority());
        role.setId(roleDto.getId());
        return role;
    }
    private OrderDto mergeAggregateIntoDto(Order order){
        OrderDto orderDto = new OrderDto();
        orderDto.setOrderCost(order.getOrderCost());
        orderDto.setOrderDate(order.getOrderDate());
        orderDto.setOrderId(order.getOrderId());
        orderDto.setUserAddress(order.getUserAddress());
        orderDto.setUserDestination(order.getUserDestination());
        orderDto.setUserId(order.getUser().getUserId());
        orderDto.setCarId(order.getCar().getCarId());
        return orderDto;
    }
    private Order mergeDtoIntoAggregate(OrderDto orderDto){
        Order order = new Order();
        order.setOrderId(orderDto.getOrderId());
        order.setOrderCost(orderDto.getOrderCost());
        order.setUserAddress(orderDto.getUserAddress());
        order.setUserDestination(orderDto.getUserDestination());
        order.setOrderDate(orderDto.getOrderDate());
        return order;
    }

}

Итак, я использовал dao в ассемблере и хочу знать, могу ли я это сделать? Спасибо.

1 ответ
1

Взаимоотношения сущностей

Сначала вы можете нарисовать диаграмму ER для визуализации отношений сущностей. Диаграмма классов UML для Order мог бы сделать вот так:

,----------------.
|Order           |
|----------------|
|customer: User  |
|orderedAt : Date|
|items: Car[]    |
`----------------'

Связи:

  • заказ имеет только одного клиента типа User (заказывается)
  • заказ подан в конкретную дату типа Date (заказывается в)
  • в заказе может быть ноль, один или несколько элементов типа Car (есть позиции заказа)

Дизайн класса

Действительный заказ должен как минимум соответствовать двум является-отношения.

class Order {
    final Date orderedAt;
    final User customer;
    final List<Car> lineItems = new ArrayList<Car>();

    public Order(User customer, Date orderedAt) {
        this.orderedAt = orderedAt;
        this.customer = customer;
    }

    public Order(User customer) {
        this(customer, new Date());  // default: ordered today
    }

    public Address getInvoiceAddress() {
        return this.customer.getUserAddress();  // delegate to customer (user)
    }

    public Address getDeliveryAddress() {
        return this.customer.getDestinationAddress();  // delegate to customer (user)
    }

    public void addItem(Car item) {
        this.lineItems.add(item);
    }
}

Это показывает, что вы можете просто создать ордер, передав User объект. Другие атрибуты (например, адреса) могут быть получены от клиента или пользователя (делегирование).

Сопоставление: от DTO к Entity и наоборот

Для этого отображение есть много каркасы нравиться MapStruct, Бульдозер и т.п.

Вы также можете реализовать Шаблон адаптера себя, что здесь очень хорошо подходит.

Hibernate: это уже OR-mapper!

Спящий режим часто описывается как объектно-реляционный преобразователь (ИЛИ-картограф).

Потому что он отображает объектно-ориентированные структуры (выраженные в классах Java) на реляционные структуры данных (выраженные в таблицах базы данных) и обратно.

Тот факт, что вы используете JPA-аннотации @Entity а также @Table на классе описывает именно это отображение.

При правильном использовании Спящий режим а также JPA (и их аннотации), то вам не нужны дополнительные фреймворки сопоставления или сервисы сборки.

    Добавить комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *