Zum Hauptinhalt springen

Repository 24.00

In ChatGPT öffnen

Das Repository-Muster in webforJ bietet eine standardisierte Methode zum Verwalten und Abfragen von Sammlungen von Entitäten. Es fungiert als Abstraktionsschicht zwischen Ihren UI-Komponenten und Daten und erleichtert die Arbeit mit verschiedenen Datenquellen, während ein einheitliches Verhalten gewährleistet bleibt.

Warum das 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 das, was sich geändert hat

Collections-Repository

Das CollectionRepository ist die gebräuchlichste 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 Collection
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 Methode commit():

List<Product> products = new ArrayList<>();
CollectionRepository<Product> repository = new CollectionRepository<>(products);

// Neuen Produkt hinzufügen
Product newProduct = new Product("P4", "Gizmo", 79.99, 15);
products.add(newProduct);
repository.commit(); // Alle angeschlossenen Komponenten aktualisieren

// Bestehendes Produkt aktualisieren
products.get(0).setPrice(89.99);
repository.commit(products.get(0)); // Aktualisiert nur diese spezifische Zeile

// Produkt entfernen
products.remove(2);
repository.commit(); // Aktualisiert die Anzeige

Die commit-Methode hat zwei Signaturen:

  • commit() - Sagt dem Repository, dass alles aktualisiert werden soll. Es löst ein RepositoryCommitEvent mit allen aktuellen Daten aus
  • commit(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
Einzelfehler commitieren

Diese Unterscheidung ist für die Leistung wichtig. Wenn Sie ein Feld in einer Tabelle mit 1000 Zeilen aktualisieren, aktualisiert commit(entity) nur diese Zelle, während commit() alle Zeilen aktualisieren würde.

Daten filtern

Der Filter des Repositories steuert, welche Daten zu verbundenen Komponenten fließen. Ihre zugrunde liegende Sammlung bleibt unverändert, da der Filter als Linse fungiert:

// Nach Verfügbarkeit im 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 festlegen, führt das Repository:

  1. Wendet das Prädikat auf jedes Element in Ihrer Sammlung an
  2. Erstellt einen gefilterten Stream von übereinstimmenden Elementen
  3. Benachrichtigt angeschlossene 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

Das Repository muss Entitäten eindeutig identifizieren, um Operationen wie find() und commit(entity) zu unterstützen. Es gibt zwei Möglichkeiten zu definieren, wie Entitäten identifiziert werden:

Verwendung des HasEntityKey-Interfaces

Implementieren Sie HasEntityKey in Ihrer Entitätsklasse:

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");

// Besondere Kunden aktualisieren
customer.ifPresent(c -> {
c.setEmail("newemail@example.com");
repository.commit(c); // Nur diese Zeile des Kunden wird aktualisiert
});

Verwendung eines benutzerdefinierten Schlüsselproviders 25.10

Für Entitäten, bei denen Sie HasEntityKey nicht implementieren können oder wollen (wie JPA-Entitäten), verwenden Sie setKeyProvider():

@Entity
public class Product {
@Id
private Long id;
private String name;
private double price;

// JPA-gemanagte Entität
}

// Repository konfigurieren, um die Methode getId() zu verwenden
CollectionRepository<Product> repository = new CollectionRepository<>(products);
repository.setKeyProvider(Product::getId);

// Jetzt funktioniert die Suche mit der ID
Optional<Product> product = repository.find(123L);

Wahl eines Ansatzes

Beide Ansätze funktionieren, aber setKeyProvider() wird bevorzugt, wenn:

  • Mit JPA-Entitäten gearbeitet wird, die @Id-Felder haben
  • Sie die Entitätsklasse nicht ändern können
  • Sie unterschiedliche Schlüsselstrategien für verschiedene Repositories benötigen

Verwenden Sie HasEntityKey, wenn:

  • Sie die Entitätsklasse kontrollieren
  • Die Schlüsselextraktionslogik komplex ist
  • Sie möchten, dass die Entität ihre eigene Identität definiert

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