H2 database — prototipado
La capa de datos suele ser un elemento central en la arquitectura de una aplicación. No solo durante el desarrollo, cuando creas ejemplos y pruebas, puedes necesitar algo ligero. A veces, lo único que necesitas de la base de datos es poder configurarla y ejecutarla rápido sin complicaciones. Muchas veces ni siquiera necesitas una consola para acceder a los datos, sobre todo en tests automáticos/integración. Sin embargo, durante el prototipado del modelo de datos (inicialización JPA) o la creación de tests basados en columnas, me gusta ver qué hay dentro.
Al principio usaba bases standalone como MySQL u Oracle DB. No era agradable configurarlas cada vez en un entorno nuevo o pedirle a alguien que lo hiciera. Luego, al descubrir Docker, me pasé enseguida. Fue una bendición hasta cierto punto. Pero después me di cuenta de que no necesitaba tanto overhead para proyectos pequeños (aún no listos para producción) o demos. Desde entonces uso distintas bases en memoria como HSQLDB, Apache Derby, SQLite y H2 Database.
Solo recientemente descubrí que H2 Database tiene todo lo que necesito para prototipar y testear. Puedo configurarla casi al instante junto con Spring Boot añadiendo una dependencia al pom:
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.194</version>
</dependency>
Elijo el scope según lo que necesite. Compile — si quiero usar herramientas extra de la librería. Runtime para uso normal (prototipado). Finalmente, test — para tests de integración. Esto me da sensación de facilidad. No tengo que pensar en arrancar y configurar la base — al menos por ahora — porque Spring Boot se encarga (JPA starter).
Consola y modo en memoria
Además, H2 viene con una consola web. Usando Spring Boot (web y JPA starters) puedes activarla añadiendo spring.h2.console.enabled=true a tu application.properties. La consola web arrancará en el puerto por defecto bajo la ruta 'h2-console', por ejemplo http://localhost:8080/h2-console. Si tienes tus entidades listas, verás sus tablas auto-inicializadas en la instancia por defecto jdbc:h2:mem:testdb.
¿No usas Spring Boot? No hay problema, arrancar los servidores es tan fácil como ejecutar org.h2.tools.Server.main(). En un contexto servlet, org.h2.server.web.DbStarter también puede ser útil. Para más detalles revisa la documentación. Hay una sección avanzada sobre uso en otros frameworks/lenguajes (.NET). Una conexión manual junto con el arranque del servidor web en Java estándar sería así:
Connection connection = DriverManager.getConnection("jdbc:h2:mem:testdb", "sa", "");
Statement statement = connection.createStatement();
if(statement.execute("Select * from dual")) {
System.out.println("Successfully connected to the jdbc:h2:mem:testdb");
}
Server.startWebServer(connection);
Esto también debería abrir la consola en tu navegador en algún puerto aleatorio.
Modo servidor
Otro caso útil es conectar a la base desde fuera de la app, desde otro proceso/host. Normalmente es difícil porque la base corre en memoria. Por defecto, solo se accede desde la misma VM y class loader. Pero también puedes exponerla por TCP usando las herramientas de H2. Un bean de ejemplo en Spring para crear, arrancar y parar el server sería:
@Bean(initMethod = "start", destroyMethod = "stop")
public Server inMemoryH2DatabaseServer() throws SQLException {
return Server.createTcpServer("-tcp", "-tcpAllowOthers", "-tcpPort", "9090");
}
Ahora puedes acceder a la base en el puerto 9090, usando el driver jdbc (org.h2.Driver) en la ruta jdbc:h2:tcp://localhost:9090/mem:testdb. Así puedes conectar desde otra app, por ejemplo JMeter, para verificar datos o hacer pruebas de carga. Para usar la clase org.h2.tools.Server, necesitas la dependencia H2 con scope compile (por defecto). Esto es el Server Mode.
Modo embebido
Por último, también puedes configurar H2 en modo embebido. Así los datos se guardan en un archivo y persisten entre ejecuciones. En Spring Boot es sencillo — define la ruta del archivo en application.properties:
spring.datasource.url=jdbc:h2:./testdb
spring.jpa.hibernate.ddl-auto=update
Hay que usar spring.jpa.hibernate.ddl-auto=update para sobrescribir el valor por defecto create-drop. Incluso puedes combinar estos modos y usar uno para "producción" y otro para tests. Basta con crear un properties aparte en test/resources.
Eso sí, por bueno que suene, cualquier enfoque tiene ventajas y desventajas, así que siempre depende de la persona elegir la herramienta y decidir qué sacrificar a cambio (quizá nada, depende del caso). ¡Suerte!
