La forma primaria di accesso ai dati in Java è senza dubbio JDBC, un'API creata per rendere platform-independent l'interazione con i RDBMS. Il suo utilizzo offre notevoli vantaggi in termini di performances e facilità di utilizzo, richiedendo per contro allo sviluppatore di farsi carico dell'intera gestione dei processi di accesso ai dati, ovvero:
- Richiesta della connessione al datasource
- Creazione del PreparedStatement e valorizzazione dei parametri
- Esecuzione del PreparedStatement
- Estrazione dei risultati dal ResultSet (in caso di interrogazioni)
- Gestione delle eccezioni
- Chiusura della connessione
Se per applicazioni di piccole dimensioni queste "complicazioni" possono essere accettabili, sicuramente provocano dei grossi disagi in ambito enterprise, dove nel corso degli anni sono sorti appositi framework che, astraendo JDBC, tendono a semplificare questi aspetti. In questo ambito si colloca Spring JDBC.
JDBC Template
Spring offre diverse possibilità per la persistenza dei dati mediante JDBC, la principale delle quali è l'utilizzo della classe JDBCTemplate
.
Questa classe implementa l'intero processo di accesso ai dati attraverso template methods, rendendo possibile la personalizzazione di tutte le fasi di tale processo mediante l'ovverride dei metodi specifici.
Vediamo ora attraverso degli snippet di codice come eseguire operazioni sul Database mediante JDBCTemplate.
Iniziamo con la creazione dell'implementazione specifica per JDBC del BookDao
visto nella precedente lezione. Come è possibile notare dal codice, questo possiede un riferimento alla classe JDBCTemplate
, inizializzata attraverso il metodo setDataSource()
che provvede a fornire il DataSource necessario.
public class BookJdbcDao implements BookDao {
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
// ...
}
Operazioni di Update
Attraverso il metodo update
è possibile eseguire tutte quelle operazioni che comportano una modifica dei dati nel database.
public class BookJdbcDao implements BookDao {
// ...
//Inserimento
public void insert(Book book)
{
jdbcTemplate.update("insert into books (isbn, autore, titolo) values (?, ?, ?)",
new Object[] { book.getIsbn(), book.getAutore(), book.getTitolo() });
}
//Modifica
public void update(Book book)
{
jdbcTemplate.update("update books set autore = ?, titolo = ? where isbn = ?",
new Object[] { book.getIsbn(), book.getAutore(), book.getTitolo() });
}
// Eliminazione
public void delete(String isbn)
{
jdbcTemplate.update("delete from books where isbn = ?",
new Object[] { isbn });
}
}
Operazioni di Ricerca
Passando alle interrogazioni, il caso più semplice è la ricerca di un intero.
public class BookJdbcDao implements BookDao {
// ...
// Query di un intero
public int bookCount() {
int rowCount = jdbcTemplate.queryForInt("select count(1) from books");
return rowCount;
}
}
Passando alle interrogazioni di oggetti oltre alla query e i suoi parametri è necessario specificare come deve avvenire il mapping tra i risultati presenti nel ResultSet
e le proprietà dell'oggetto. Per fare questo si utilizza l'interfaccia RowMapper, nel nostro codice implementata dalla classe BookRowMapper
.
public class BookJdbcDao implements BookDao {
...
//Query di un singolo oggetto
public Book findByISBN(String isbn) {
Book book = (Book) jdbcTemplate.queryForObject("select * from books where isbn = ?",
new Object[] { isbn },
new BookRowMapper());
return book;
}
// Query di una lista
public List<Book> findAllBooks() {
List<Book> books = (List<Book>) jdbcTemplate.query("select * from books",
new BookRowMapper());
return books;
}
}
// Classe RowMapper
public class BookRowMapper implements RowMapper {
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
Book book= new Book();
book.setIsbn(rs.getString("isbn"));
book.setAutore(rs.getString("autore"));
book.setTitolo(rs.getString("titolo"));
return book;
}
}
Come possiamo notare la classe BookRowMapper
contiene le regole di mapping tra una riga del ResultSet e classe Book
ed è utilizzata dal jdbcTemplate per ritornare i valori della query.