私が取り組んでいるプロジェクトで CQRS を使用しようとしていますが、現在、CQRS のクエリ側を実装する最良の方法に苦労しています。私のやや限定的な理解に基づいて、データベースにクエリを実行し、アプリケーションの UI レイヤーで使用されるクエリ結果を含む DTO を返すシン データ レイヤー (シン リード レイヤーと呼ばれることもあります) があります。
これは私が開発しているJava EEアプリケーションであるため、シンデータレイヤーはJPAを使用してデータベースにクエリを実行し、これを使用しEntityManager.createNamedQuery
て結果を含むエンティティを返し、それをDTOにマッピングします。
アプリケーションのクエリ側が「読み取り専用」である必要がある場合、DTO には getter が含まれますが、各プロパティの setter は含まれず、作成時にプロパティを設定するために使用されるコンストラクターは含まれません。
単純なクエリの場合、コンストラクターを使用してエンティティの値を DTO に手動でマップできますが、これはより複雑なクエリでは実用的ではありません。特に、対応するエンティティにマップする必要がある「1 対多」の関係がエンティティに含まれている場合はそうです。 DTO。Dozer や ModelMapper などのマッピング フレームワークの使用を検討しましたが、それらはすべて DTO のセッターに依存しているようで、コンストラクターを使用していないようです。
次のコードは、状況を説明するために作成した 2 つのエンティティと 2 つの 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
}
私の質問は次のとおりです。
CQRS を使用する場合、DTO にはゲッターとコンストラクターのみが必要ですか、それともセッターも使用できますか?
DTO が理想的にはゲッターとコンストラクターのみを持つ必要がある場合、マッピング フレームワークは、エンティティが "1 対多" の関係を含む複雑な結果セットを返す DTO を設定するための最良の方法ですか?
セッターではなくコンストラクターを使用できるマッピング フレームワークはありますか?