Repository 24.00
Het Repository-patroon in webforJ biedt een gestandaardiseerde manier om collecties van entiteiten te beheren en op te vragen. Het fungeert als een abstractielaag tussen je UI-componenten en gegevens, waardoor het eenvoudig is om met verschillende gegevensbronnen te werken terwijl je consistent gedrag behoudt.
Waarom een repository gebruiken
Repository elimineert handmatige updates terwijl je originele gegevens intact blijven:
// Zonder Repository - handmatige updates
List<Customer> customers = loadCustomers();
Table<Customer> table = new Table<>();
table.setItems(customers);
// Toevoegen vereist volledige herlaad
customers.add(newCustomer);
table.setItems(customers); // Moet alles opnieuw laden
// Met Repository - automatische synchronisatie
List<Customer> customers = loadCustomers();
CollectionRepository<Customer> repository = new CollectionRepository<>(customers);
Table<Customer> table = new Table<>();
table.setRepository(repository);
// Toevoegen synchroniseert automatisch
customers.add(newCustomer);
repository.commit(newCustomer); // Update alleen wat veranderd is
Collectie repository
De CollectionRepository is de meest gebruikelijke implementatie en omhult elke Java Collection:
// Van ArrayList
List<Customer> customers = new ArrayList<>();
CollectionRepository<Customer> customerRepo = new CollectionRepository<>(customers);
// Van HashSet
Set<String> tags = new HashSet<>();
CollectionRepository<String> tagRepo = new CollectionRepository<>(tags);
// Van elke Collection
Collection<Employee> employees = getEmployeesFromHR();
CollectionRepository<Employee> employeeRepo = new CollectionRepository<>(employees);
Gegevenssynchronisatie
De Repository fungeert als een brug tussen je gegevens en UI-componenten. Wanneer gegevens veranderen, stel je de repository op de hoogte via de commit()-methode:
List<Product> products = new ArrayList<>();
CollectionRepository<Product> repository = new CollectionRepository<>(products);
// Nieuwe product toevoegen
Product newProduct = new Product("P4", "Gizmo", 79.99, 15);
products.add(newProduct);
repository.commit(); // Alle verbonden componenten worden bijgewerkt
// Bestaande product bijwerken
products.get(0).setPrice(89.99);
repository.commit(products.get(0)); // Update alleen deze specifieke rij
// Product verwijderen
products.remove(2);
repository.commit(); // Vernieuwt de weergave
De commit-methode heeft twee handtekeningen:
commit()- vertelt de repository om alles te vernieuwen. Het activeert eenRepositoryCommitEventmet alle huidige gegevenscommit(entity)- richt zich op een specifieke entiteit. De repository vindt deze entiteit op basis van zijn sleutel en werkt alleen de aangetaste UI-elementen bij
Deze onderscheiding is belangrijk voor de prestaties. Wanneer je één veld bijwerkt in een tabel met 1000 rijen, werkt commit(entity) alleen dat vakje bij, terwijl commit() alle rijen zou vernieuwen.
Gegevens filteren
De filter van de repository bepaalt welke gegevens naar verbonden componenten stromen. Je onderliggende collectie blijft ongewijzigd omdat de filter als een lens fungeert:
// Filter op voorraadbeschikbaarheid
repository.setBaseFilter(product -> product.getStock() > 0);
// Filter op categorie
repository.setBaseFilter(product -> "Electronics".equals(product.getCategory()));
// Meerdere voorwaarden combineren
repository.setBaseFilter(product ->
product.getCategory().equals("Electronics") &&
product.getStock() > 0 &&
product.getPrice() < 100.0
);
// Filter wissen
repository.setBaseFilter(null);
Wanneer je een filter instelt, doet de Repository:
- Past de predicate toe op elk item in je collectie
- Maakt een gefilterde stroom van overeenkomende items
- Stelt verbonden componenten in kennis om hun weergave bij te werken
De filter blijft bestaan totdat je deze verandert. Nieuwe items die aan de collectie worden toegevoegd, worden automatisch getest tegen de huidige filter.
Werken met entiteit-sleutels
De repository moet entiteiten uniek kunnen identificeren om bewerkingen zoals find() en commit(entity) te ondersteunen. Er zijn twee manieren om te definiëren hoe entiteiten worden geïdentificeerd:
Gebruik van het HasEntityKey-interface
Implementeer HasEntityKey in je entiteitsklasse:
public class Customer implements HasEntityKey {
private String customerId;
private String name;
private String email;
@Override
public Object getEntityKey() {
return customerId;
}
// Constructor en getters/setters...
}
// Vind op sleutel
Optional<Customer> customer = repository.find("C001");
// Specifieke klant bijwerken
customer.ifPresent(c -> {
c.setEmail("newemail@example.com");
repository.commit(c); // Alleen deze klant's rij wordt bijgewerkt
});
Gebruik van aangepaste sleutelprovider 25.10
Voor entiteiten waarbij je HasEntityKey niet kunt of wilt implementeren (zoals JPA-entiteiten), gebruik setKeyProvider():
@Entity
public class Product {
@Id
private Long id;
private String name;
private double price;
// JPA-beheerde entiteit
}
// Configureer repository om de getId() methode te gebruiken
CollectionRepository<Product> repository = new CollectionRepository<>(products);
repository.setKeyProvider(Product::getId);
// Nu werkt vinden met de ID
Optional<Product> product = repository.find(123L);
Een aanpak kiezen
Beide benaderingen werken, maar setKeyProvider() heeft de voorkeur wanneer:
- Je werkt met JPA-entiteiten die
@Idvelden hebben - Je de entiteitsklasse niet kunt aanpassen
- Je verschillende sleutelstrategieën nodig hebt voor verschillende repositories
Gebruik HasEntityKey wanneer:
- Je de entiteitsklasse beheert
- De logica voor sleutelextractie complex is
- Je wilt dat de entiteit zijn eigen identiteit definieert
UI-integratie
Repository integreert met gegevensbewuste componenten:
// Maak repository en tabel
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("Naam", Customer::getName);
table.addColumn("E-mail", Customer::getEmail);
// Voeg gegevens toe - tabel wordt automatisch bijgewerkt
customers.add(new Customer("C001", "Alice Johnson", "alice@example.com"));
repository.commit();
Volgende stappen
📄️ Querying data
De QueryableRepository interface breidt Repository uit met geavanceerd opvragen via RepositoryCriteria. In tegenstelling tot basisrepositories die alleen eenvoudige filtering ondersteunen, bieden opvraagbare repositories gestructureerd opvragen met aangepaste filtertypes, sorteren en paginering.
📄️ Custom data sources
Wanneer je gegevens buiten je app hebt - in een REST API, database of externe service - moet je een aangepaste repository-implementatie maken. De DelegatingRepository klasse maakt dit eenvoudig door je in staat te stellen functies te bieden in plaats van een volledige klasse te implementeren.
📄️ Events and updates
Repository-evenementen stellen je in staat om te reageren op gegevenswijzigingen. Naast de automatische UI-updates, kun je luisteren naar veranderingen om aangepaste logica te activeren.