====== 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.