I've been struggling with this issue for a while. Let's say you have a business application that has a rich domain and in one of the front-end views you show a list of open Orders
. In this view you show things like that orderDate, customerName, totalAmount,... but the client also wants to see how many items are in the order (basically the count of OrderItems entity). What is the best way to handle this?
Assumptions
- The
Order
class has aList<OrderItem>
which is fetched lazily - Each ResponseDTO object only contains its core properties and any properties from
@ManyToOne
associations (soCustomer
would be included when fetching anOrder
Solution 1
You can do a rest call for the Order
resource by calling /api/orders
, you'll get a response with the core properties and the customer data. For each order you'll have to do a new fetch to /api/orders/<id>/items
. This is basically an N+1 problem with many HTTP calls.
Solution 2
I change my initial assumption and eagerly fetch collections and immediately include the OrderItems
in the ResponseDTO. The question then becomes, am I going to eagerly fetch each collection of each entity? This seems like a serious performance issue. In this solution the front end would only need to make 1 call.
Solution 3
Initial assumptions are in play, so I lazily fetch collections but I move the N+1 problem from the front-end to the back-end (so no extra HTTP calls), not really a solution but at least the expensive HTTP calls are weeded out.
Solution 4
In my rich domain model I add an attribute to the Order
entity called numberOfItems
. Whenever the method addOrderItem(OrderItem item)
is invoked on an Order
object, I increment the numberOfItems
attribute. It is stored in the database as well. This way I can have all my initial assumptions and use the ResponseDTO with only core properties and I only make 1 HTTP call. The issue I have with this solution is that many people say that you shouldn't store aggregate data like that in the database.
I realize there's no perfect solution and it always depends, but for the life of me I can't seem to find good discussions about this issue. When you google an issue like this you often find information about HATEOAS but that would fit in my Solution 1, which I don't think is really a solution.
If anyone can give an alternative solution or improve on any of the solutions I gave, it would be greatly appreciated.
NumberOfItems
goes to a new read-sideOrderReadModel
class but not to theOrder
entity.