====== 08 - Spring Boot ======
**Spring Boot** (visto en Programación) elimina el cableado a mano: el contenedor de ''IoC'' crea los objetos y los conecta. En la parte de datos, lo que este temario ha construido a mano se reduce a configuración y anotaciones. Sigue siendo **JDBC** por debajo: lo que cambia es quién crea y conecta las piezas.
===== 1. Conexión y pool =====
Desaparece la clase ''DbConnection''. Las credenciales viajan en el fichero de propiedades estándar y los componentes necesarios llegan como **dependencias**:
org.springframework.boot
spring-boot-starter-jdbc
org.mariadb.jdbc
mariadb-java-client
runtime
spring.datasource.url=jdbc:mariadb://localhost:3306/library
spring.datasource.username=library_user
spring.datasource.password=secret
Con esas propiedades, Spring Boot auto-configura un bean ''DataSource'' con **HikariCP** — el pool del tema 06 — e **inyecta** donde haga falta. Los ajustes del pool, cuando toca afinarlos, van en el mismo fichero:
spring.datasource.hikari.maximum-pool-size=10
===== 2. JdbcTemplate =====
El DAO inyecta ''JdbcTemplate'', que ejecuta SQL y mapea resultados sin gestionar conexiones ni ''PreparedStatement'' a mano (los abre y cierra contra el ''DataSource'' del pool):
@Repository
public class JdbcBookDao implements BookDao {
private final JdbcTemplate template;
private final SimpleJdbcInsert insertBook;
public JdbcBookDao(DataSource dataSource) {
this.template = new JdbcTemplate(dataSource);
this.insertBook = new SimpleJdbcInsert(dataSource)
.withTableName("book")
.usingGeneratedKeyColumns("id");
}
@Override
public Optional findById(long id) {
List books = template.query(
"SELECT id, title, price, publisher_id FROM book WHERE id = ?",
this::map, id);
return books.stream().findFirst();
}
@Override
public Book save(Book book) {
long id = insertBook.executeAndReturnKey(Map.of(
"title", book.title(),
"price", book.price(),
"publisher_id", book.publisherId())).longValue();
return new Book(id, book.title(), book.price(), book.publisherId());
}
private Book map(ResultSet resultSet, int rowNum) throws SQLException {
// el mismo mapeo del tema 05
}
}
^ Elemento ^ Función ^
| ''query'' / ''queryForObject'' | ''SELECT'' con un mapeador por fila |
| ''update'' | ''INSERT''/''UPDATE''/''DELETE''; devuelve filas afectadas |
| ''SimpleJdbcInsert'' | ''INSERT'' declarativo que devuelve la clave autogenerada |
| ''@Repository'' | Estereotipo de persistencia: el ''IoC'' registra el DAO como bean |
La interfaz ''BookDao'' no cambia: es el mismo patrón del tema 05 reescrito a la API de Spring.
===== 3. Transacciones =====
''@Transactional'' sustituye el bloque manual de ''setAutoCommit'', ''commit'' y ''rollback'':
@Transactional
public void publish(Book book, Author author) {
bookDao.save(book);
authorDao.save(book.id(), author);
}
El método completo se ejecuta dentro de una transacción: al terminar sin excepción se confirma (''commit''); si cualquier excepción sale del método, se deshace (''rollback'') automáticamente — por defecto ante excepciones ''unchecked''.
===== 4. Flyway en el arranque =====
Con ''flyway-core'' en el classpath y los scripts en ''db/migration'', Spring Boot ejecuta ''migrate'' automáticamente al arrancar, antes de servir la primera consulta: el flujo del tema 07 sin escribir nada en el ''main''. La ruta y el comportamiento se ajustan con las propiedades ''spring.flyway.*''.
===== 5. En las pruebas =====
Las pruebas de integración con **Testcontainers** (explicadas en Entornos) se simplifican igual: la anotación ''@ServiceConnection'' conecta la aplicación de prueba con el contenedor sin configurar la ''DataSource'' a mano:
@Testcontainers
@SpringBootTest
class ApplicationIntegrationTest {
@Container
@ServiceConnection
static MariaDBContainer> mariadb = new MariaDBContainer<>("mariadb:12.3");
}
Nada de esto introduce otro mecanismo de acceso: el ''DataSource'' es **HikariCP** con su pool, ''JdbcTemplate'' ejecuta sentencias parametrizadas, ''@Transactional'' usa las transacciones del propio JDBC y Flyway aplica scripts SQL puros. **JPA** y sus repositorios automáticos quedan para 2.º curso.