2015-03-15 2 views
1

Я ищу, чтобы использовать CQRS в проекте, над которым я работаю, однако сейчас я изо всех сил стараюсь реализовать запрос CQRS. Основываясь на моем немного ограниченном понимании, есть тонкий слой данных (иногда называемый тонким слоем чтения), который запрашивает базу данных и возвращает DTO с результатами запроса, которые используются уровнем пользовательского интерфейса приложения.Сопоставление между сущностью JPA и DTO в CQRS

Поскольку это приложение Java EE, которое я разрабатываю, слой тонких данных использует JPA для запроса базы данных с использованием EntityManager.createNamedQuery, который возвращает объект, содержащий результаты, которые я затем сопоставляю с DTO.

Учитывая, что сторона запроса приложения должна быть «только для чтения», DTO содержит геттеры, но не устанавливает для каждого из свойств и конструктора, который используется для заполнения свойств при создании.

Для простого запроса я могу вручную сопоставить значения в объекте с DTO с помощью конструктора, однако это нецелесообразно для более сложных запросов, особенно если объект содержит отношения «один ко многим», которые необходимо быть сопоставлены с соответствующими DTO. Я рассмотрел использование фреймворков отображения, таких как Dozer и ModelMapper, однако все они полагаются на DTO с сеттерами и, похоже, не используют конструктор.

Следующий код представляет собой очень упрощенный вид двух объектов и двух DTO, которые я создал, чтобы помочь объяснить ситуацию.

@Entity 
@Table(name = "ORDER") 
public class Order { 

    // Various named queries 
    @Id 
    @Column(name = "ORDER_ID") 
    private UUID orderId; 

    @Column(name = "ORDER_NUMBER") 
    private long orderNumber; 

    @Column(name = "ORDER_DATE") 
    @Temporal(TemporalType.DATE) 
    private Date orderDate; 

    @Column(name = "CUSTOMER_NAME") 
    private String customerName; 

    @OneToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE }, orphanRemoval=true) 
    @JoinColumn(name = "ORDER_NUMBER", referencedColumnName = "ORDER_NUMBER") 
    private List<OrderLine> orderLines; 

    // Getters and setters, equals, hashCode, toString 

} 

@Entity 
@Table(name = "ORDER_LINE") 
public class OrderLine { 

    @Id 
    @Column(name = "ORDER_LINE_ID") 
    private UUID orderLineId; 

    @OneToOne(fetch=FetchType.EAGER) 
    @JoinColumn(name = "ORDER_ID", referencedColumnName = "ORDER_ID") 
    private Order order; 

    @Column(name = "PART_NUMBER") 
    private String partNumber; 

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

    @Column(name = "UNIT_PRICE") 
    private BigDecimal unitPrice; 

    @Column(name = "QUANTITY") 
    private int quantity; 

    // Getters and setters, equals, hashCode, toString 

} 

public class OrderDTO { 

    private long orderNumber; 
    private Date orderDate; 
    private String customerName; 
    private List<OrderLine> orderLines; 

    public OrderDTO() {} 

    public OrderDTO(long orderNumber, Date orderDate, String customerName, List<OrderLineDTO> orderLines) { 
    this.orderNumber = orderNumber; 
    this.orderDate = orderDate; 
    this.customerName = customerName; 
    this.orderLines = orderLines; 
    } 

    //Getters but no setters 

} 

public class OrderLineDTO { 

    private String partNumber; 
    private String description; 
    private BigDecimal unitPrice; 
    private int quantity; 

    public OrderLineDTO() {} 

    public OrderLineDTO(String partNumber, String description, BigDecimal unitPrice, int quantity) { 
    this.partNumber = partNumber; 
    this.description = description; 
    this.unitPrice = unitPrice; 
    this.quantity = quantity; 
    } 

    //Getters but no setters 

} 

Мои вопросы:

  1. При использовании CQRS должны в DTOS только добытчиками и конструктор или это приемлемо иметь сеттеры, а?

  2. Если DTOS в идеале должен только добытчики и конструктор, является основой отображения лучшим способом для заполнения DTOs где объект возвращаемых сложный результирующего набор, содержащий «один-ко-многим» отношения?

  3. Есть ли какие-либо рамки отображения, которые могут использовать конструктор, а не , чем сеттеры?

ответ

2
  1. Лучший способ иметь только добытчиками и конструктор. Тогда ваши DTO неизменны.
  2. Вы можете производить DTO двумя способами. Один из них - использование JPA и запросов, таких как select new my_package.MyDto(u.username, u.email) from User u. Второй, который более популярен для больших dtos, включая множество результатов таблицы, - использовать технологию non-jpa, такую ​​как MyBatis или SpringJdbcTemplate. Второй способ имеет больше смысла, потому что вы не извлекаете ненужные данные из базы данных. Поэтому по причинам производительности вы должны получить только данные, необходимые для создания DTO.
  3. Да - например, самый популярный JacksonMapper может использовать конструкторы вместо сеттеров. Другие структуры, такие как Orika, также могут создавать такое отображение. Вы можете найти подробную информацию в своем блоге - http://www.kubrynski.com/2015/02/datatransferobject-myth-busting.html

 Смежные вопросы

  • Нет связанных вопросов^_^