I have an aggregate root called Scene like below, I need to fetch all the active scene to do some business logic. I want to know where do I fetch these aggregates? Query repository? Or query database then use factory to build these aggregate roots? In my project, I use CQRS by using the same database.
public class Scene extends Entity {
private SceneId sceneId;
private ConditionId conditionId;
private Area area;
private Date startEffectTime;
private Date endEffectTime;
private boolean active;
...
public methods...
...
}
Related
i'm stuck with this problem while designing aggregates in a DDD project.
Please consider the following scenario:
public abstract class BaseAppType{
public abstract int GetUserOwnerId();
public List<AppTypeHost> Hosts {get;set;} = new List<AppTypeHost>()
}
public class PersonalAppType:BaseAppType //this is an aggregate root
{
public int override GetUserOwnerId(){ return Hosts.Select(h=>h.UserId).Single(); }
}
public class TeamAppType:BaseAppType //this is another aggregate root
{
publi int TeamOwnerId {get;set;}
public int override GetUserOwnerId(){ //this is much harder becase i don't have the info in the object }
}
public class Team {
public List<TeamMember> TeamMembers = new List<TeamMember>();
}
public class TeamMember {
public int TeamId {get;set;}
public int UserId {get;set;}
public TeamMemberRole Role {get;set;} //this might be either Owner or Member
}
So basically i've two types of appointments that share common info, functionality and shape via a root class.
Now i've to implement GetUserOwnerId in the two derived class, which are two distinct aggregates root.
In the PersonalAppType it is kind of easy because the information of the userOwner is within one of the entity of the aggregate so i simply query the object in memory and return it.
In the TeamAppType it is more diffuclt because the information is in another aggregate root ( basically for my business rules, the owner of the TeamAppType is the Owner of the Team AggregateRoot).
Since Team is another AggregateRoot i could not load it into the TeamAppType aggregate and i pretty stuck...
I've tried:
the route of injecting a service in the TeamAppType
so that i can call it within the GetUserOwnerId but i don't like it because it feel "wrong" to inject a service within a domain constructor and it is kind of hard because when i retrieve the aggregate root from ef core, it doesn't inject the service ( because it uses the default construcor with 0 params )
I've also tried the route of doing it in a domain service, something like this:
public class AppTypeOwnerResolverService{
public int GetUserOwnerId (BaseAppType appType)
{
switch (appType.GetType())
{
case "PersonalAppType":
//retrieve owener of PersonalAppType
break
case "TeamAppType":
//retrieve owener of TeamAppType
break
}
}
}
but it feels off because it looks like the GetUserOwnerId should stay within the inherited class and this reduces the benefits of polymorfism.
Do you have any suggestion on how to approach this problem?
Thanks to everyone for the help.
Another option would be to have a Team aggregate emitting domain events, (i.e. TeamOwnerAssigned) and having a domain event handler that modifies the TeamAppType aggregate based on this event.
In DDD, Entities have this concept of identity that uniquely identifies every instance regardless of all the other properties. Usually this identity has to be unique among the BC in which the Entity live, but there is an exception.
Sometimes we need to create Aggregates that are not only made by the root Entity and some Value Objects but have one or more child / nested Entities (that I understand to be called local Entities). For this kind of Entities the identity has only to be locally unique i.e. unique among the Aggregate boundaries.
Given this, let's also consider the fact that are two way to model a has-a relationship in DDD, depending on the actual business needs: separate Aggregates or Aggregate Root + child Entities.
In the first case the "child" Aggregate of the relation has a reference to the identity of the parent one, which in turn usually has a factory method to create and return an instance of the child:
class ForumId extends ValueObject
{
// let's say we have a random UUID here
// forum name is not a suitable identifier because it can be changed
}
// "parent" aggregate
class Forum extends AggregateRoot
{
private ForumId _forumId;
private string _name;
method startNewThread(ThreadId threadId, string title): Thread
{
// make some checks, maybe the title is not appropriate for this forum
// and needs to be rejected
...
// passing this forum's ID,
return new Thread(this->_forumId, threadId, title)
}
}
class ThreadId extends ValueObject
{
// let's say we have a random UUID here
// thread title is not a suitable identifier because it can be changed
}
// "child" aggregate
class Thread extends AggregateRoot
{
private ForumId _forumId;
private ThreadID _threadId;
private string _title;
}
If we consider instead the second case, let's say because for some business reason we need to have Thread as a local entity of Forum, what is the correct way to identify it? Should Thread still contain the ForumId of the parent Forum or it is redundant since it will only live inside that specific Forum and never accessed outside?
Which way is better and more importantly why? May the data model (i.e. the database level) steer the decision toward one way or another, or should we still ignore it as per good DDD design?
class Forum extends AggregateRoot
{
private ForumId _forumId;
private string _name;
private List<Thread> _threads;
method startNewThread(string title): ThreadId
{
// or use and injected `ThreadIdentityService`'s `nextThreadId(ForumId)` method
var threadId = this.generateNextLocalThreadId()
var newThread = new Thread(/*this->_forumId, */ threadId, title)
this._threads.append(newThread)
return threadId
}
}
// "child" aggregate - case 1
class Thread extends LocalEntity
{
private ForumId _forumId;
private ThreadID _threadId;
private string _title;
}
// "child" aggregate - case 2
class Thread extends LocalEntity
{
private ThreadID _threadId;
private string _title;
}
So the main purpose of having an aggregate is to make any change to this aggregate atomic.
The aggregate root contains the full child entity inside, for example Forum would have a collection of Threads.
Since the Thread is already inside a Forum wouldn’t make any sense having ForumId inside since the repository in charge of saving it would already know that id because we’d save the whole forum not a single thread.
Also wanted to add that Forum aggregate seems to be a huge aggregate, that implies some trade offs that you should take into account.
I'm having trouble writing a query using JPQL. I have two entities with a many-to-many relationship:
Entity1 (User)
#Entity
public class User implements Serializable {
#Id
private long id;
private String name;
#ManyToMany()
#JoinTable(name="users_roles",
joinColumns=#JoinColumn(name="user_id"),
inverseJoinColumns=#JoinColumn(name="role_id"))
private Set<Role> roles;
}
Entity2 (Role)
#Entity
public class Role implements Serializable {
#Id
private long id;
private String name;
}
Imagine that I have a list of roles that can vary in size (e.g. "roleA", "roleB", "roleC", ...), and I want to get every user that has every role in this list. In my head, it would be something like this:
select u from users u where :roles member of u.roles
As far as I know this doesn't work because :roles can't be a collection when used at the left hand side of "member of". Is there a way to achieve this in one JPQL query? If it is not possible in a single query, then what would be the best approach?
Thanks
Try this:
select u FROM User u JOIN u.roles r WHERE r IN (:roles)
I'm reading Vernon's article Effective Aggregate Design. And I have a question about why modifies only one aggregate instance per transaction?
Let's take an example, consider a Warehouse invertory management story.
Inventory represents an item with quantity in a warehouse. 5 Implementing Domain Driven Design books in Shanghai warehouse for instance.
Entry represents a log about an in/out operation on an Inventory. Entering 2 Implementing Domain Driven Design books in Shanghai warehouse for instance.
An Inventory's quantity need to be changed if an Entry is submitted.
It easily comes to my mind, this is an invarient could be implemented by transactional consistency.
Solution A: Using one Aggregate and cluster Entry into Inventory.
public class Inventory implements Aggregate<Inventory> {
private InventoryIdentity id;
private Sku sku;
private int quantity;
private List<Entry> entries;
public void add(Entry entry) {
this.quantity += entry.getQuantity();
this.entries.add(entry);
}
}
public class Entry implements LocalEntity<Entry> {
private int quantity;
// some other attributes such as whenSubmitted
}
public class TransactionalInventoryAdminService impelments InventoryAdminService, ApplicationService {
#Override
#Transactional
public void handle(InventoryIdentity inventoryId, int entryQuantity, ...other entry attributes)
Inventory inventory = inventoryRepository.findBy(inventoryId);
Entry entry = inventory.newEntry(entryQuantity, ..);
inventory.add(entry);
inventoryRepository.store(inventory);
}
}
Solution B: Using seperate Aggregate for Inventory and Entry.
public class Inventory implements Aggregate<Inventory> {
private InventoryIdentity id;
private Sku sku;
private int quantity;
public void add(int quantity) {
this.quantity += quantity;
}
}
public class Entry implements LocalEntity<Entry> {
private Inventory inventory;
private int quantity;
private boolean handled = false;
// some other attributes such as whenSubmitted
public void handle() {
if (handled) {
throw .....
} else {
this.inverntory.add(quantity);
this.handled = true;
}
}
}
public class TransactionalInventoryAdminService impelments InventoryAdminService, ApplicationService {
#Override
#Transactional
public void handle(InventoryIdentity inventoryId, int entryQuantity, ...other entry attributes)
Inventory inventory = inventoryRepository.findBy(inventoryId);
Entry entry = inventory.newEntry(entryQuantity, ..);
entry.handle();
inventoryRepository.store(inventory);
entryRepository.store(entry);
}
}
Both A and B are feasible, but solution B is kind of inelegant for leaving inadvertent oppertunity to invoke Inventory.add(quantity) without Entry involved. Is this what the rule (Modifies only one aggregate instance per transaction) tries to point out for me? I'm confused mostly why we should modify only one aggregate in a transaction, what goes wrong if we don't.
Update1 start
Is it intend to alleviate concurrency problems (with another rule of "make smaller aggregates")? For example, Entry is an Aggregate with relatively low contention and Inventory is one with relatively high contetion (assuming that multiple user could manipulate one Inventory), it causes unnecessary concurrency failure if I modify them both in a transaction .
Update1 end
Some further problems need to be addressed if I adopt solution A:
1.What if there are many Entry s for an Inventory and I need a paged query UI? How to implement a paged query using Collections? One way is to load all Entry s and picks what the page need, the other way is InventoryRepository.findEntriesBy(invoiceId, paging), but this seems to break the rule of get an local entity only by get it's aggreate then navigate the object graph.
2.What if there are too many Entry s for an Inventory and I have to load all of them when add an new Entry?
I know these questions stem from lacking full understanding. So any idea is welcome, thanks in advance.
Rule of thumb is to keep your aggregates small, since you want to avoid transactional failures due to concurrency. And why would we make the memory footprint big if it shouldn't be?
So, solution A is not optimal. Big aggregates often introduce problems that easily can be avoided.
It's true that another rule of thumb is to only change one aggregate in one transaction. If you make Entry it's own aggregate, you can make the inventory's quantity eventual consistent, meaning the Entry aggregate could raise an event to which the inventory is subscribed. This way you're only changing one aggregate per transaction.
public class Entry {
public Entry(InventoryId inventoryId, int quantity) {
DomainEvents.Raise(new EntryAdded(inventoryId, quantity))
}
}
If you don't feel comfortable with eventual consistency, you can still keep the aggregates separate, but modify them both in one transaction for now - until you're feeling the pain, using an encapsulating domain service. Another option is to keep the domain events in process, so that they're also committed in a single transaction.
public class InventoryService {
public void AddEntryToInventory(Entry entry) {
// Modify Inventory quantity
// Add Entry
}
}
One of the reason you should avoid modifying multiple aggregates in single transaction is that each aggregate may be stored in different db storage and may require some specific transaction handling or impose all the difficulty of managing distributed transactions (two-phase commit etc).
The better approach is eventual consistency along with events and saga pattern.
See also: https://softwareengineering.stackexchange.com/questions/356106/ddd-why-is-it-a-bad-practice-to-update-multiple-aggregate-roots-per-transaction
I need to display a large table with about 1300 roles at one time. (I know I should use a data scroll but my users want to see the whole table at one time.) The table displays 4 columns. Two of those columns are from the object but the other two are from referenced objects in the original object. I need to find the best/efficient way to do this. I currently have this working but when I reload the table it give an out of memory error. I think that it's caused by the large amount of redundant data in memory.
Create a view object that the repository will fill in only the needed fields.
Any other suggestions.
Here are the objects:
public class Database extends EntityObject {
private Long id;
private String name;
private String connectionString;
private String username;
private String password;
private String description;
// getter and setters omitted
}
public class Application extends EntityObject {
private Long id;
private String name;
private String fullName = "";
private String description;
private Database database;
private List<Role> roles = new ArrayList<Role>(0);
// getter and setters omitted
}
public class Role extends EntityObject {
private Long id;
private String name;
private String nameOnDatabase;
private Application application;
// getter and setters omitted
}
What I need displayed from the list of Roles is:
role.id, role.name, role.application.name, role.application.database.name
To optimize wisely, define what are you going to do with data, view or/and edit. Here are some common scenarios:
Retrieval using lazy fetch type.
Mark your roles in application with FetchType.LAZY annotation.
Retrieval using multiselect query. Create your custom class (like DTO) and populate it with data from the database using multiselect query. (Similar to VIEW mapped as Entity)
There are also other possibilities, such as Shared (L2) Entity Cache or Retrieval by Refresh.
See if you are using EntityManager correctly reading Am I supposed to call EntityManager.clear() often to avoid memory leaks?.