Add bidirectional Genre relationship to Album entity

This commit extends the Album entity with bidirectional relationship
  management for the AlbumHasGenre join table, enabling many-to-many
  associations between albums and genres with convenient helper methods.

  Key enhancements:

  Relationship Mapping:
  - Added OneToMany relationship from Album to AlbumHasGenre
    * Bidirectional mapping with cascade ALL and orphan removal
    * Maintains collection of album-genre associations
    * Initialized as ArrayList to prevent null pointer exceptions
    * Follows the same pattern as albumArtists relationship

  Helper Methods for Genre Management:
  - addGenre(Genre genre):
    * Creates AlbumHasGenre join table entry
    * Sets bidirectional references to Album and Genre
    * Adds association to albumGenres collection
    * Simplifies adding genres to albums programmatically

  - removeGenre(Genre genre):
    * Removes association by comparing genre IDs
    * Safely handles null checks
    * Uses removeIf for clean collection manipulation
    * Maintains referential integrity

  - getGenres():
    * Convenience method to extract Genre list from join table
    * Uses Java streams for clean transformation
    * Maps AlbumHasGenre → Genre
    * Returns List<Genre> for easy consumption

  Collection Management:
  - Added getAlbumGenres() getter
    * Returns full List<AlbumHasGenre> for direct access
    * Useful for repository-level operations

  - Added setAlbumGenres() setter
    * Allows bulk replacement of genre associations
    * Required by JPA for entity hydration

  Benefits:
  - Enables navigating from Album to associated Genres
  - Simplifies genre association management in service layer
  - Cascade operations ensure join table entries are managed automatically
  - Orphan removal prevents orphaned join table entries
  - Consistent API with existing Artist relationship methods
  - Type-safe genre management through helper methods

  Pattern Consistency:
  This implementation mirrors the albumArtists relationship structure,
  providing a consistent API for managing both artist and genre associations
  on the Album entity. Both relationships use the same cascade and orphan
  removal strategies for reliable data integrity.

  🤖 Generated with [Claude Code](https://claude.com/claude-code)

  Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

  This commit message is ready to use in IntelliJ for the Album.java changes!
This commit is contained in:
Gustavo Henrique Santos Souza de Miranda 2025-12-07 23:31:07 -03:00
parent a102b24ecd
commit e51d5aa678
1 changed files with 41 additions and 0 deletions

View File

@ -41,6 +41,10 @@ public class Album {
@OneToMany(mappedBy = "album", cascade = CascadeType.ALL, orphanRemoval = true) @OneToMany(mappedBy = "album", cascade = CascadeType.ALL, orphanRemoval = true)
private List<AlbumHasArtist> albumArtists = new ArrayList<>(); private List<AlbumHasArtist> albumArtists = new ArrayList<>();
// Relacionamento ManyToMany com Genre através da tabela de junção
@OneToMany(mappedBy = "album", cascade = CascadeType.ALL, orphanRemoval = true)
private List<AlbumHasGenre> albumGenres = new ArrayList<>(); // ADICIONE ESSA LINHA
@Column(name = "created_at", nullable = false, updatable = false) @Column(name = "created_at", nullable = false, updatable = false)
private LocalDateTime createdAt; private LocalDateTime createdAt;
@ -81,6 +85,31 @@ public class Album {
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
// ========== ADICIONE ESSES MÉTODOS PARA GENRE ==========
// Métodos helper para Genre (ManyToMany)
public void addGenre(Genre genre) {
AlbumHasGenre albumHasGenre = new AlbumHasGenre();
albumHasGenre.setAlbum(this);
albumHasGenre.setGenre(genre);
albumGenres.add(albumHasGenre);
}
public void removeGenre(Genre genre) {
albumGenres.removeIf(ag ->
ag.getGenre() != null && ag.getGenre().getId().equals(genre.getId())
);
}
// Método conveniente para pegar os gêneros
public List<Genre> getGenres() {
return albumGenres.stream()
.map(AlbumHasGenre::getGenre)
.collect(Collectors.toList());
}
// ========== FIM DOS MÉTODOS DE GENRE ==========
// Getters and Setters // Getters and Setters
public Integer getId() { public Integer getId() {
return id; return id;
@ -154,6 +183,18 @@ public class Album {
this.albumArtists = albumArtists; this.albumArtists = albumArtists;
} }
// ========== ADICIONE ESSES GETTERS/SETTERS ==========
public List<AlbumHasGenre> getAlbumGenres() {
return albumGenres;
}
public void setAlbumGenres(List<AlbumHasGenre> albumGenres) {
this.albumGenres = albumGenres;
}
// ========== FIM DOS GETTERS/SETTERS DE GENRE ==========
public LocalDateTime getCreatedAt() { public LocalDateTime getCreatedAt() {
return createdAt; return createdAt;
} }