Lavorando con Liferay ed il Service Builder vi sarà sicuramente capitato di dover gestire delle relazioni N-N; come sappiamo, all'interno del file service.xml
, è possibile utilizzare l'attributo mapping-table
per definire la relazione N-N demandando al Service Builder tutto il lavoro sporco.
Ciò significa che il codice generato dal Service Builder conterrà tutti i metodi per leggere e scrivere record nella tabella di join; non c'è nulla di magico in questo, semplicemente vengono utilizzate determinate classi che si occupano di tutto quanto.
Tuttavia potrebbe capitarvi di dover gestire una relazione N-N a mano, senza poter usare l'attributo mapping-table
e quindi potenzialmente perdendo tutti gli automatismi. Per fortuna non è così, se sai cosa fare; esiste infatti l'interfaccia TableMapper
che possiamo utilizzare direttamente senza problemi.
Supponiamo di dover gestire la relazione N-N tra autori e libri; all'interno del service.xml
avremo pertanto definito 3 entità:
Author
, con chiave primaria authorId
; Book
, con chiave primaria bookId
; Author_Book
, con chiave primaria composta da authorId
e bookId
.
Ovviamente il Service Builder ci mette già a disposizione tutti i metodi di base ma quello che vogliamo è avere un metodo che ci restituisca l'elenco degli autori a partire dal libro e l'elenco dei libri a partire dall'autore; infatti sebbene si possano definire dei finder all'interno dell'entità Author_Book
(findByAuthorId
e findByBookId
), questi restituiranno comunque una lista di oggetti Author_Book
e non una lista di Author
o di Book
.
Vediamo quindi come il TableMapper
possa aiutarci; apriamo quindi la classe AuthorLocalServiceImpl
e definiamo il seguente metodo:
public List<Autor> getBookAuthors(long bookId, int start, int end, OrderByComparator comparator)
throws SystemException {
TableMapper tableMapper = TableMapperFactory.getTableMapper(
Author_BookImpl.TABLE_NAME,
"authorId", "bookId",
authorPersistence, bookPersistence);
return tableMapper.getLeftBaseModels(bookId, start, end, comparator);
}
Come vedete è veramente semplicissimo; prima di tutto si ottiene un'istanza del TableMapper
attraverso la factory. I parametri della factory sono i seguenti:
- Nome della tabella di join (abbiamo già una bella costante);
- Nome della chiave primaria della tabella di sinistra della relazione N-N;
- Nome della chiave primaria della tabella di destra della relazione N-N;
- Classe di persistenza della tabella di sinistra della relazione N-N;
- Classe di persistenza della tabella di destra della relazione N-N.
A questo punto possiamo semplicemente invocare uno dei tanti metodi forniti da TableMapper
, per leggere o scrivere dati:
getLeftBaseModels
, restituisce l'elenco delle entità di sinistra associate allo specifico elemento di destra (ossia l'elenco degli autori in base al libro); getRightBaseModels
, restituisce l'elenco delle entità di destra associate allo specifico elemento di sinistra (ossia l'elenco dei libri in base all'autore); addTableMapping
, aggiunge un elemento alla relazione N-N; deleteTableMapping
, rimuove un elemento dalla relazione N-N; - ...
Chiaramente farete poi una cosa analoga nella classe BookLocalServiceImpl
, ma ve lo lascio come esercizio.
Ok, ditemi se non è una figata!