我希望在我正在开发的项目中使用CQRS,但是我目前正在努力实现CQRS的查询方面的最佳方法。基于我有限的理解,有一个瘦数据层(有时称为精简读取层),它查询数据库并返回一个DTO,其中包含应用程序UI层使用的查询结果。
由于这是一个Java EE应用程序,我正在开发瘦数据层使用JPA使用EntityManager.createNamedQuery
查询数据库,该@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
}
返回一个包含结果的实体,然后我将其映射到DTO。
鉴于应用程序的查询端应该是“只读”,DTO包含getter但不包含每个属性的setter,以及用于在创建时填充属性的构造函数。
对于一个简单的查询,我可以使用构造函数手动将实体中的值映射到DTO,但是这对于更复杂的查询是不实际的,特别是在实体包含需要的“一对多”关系的情况下映射到相应的DTO。我已经看过使用Dozer和ModelMapper之类的映射框架,但是它们似乎都依赖于具有setter的DTO,并且似乎没有使用构造函数。
以下代码代表了我创建的两个实体和两个DTO的非常简化的视图,以帮助解释这种情况。
{{1}}
我的问题是:
使用CQRS时,DTO应该只有getter和构造函数 或者也可以设置制定者?
如果理想情况下DTO应该只有getter和构造函数,那么是 映射框架填充实体所在DTO的最佳方法 返回一个包含“一对多”的复杂结果集 关系
是否有任何可以使用构造函数的映射框架 比定居者?
答案 0 :(得分:2)
select new my_package.MyDto(u.username, u.email) from User u
之类的查询。对于包括许多表结果的更大dtos更受欢迎的第二个是使用非jpa技术,如MyBatis或SpringJdbcTemplate。第二种方式更有意义,因为您没有从数据库中检索不必要的数据。因此,由于性能原因,您应该只获得创建DTO所需的数据。