Repository 24.00
Das Repository
-Muster in webforJ bietet eine standardisierte Möglichkeit, Sammlungen von Entitäten zu verwalten und abzufragen. Es dient als Abstraktionsschicht zwischen Ihren UI-Komponenten und den Daten, wodurch es einfach wird, mit verschiedenen Datenquellen zu arbeiten, während ein konsistentes Verhalten aufrechterhalten wird.
Warum ein Repository verwenden
Repository
beseitigt manuelle Aktualisierungen, während Ihre ursprünglichen Daten intakt bleiben:
// Ohne Repository - manuelle Updates
List<Customer> customers = loadCustomers();
Table<Customer> table = new Table<>();
table.setItems(customers);
// Hinzufügen erfordert vollständiges Neuladen
customers.add(newCustomer);
table.setItems(customers); // Muss alles neu laden
// Mit Repository - automatische Synchronisation
List<Customer> customers = loadCustomers();
CollectionRepository<Customer> repository = new CollectionRepository<>(customers);
Table<Customer> table = new Table<>();
table.setRepository(repository);
// Hinzufügen synchronisiert automatisch
customers.add(newCustomer);
repository.commit(newCustomer); // Aktualisiert nur, was sich geändert hat
Sammlung-Repository
Die CollectionRepository
ist die häufigste Implementierung und umschließt jede Java-Sammlung:
// Von ArrayList
List<Customer> customers = new ArrayList<>();
CollectionRepository<Customer> customerRepo = new CollectionRepository<>(customers);
// Von HashSet
Set<String> tags = new HashSet<>();
CollectionRepository<String> tagRepo = new CollectionRepository<>(tags);
// Von jeder Sammlung
Collection<Employee> employees = getEmployeesFromHR();
CollectionRepository<Employee> employeeRepo = new CollectionRepository<>(employees);
Daten-Synchronisation
Das Repository
fungiert als Brücke zwischen Ihren Daten und den UI-Komponenten. Wenn sich die Daten ändern, benachrichtigen Sie das Repository über die commit()
-Methode:
List<Product> products = new ArrayList<>();
CollectionRepository<Product> repository = new CollectionRepository<>(products);
// Neues Produkt hinzufügen
Product newProduct = new Product("P4", "Gizmo", 79.99, 15);
products.add(newProduct);
repository.commit(); // Alle verbundenen Komponenten aktualisieren sich
// Vorhandenes Produkt aktualisieren
products.get(0).setPrice(89.99);
repository.commit(products.get(0)); // Aktualisiert nur diese spezielle Zeile
// Produkt entfernen
products.remove(2);
repository.commit(); // Aktualisiert die Ansicht
Die commit-Methode hat zwei Signaturen:
commit()
- Sagt dem Repository, dass alles aktualisiert werden soll. Es löst einRepositoryCommitEvent
mit allen aktuellen Daten auscommit(entity)
- Zielt auf eine spezifische Entität ab. Das Repository findet diese Entität anhand ihres Schlüssels und aktualisiert nur die betroffenen UI-Elemente
Dieser Unterschied ist wichtig für die Leistung. Wenn Sie ein Feld in einer 1000-Zeilen-Tabelle aktualisieren, aktualisiert commit(entity)
nur diese Zelle, während commit()
alle Zeilen neu laden würde.
Daten filtern
Der Filter des Repositories steuert, welche Daten an verbundene Komponenten fließen. Ihre zugrunde liegende Sammlung bleibt unverändert, da der Filter wie eine Linse fungiert:
// Nach Verfügbarkeit auf Lager filtern
repository.setBaseFilter(product -> product.getStock() > 0);
// Nach Kategorie filtern
repository.setBaseFilter(product -> "Electronics".equals(product.getCategory()));
// Mehrere Bedingungen kombinieren
repository.setBaseFilter(product ->
product.getCategory().equals("Electronics") &&
product.getStock() > 0 &&
product.getPrice() < 100.0
);
// Filter löschen
repository.setBaseFilter(null);
Wenn Sie einen Filter setzen, führt das Repository
:
- Wendet das Prädikat auf jedes Element in Ihrer Sammlung an
- Erstellt einen gefilterten Stream übereinstimmender Elemente
- Benachrichtigt verbundene Komponenten, ihre Anzeige zu aktualisieren
Der Filter bleibt bestehen, bis Sie ihn ändern. Neue Elemente, die zur Sammlung hinzugefügt werden, werden automatisch gegen den aktuellen Filter getestet.
Arbeiten mit Entitätsschlüsseln
Wenn Ihre Entitäten HasEntityKey
implementieren, kann das Repository spezifische Elemente anhand ihrer ID finden und aktualisieren:
public class Customer implements HasEntityKey {
private String customerId;
private String name;
private String email;
@Override
public Object getEntityKey() {
return customerId;
}
// Konstruktor und Getter/Setter...
}
// Nach Schlüssel suchen
Optional<Customer> customer = repository.find("C001");
// Bestimmten Kunden aktualisieren
customer.ifPresent(c -> {
c.setEmail("newemail@example.com");
repository.commit(c); // Nur diese Zeile des Kunden wird aktualisiert
});
Ohne HasEntityKey
:
repository.find("C001")
findet Ihren Kunden nicht, da es nach einem Objekt sucht, das "C001" entsprichtrepository.commit(entity)
funktioniert weiterhin, basiert jedoch auf der Objektgleichheit- UI-Komponenten können Elemente nicht nach ID, sondern nur nach Objektreferenz auswählen
UI-Integration
Repository
integriert sich mit datenbewussten Komponenten:
// Repository und Tabelle erstellen
List<Customer> customers = new ArrayList<>();
CollectionRepository<Customer> repository = new CollectionRepository<>(customers);
Table<Customer> table = new Table<>();
table.setRepository(repository);
table.addColumn("ID", Customer::getId);
table.addColumn("Name", Customer::getName);
table.addColumn("Email", Customer::getEmail);
// Daten hinzufügen - Tabelle aktualisiert sich automatisch
customers.add(new Customer("C001", "Alice Johnson", "alice@example.com"));
repository.commit();
Nächste Schritte
📄️ Querying data
Das QueryableRepository-Interface erweitert Repository mit erweiterten Abfragemöglichkeiten über RepositoryCriteria. Im Gegensatz zu einfachen Repositories, die nur grundlegendes Filtern unterstützen, bieten abfragefähige Repositories strukturierte Abfragen mit benutzerdefinierten Filtertypen, Sortierung und Pagination.
📄️ Custom data sources
Wenn Ihre Daten außerhalb Ihrer App - in einer REST-API, Datenbank oder externen Dienst - leben, müssen Sie eine benutzerdefinierte Repository-Implementierung erstellen. Die DelegatingRepository Klasse macht dies einfach, indem sie es Ihnen ermöglicht, Funktionen bereitzustellen, anstatt eine vollständige Klasse zu implementieren.
📄️ Events and updates
Repository-Ereignisse ermöglichen es Ihnen, auf Datenänderungen zu reagieren. Neben den automatischen UI-Updates können Sie Änderungen überwachen, um benutzerdefinierte Logik auszulösen.