Capa de Persistencia (Dao)
Esta capa es responsable de la comunicación directa con la base de datos. En el ecosistema Spring, se utiliza comúnmante MyBatis para mapear las consultas SQL. La interfaz debe estar anotada para que el framework pueda vincularla con su archivo de configuración XML corerspondiente.
Annotation @Mapper
Se coloca sobre la interfaz del repositorio. Su función es indicar al contenedor que busque el archivo XML asociado para ejecutar las sentencias SQL definidas.
@Mapper
public interface InventoryMapper {
Articulo selectById(Long id);
}
Capa de Servicio (Service)
La capa de servicio contiene la lógica de negocio. Aquí se inyectan los componentes de la capa Dao y se coordinan las operaciones antes de devolver los resultados al controlador.
Annotations Principales
@Service: Identifica la clase como un bean de servicio, permitiendo su registro automático en el contexto de Spring.
@Resource / @Autowired: Se utilizan para inyectar dependencias, como el mapper de la capa Dao.
@Service
public class InventoryService {
@Resource
private InventoryMapper inventoryMapper;
public Articulo obtenerDetalle(Long id) {
return inventoryMapper.selectById(id);
}
}
Sobrescritura vs. Sobrecarga
Es fundamental distinguir entre estos dos conceptos en Java:
- @Override (Sobrescritura): Ocurre cuando una subclase redefine un método existente en su superclase. La firma del método (nombre y parámetros) debe ser idéntica. Métodos privados, estáticos o constructores no pueden ser sobrescritos.
- Overload (Sobrecarga): Implica definir múltiples métodos con el mismo nombre dentro de una misma clase, pero con diferentes listas de parámetros (tipo o cantidad). El tipo de retorno no es suficiente para diferenciar una sobrecarga.
Manipulación de Colecciones con Stream API
Java Stream permite procesar secuencias de elementos de manera funcional. A continuación se muestran operaciones comunes sobre listas de objetos.
Transformación a Lista
Se puede filtrar y transformar datos antes de colectarlos en una nueva lista.
List<String> nombresProcesados = listaArticulos.stream()
.map(Articulo::getNombre)
.map(String::toUpperCase)
.collect(Collectors.toList());
Conversión a Mapa
Para crear un mapa donde la clave sea el ID y el valor el nombre del artículo.
Map<Long, String> mapaInventario = listaArticulos.stream()
.collect(Collectors.toMap(
Articulo::getId,
Articulo::getNombre,
(existente, nuevo) -> existente
));
El tercer parámetro maneja la colisión de claves, decidiendo qué valor prevalece.
Agrupación de Datos
Clasificar elementos según una categoría específica.
Map<String, List<Articulo>> porCategoria = listaArticulos.stream()
.collect(Collectors.groupingBy(Articulo::getCategoria));
Unión de Cadenas
Concatenar valores de una colección en un único string separados por un delimitador.
String codigosUnidos = listaArticulos.stream()
.map(Articulo::getCodigo)
.collect(Collectors.joining(";"));
Filtrado y Conteo
Ignorar valores nulos antes de realizar operaciones de unión o contar elementos.
long cantidadValida = listaArticulos.stream()
.filter(a -> a.getPrecio() != null)
.count();
Capa de Controlador (Controller)
Esta capa expone los endpoints HTTP. Recibe las solicitudes, invoca los servicios correspondientes y formatea la respuesta para el cliente.
@RestController
@RequestMapping("/api/inventario")
public class InventoryController {
@Resource
private InventoryService inventoryService;
@GetMapping("/detalle/{id}")
public ResponseEntity<String> getDetalle(@PathVariable Long id) {
Articulo item = inventoryService.obtenerDetalle(id);
return ResponseEntity.ok("Detalle: " + item.toString());
}
}
- @RestController: Combina @Controller y @ResponseBody para indicar que la clase maneja requests web y devuelve datos directamente.
- @RequestMapping / @GetMapping: Definen la URI de acceso al método.
Tareas Programadas (Spring Task)
Spring Boot permite ejecutar métodos periódicamente utilizando la anotación @Scheduled. Por defecto, el ejecutor es de un solo hilo, lo cual puede bloquear otras tareas si el proceso es largo.
Configuración Inicial
Se debe habilitar la programación en la clase principal de la aplicación.
@EnableScheduling
@SpringBootApplication
public class AplicacionPrincipal {
public static void main(String[] args) {
SpringApplication.run(AplicacionPrincipal.class, args);
}
}
Definición del Job
Se crea un componente con el método anotado y la expresión Cron correspondiente.
@Component
public class LimpiezaDiaria {
@Scheduled(cron = "0 0 3 * * ?")
public void ejecutarLimpieza() {
System.out.println("Ejecutando mantenimiento nocturno...");
}
}
Expresión Cron
La configuración sigue el orden: Segundo, Minuto, Hora, Día del mes, Mes, Día de la semana. El carácter '*' indica cualquier valor permitido en ese campo. Para proyectos que requieran concurrencia en las tareas, es necesario configurar un ThreadPoolTaskScheduler personalizado en la configuración de Spring.