Question

I have two aggregates Parent and Child, say. A Parent can have many Childs (Children). A Child can only belong to one Parent.

I need to keep track of a sort order of the Child entities so that when you get the Child entities for a Parent the list is in that order.

The obvious database schema is the following:

enter image description here

However, an invariant of the model needs to be that this order is well defined. So if you have a method on Child, Child.SetOrdinal(int) say, then this invariant is not protected (there is nothing stopping you setting two Childs to ordinal 3). I don't want to pull it all together into one large aggregate.

The alternative I see is a database like the following: enter image description here

Where I have introduced a link table to store the relationship and order, this would be inside the Parent aggregate, where the invariant could be protected. This does add complexity to the database however.

Is there another way, or is the first, simpler version not that bad?

Was it helpful?

Solution

When Adopting the first approach, your model probably looks like this(Assuming Parent and Child are AggregateRoot s):

public Class Parent {
    private Long id;
}

public Class Child {
    private Long id;
    private Long parentId; // most orm need this field.
}

Then you can use childRepository.findBy(parentId): List<Child> to retrieve all children belonging to a Parent and use parentRepository.findBy(child.getParentId()):Parent to retrieve a child's Parent. But this is not your case since you said "However, an invariant of the model needs to be that this order is well defined". This leads to another approach: Parent and Child as AggregateRoot and a ValueObject to keep the relationships:

public Class Parent {
    private Long id;
    private List<LineChild> children;
}

public class LineChild {
    private int ordinal;
    private Long childId;
}

public Class Child {
    private Long id;
}

But in my expirences, most orm doesn't support this (the second db schema is used instead). Some "half orm tool" can help, like iBATIS.

<resultMap class="Parent">
    <property name="id" column="id" />
    <property name="children" column="id" select="findChilren"/>
</resultMap>

<select id="findChilren" parameterClass="long" resultMap="LineChild">
    select * from Child where parant_id = #parantId# order by ordinal
</select>

<resultMap id="LineChild" class="LineChild">
    <property name="ordinal" column="ordinal" />
    <property name="childId" column="id"/>
</resultMap>

But you lost all benefits from an orm framework, such as dynamic update and so on.

Or, consider eventual consistency?

last but quite confused, why "A Child can only belong to one Parent"? I have mom and dad! :P

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