Estructura per al RestController
Podem estructurar el nostre RestController
de moltes maneres segons el nivell d’abstracció i modularitat que vullgam aplicar. Els més comuns són:
1️ Directament amb el Repository (@RestController
+ @Repository
)
- El
RestController
crida directament elsJpaRepository
, sense cap capa de servei. - Avantatges:
- Codi senzill i ràpid de desenvolupar.
- Menys classes i menys codi a mantenir.
- Inconvenients:
- Difícil d’ampliar si cal modificar la lògica de negoci.
- No permet reutilitzar la lògica de negoci en altres llocs.
- No separa clarament responsabilitats.
2️ Amb una Capa de Serveis (@Service
)
- El
RestController
crida unService
, que conté la lògica de negoci i després crida alRepository
. - Avantatges:
- Separa les responsabilitats: el
Controller
només rep les peticions, elService
s’encarrega de la lògica i elRepository
accedeix a la BD. - Fàcil de modificar o afegir nova lògica sense tocar el
Controller
.
- Separa les responsabilitats: el
- Inconvenients:
- Més classes, pot semblar sobreenginyeria si l’API és molt simple.
3️ Amb DTOs
(Data Transfer Objects)
- Com funciona? Utilitza DTOs per encapsular les dades que s’envien o reben a l’API, en lloc d’exposar directament les entitats JPA.
- Avantatges:
- Protegeix l’estructura interna de la BD (no exposem directament les entitats JPA).
- Evita problemes de Lazy Loading amb entitats relacionades.
- Permet personalitzar les respostes i no dependre de la BD.
- Inconvenients:
- Necessita classes addicionals (DTOs).
- Es requereix mapeig entre Entitats <-> DTOs (per exemple, amb MapStruct o manualment).
Esta és la millor opció per a projectes escalables:
- Utilitzar Capa de Servei + DTOs, perquè separa bé les responsabilitats i protegeix l’estructura de la BD.
Estructura Recomanada
- 1.- Repositoris (DAO)
CiutatRepository.java
ProvinciaRepository.java
PaisRepository.java
FranquiciaRepository.java
CiutatFranquiciaRepository.java
- 2️ Serveis (Business Logic)
CiutatService.java
ProvinciaService.java
PaisService.java
FranquiciaService.java
CiutatFranquiciaService.java
- 3️ DTOs
CiutatDTO.java
ProvinciaDTO.java
PaisDTO.java
FranquiciaDTO.java
CiutatFranquiciaDTO.java
- 4️ Controllers
CiutatController.java
ProvinciaController.java
PaisController.java
FranquiciaController.java
CiutatFranquiciaController.java
Exemple d’implementació
🔹 DTO per a Ciutat
public class CiutatDTO {
private Long id;
private String nom;
private int poblacio;
private String descripcio;
private String imatge;
private String nomProvincia; // Evitem retornar l’objecte complet
public CiutatDTO(Ciutat ciutat) {
this.id = ciutat.getId();
this.nom = ciutat.getNom();
this.poblacio = ciutat.getPoblacio();
this.descripcio = ciutat.getDescripcio();
this.imatge = ciutat.getImatge();
this.nomProvincia = ciutat.getProvincia().getNom();
}
// Getters i Setters...
}
- CiutatRepository (DAO)
@Repository public interface CiutatRepository extends JpaRepository<Ciutat, Long> { List<Ciutat> findByPoblacioGreaterThan(int poblacio); }
- CiutatService
@Service public class CiutatService { @Autowired private CiutatRepository ciutatRepository; public List<CiutatDTO> obtenirTotesLesCiutats() { List<Ciutat> ciutats = ciutatRepository.findAll(); return ciutats.stream().map(CiutatDTO::new).collect(Collectors.toList()); } public CiutatDTO obtenirCiutatPerId(Long id) { return ciutatRepository.findById(id) .map(CiutatDTO::new) .orElseThrow(() -> new RuntimeException("Ciutat no trobada")); } }
- CiutatController
@RestController @RequestMapping("/api/ciutats") public class CiutatController { @Autowired private CiutatService ciutatService; @GetMapping public List<CiutatDTO> obtenirTotes() { return ciutatService.obtenirTotesLesCiutats(); } @GetMapping("/{id}") public CiutatDTO obtenirPerId(@PathVariable Long id) { return ciutatService.obtenirCiutatPerId(id); } }
En definitiva:
- Si volem una API simple: Farem el
Controller
que cride directament elRepository
(opció 1). - Si volem modularitat i escalabilitat: Separa en Service + Repository (opció 2).
- Si vols protegir la BD i evitar problemes: Usa DTOs per encapsular les dades (opció 3).
Recomanació: Per a un projecte seriós i escalable, Capa de Servei + DTOs és la millor opció.