Question

I am fairly new to DDD. I've seen a number of example projects that use a generic AggregateId (with a String containing a GUID) as a key for an aggregate root.

I was wondering how to refer to the aggregateRoot from a child in a OneToMany relationship.

Say there is a Order AggregateRoot and a OrderLine. Would it be wise to have an extra generated (eg. sequence) id, next to the GUID, so the OrderLine can refer to that on database level? Or is the foreign key of orderLine to order the GUID ? Are there performance implications?

eg.

BaseAggregateRoot:

@MappedSuperclass  
public abstract class BaseAggregateRoot {
    @EmbeddedId
    @AttributeOverrides({
       @AttributeOverride
       (name = "idValue", column = @Column(name = "aggregateId", nullable = false))
    })
    protected AggregateId aggregateId;
    ...

Order:

@Entity
public class Order extends BaseAggregateRoot{
    // is this ID necessary?
    @Id
    @GeneratedValue(generator = "OrderSequenceGenerator")
    @SequenceGenerator(name = "OrderSequenceGenerator", sequenceName = "ORD_SEQ1", allocationSize = 1)
    @Column(name = "ord_seq")
    private Long id;

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @JoinColumn(name = "aggregateId")  <-- should this point to ID or aggregateId?
    private List<OrderLine> orderLines;
Was it helpful?

Solution

First, I'd like to clarify that DDD is all about domain modeling and has nothing to do with how the domain is persisted. It might be persisted in a a database, but it might just as well be in a text file. From a domain modeling stand point it matters which (and how) entities are related with other entities, but generally not how they are related in a relational database. To wit, ask a sales rep. how an order line item can identify the order its part of and he'll ask you in return what's wrong with you.

Performance wise there are some risks involved in using GUIDs as keys. Randomly generated GUIDs are not suitable for clustered indices. It is best to use a sequential generational algorithm and have the database provide you with those GUIDs. Here is a link to a discussion on this topic:

What are the performance improvement of Sequential Guid over standard Guid?

I would advise you to read this answer in particular. I agree with Dan that having sequential GUIDs is missing the point.

Relationally speaking, it seems unnecessary and generally unwise to me to have two identifiers for the same record. I would advise you to pick one. So, if somehow you are stuck with GUIDs in your project. See if you can use them as keys by having them sequentially generated. Then you can remove your @Id Long id. If not, replace the @EmbeddedId with a @Column annotation.

Hope this helps,

Good luck

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top