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!