Oggi ho imparato a fare le relazioni molti a molti con JPA.
E' abbastanza semplice. Ve lo spiego con un esempio.
Abbiamo due entità
- Book
- Author
Un libro puo' essere stato scritto da uno o piu' autori.
Un autore può aver scritto uno o piu' libri.
Per rendere la relazione basta usare @ManyToMany, nel nostro caso:
Book.java:
public class Book implements Serializable {
private Long id;
private List<Author> authors = new ArrayList<Author>();
protected String title;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="id")
public Long getId() {
return id;
}
@ManyToMany(cascade=CascadeType.PERSIST)
public List<Author> getAuthors() {
return authors;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public void setId(Long id) {
this.id = id;
}
public void setAuthors(List<Author> authors) {
this.authors = authors;
}
}
Author.java
@Entity
@Table(name="Autores")
public class Author implements Serializable {
private Long id;
protected String name;
private List<Book> books;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="id")
public Long getId() {
return id;
}
@ManyToMany(mappedBy = "authors")
public List<Book> getBooks() {
return books;
}
public String getName() {
return name;
}
public void setId(Long id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setBooks(List<Book> books) {
this.books = books;
}
}
Esempio di utilizzo:
EntityManager em = ...
Author author1 = new Author();
Author author2 = new Author();
Author author3 = new Author();
author1.setName("Pippo");
author1.setName("Pluto");
author1.setName("Paperino");
Book book1 = new Book();
book1.setTitle("Vivere a topolinia");
book1.getAuthors().add(author1);
book1.getAuthors().add(author2);
book1.getAuthors().add(author3);
Book book2 = new Book();
book2.setTitle("Vivere a Paperopoli");
book2.getAuthors().add(author3);
em.persist(book1);
em.persist(book2);
Nota sul mapping
Le relazioni molti a molti non possono essere espresse direttamente sui database relazionali, è infatti necessario introdurre una tabella che faccia da ponte. Nei casi semplici è possibile ignorare questi dettagli perché sono gestiti dal provider JPA.
Però nel caso la struttura del database sia già definita e necessario istruire JPA in modo che utilizzi la tabella ponte giusta. Questo si fa usando l'annotazione @JoinTable.
Per esempio nel caso la tabella ponte sia definita come:
CREATE TABLE "LIBROS_AUTORES" (
"libros_id" BIGINT NOT NULL,
"autores_id" BIGINT NOT NULL);
Useremo annoteremo getAuthors nel seguente modo:
@JoinTable(
name="LIBROS_AUTORES",
joinColumns=@JoinColumn(name="libros_id", referencedColumnName="id"),
inverseJoinColumns=@JoinColumn(name="autores_id",referencedColumnName="id")
)
public List<Author> getAuthors() {
return authors;
}