Repositorio 24.00
El patrón Repositorio
en webforJ proporciona una forma estandarizada de gestionar y consultar colecciones de entidades. Actúa como una capa de abstracción entre tus componentes de UI y los datos, facilitando el trabajo con diferentes fuentes de datos mientras se mantiene un comportamiento consistente.
Por qué usar repositorio
Repositorio
elimina las actualizaciones manuales mientras mantiene tus datos originales intactos:
// Sin Repositorio - actualizaciones manuales
List<Customer> customers = loadCustomers();
Table<Customer> table = new Table<>();
table.setItems(customers);
// Agregar requiere recargar todo
customers.add(newCustomer);
table.setItems(customers); // Debe recargar todo
// Con Repositorio - sincronización automática
List<Customer> customers = loadCustomers();
CollectionRepository<Customer> repository = new CollectionRepository<>(customers);
Table<Customer> table = new Table<>();
table.setRepository(repository);
// Agregar se sincroniza automáticamente
customers.add(newCustomer);
repository.commit(newCustomer); // Solo actualiza lo que cambió
Repositorio de colección
El CollectionRepository
es la implementación más común y envuelve cualquier colección de Java:
// Desde ArrayList
List<Customer> customers = new ArrayList<>();
CollectionRepository<Customer> customerRepo = new CollectionRepository<>(customers);
// Desde HashSet
Set<String> tags = new HashSet<>();
CollectionRepository<String> tagRepo = new CollectionRepository<>(tags);
// Desde cualquier colección
Collection<Employee> employees = getEmployeesFromHR();
CollectionRepository<Employee> employeeRepo = new CollectionRepository<>(employees);
Sincronización de datos
El Repositorio
actúa como un puente entre tus datos y los componentes de UI. Cuando los datos cambian, notificas al repositorio a través del método commit()
:
List<Product> products = new ArrayList<>();
CollectionRepository<Product> repository = new CollectionRepository<>(products);
// Agregar nuevo producto
Product newProduct = new Product("P4", "Gizmo", 79.99, 15);
products.add(newProduct);
repository.commit(); // Todos los componentes conectados se actualizan
// Actualizar producto existente
products.get(0).setPrice(89.99);
repository.commit(products.get(0)); // Solo actualiza esta fila específica
// Eliminar producto
products.remove(2);
repository.commit(); // Refresca la vista
El método commit tiene dos firmas:
commit()
- Indica al repositorio que refresque todo. Dispara unRepositoryCommitEvent
con todos los datos actuales.commit(entity)
- Apunta a una entidad específica. El repositorio encuentra esta entidad por su clave y actualiza solo los elementos de UI afectados.
Esta distinción es importante para el rendimiento. Cuando actualizas un campo en una tabla de 1000 filas, commit(entity)
actualiza solo esa celda, mientras que commit()
refrescaría todas las filas.
Filtrar datos
El filtro del repositorio controla qué datos fluyen hacia los componentes conectados. Tu colección subyacente permanece sin cambios porque el filtro actúa como una lente:
// Filtrar por disponibilidad de stock
repository.setBaseFilter(product -> product.getStock() > 0);
// Filtrar por categoría
repository.setBaseFilter(product -> "Electrónica".equals(product.getCategory()));
// Combinar múltiples condiciones
repository.setBaseFilter(product ->
product.getCategory().equals("Electrónica") &&
product.getStock() > 0 &&
product.getPrice() < 100.0
);
// Borrar filtro
repository.setBaseFilter(null);
Cuando estableces un filtro, el Repositorio
:
- Aplica el predicado a cada elemento en tu colección.
- Crea un flujo filtrado de elementos que coinciden.
- Notifica a los componentes conectados para que actualicen su visualización.
El filtro persiste hasta que lo cambies. Los nuevos elementos añadidos a la colección se prueban automáticamente contra el filtro actual.
Trabajando con claves de entidad
Cuando tus entidades implementan HasEntityKey
, el repositorio puede encontrar y actualizar elementos específicos por su ID:
public class Customer implements HasEntityKey {
private String customerId;
private String name;
private String email;
@Override
public Object getEntityKey() {
return customerId;
}
// Constructor y getters/setters...
}
// Buscar por clave
Optional<Customer> customer = repository.find("C001");
// Actualizar cliente específico
customer.ifPresent(c -> {
c.setEmail("newemail@example.com");
repository.commit(c); // Solo se actualiza la fila de este cliente
});
Sin HasEntityKey
:
repository.find("C001")
no encontrará a tu cliente porque busca un objeto que sea igual a "C001".repository.commit(entity)
sigue funcionando, pero depende de la igualdad de objetos.- Los componentes de UI no pueden seleccionar elementos por ID, solo por referencia de objeto.
Integración de UI
Repositorio
se integra con componentes conscientes de los datos:
// Crear repositorio y tabla
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("Nombre", Customer::getName);
table.addColumn("Correo Electrónico", Customer::getEmail);
// Agregar datos - la tabla se actualiza automáticamente
customers.add(new Customer("C001", "Alice Johnson", "alice@example.com"));
repository.commit();
Próximos pasos
📄️ Querying data
La interfaz QueryableRepository extiende Repository con consultas avanzadas a través de RepositoryCriteria. A diferencia de los repositorios básicos que solo admiten filtrado simple, los repositorios consultables proporcionan consultas estructuradas con tipos de filtro personalizados, ordenamiento y paginación.
📄️ Custom data sources
Cuando tus datos están fuera de tu aplicación - en una API REST, base de datos o servicio externo - necesitas crear una implementación de repositorio personalizada. La clase DelegatingRepository hace esto sencillo al permitirte proporcionar funciones en lugar de implementar una clase completa.
📄️ Events and updates
Los eventos de Repository te permiten reaccionar a cambios de datos. Más allá de las actualizaciones automáticas de la UI, puedes escuchar cambios para disparar lógica personalizada.