Ich lese Vernons Artikel Effective Aggregate Design. Und ich habe eine Frage darüber, warum nur eine Sammelinstanz pro Transaktion geändert wird?Warum ändert nur eine Aggregat-Instanz pro Transaktion?
Nehmen wir ein Beispiel, betrachten Sie eine Lagerverwaltungs-Geschichte.
Inventar repräsentiert einen Artikel mit Menge in einem Lagerhaus. 5 Implementing Domain Driven Design Bücher in Shanghai Lager zum Beispiel.
Der Eintrag steht für ein Protokoll über einen Ein-/Aus-Vorgang an einem Inventory. Eingeben 2 Implementing Domain Driven Design Bücher in Shanghai Lager zum Beispiel.
Ein Lagerbestand Die Menge muss geändert werden, wenn ein Eintrag eingereicht wird.
Es kommt mir in den Sinn, dies ist eine Invariente könnte durch transaktionale Konsistenz implementiert werden.
Lösung A: Unter Verwendung eines Aggregate und Cluster Eintrag in Inventar.
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);
}
}
Lösung B: Die Verwendung eigener Aggregate für Inventar und Eintrag.
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);
}
}
Sowohl A als auch B sind machbar, aber Lösung B ist eine Art unelegant für versehentliche oppertunity verlassen Inventar .Add (Anzahl) ohne Eintrag beteiligt aufzurufen. Ist das, was die Regel (ändert nur eine Aggregat-Instanz pro Transaktion) versucht, für mich zu zeigen? Ich bin meistens verwirrt, warum wir nur ein Aggregat in einer Transaktion ändern sollten, was schief geht, wenn wir das nicht tun.
Update1 starten
Ist es die Absicht, Concurrency Probleme zu lindern (mit einer anderen Regel "kleinere Aggregate machen")? Beispiel: Eintrag ist ein Aggregat mit relativ geringen Konflikten und Inventar ist einer mit relativ hoher Contotion (unter der Annahme, dass mehrere Benutzer einen Inventory manipulieren können), verursacht es unnötige Nebenläufigkeitsfehler, wenn ich sie beide in einer Transaktion ändern.
Update1 Ende
Einige weitere Probleme müssen angegangen werden, wenn ich die Lösung A annehmen:
1.Was passiert, wenn es viele Eintrag s für ein Inventar gibt und ich eine seitenbasierte Abfrage UI brauche? Wie implementiere ich eine ausgelagerte Abfrage mit Collections? Ein Weg ist, alle Eintrag s und wählt, was die Seite brauchen, die andere Möglichkeit ist InventoryRepository.findEntriesBy (Rechnungs-ID, Paging), aber dies scheint die Regel zu brechen eine lokale Entität nur zu bekommen, ist es aggregieren dann navigieren Sie die Objektgraph.
2.What, wenn es zu viele Eintrag s für ein Inventar und ich habe sie alle zu laden, wenn einen neuen Eintrag hinzufügen?
Ich weiß, dass diese Fragen aus mangelndem Verständnis stammen. Also jede Idee ist willkommen, danke im Voraus.
Ich denke, dass dieser Ansatz mildert auch die Chance, dass ein Riegelschloss auftreten kann http://stackoverflow.com/questions/735894/database-deadlocks –