Configuración HSQLDB "In Proccess Mode" en aplicación web con Spring + Hibernate.

...

Este artículo explica en dos simples pasos cómo configurar HSQLDB en modo "In process" en una aplicación web con Spring + Hibernate, leyendo un archivo SQL ubicado en el directorio de la aplicación para crear el modelo de datos necesario para la aplicación.

Introducción

HSQLDB nos ofrece una base de datos ligera y rápida que se basa en tablas manejadas en memoria y en disco que, además, puede ser embebida en una aplicación web para lograr una solución independiente de un servidor de base de datos externo, teniendo como ventajas transacciones más rápidas y seguras, simplificación del procedimiento de despligue y la posibilidad de realizar pruebas en local offline.

En este artículo, utilizaremos una clase java que será la encargada de crear la base de datos HSQLDB y las tablas (Si no fueron creadas) y, haciendo uso de spring, definiremos nuestra clase como un Bean con prioridad alta, de esta manera, la clase será inicializada antes que cualquier otro Bean. Por ultimo, configuraremos Spring e Hibernate para que la aplicación se conecte a la base de datos creada. 

Se puede descargar HSQLDB desde http://hsqldb.org/

Versiones pertinentes para este artículo: 

  • hsqldb-2.3.2.jar
  • sqltool.jar (Incluido al descargarse hsqldb)
  • Spring 3.1.1.RELEASE
  • Hibernate 4.1.9.FINAL 

Paso 1: HSQLDBSetup.java

Esta es la clase encargada de la creación del servidor de base de datos y creación de las tablas:

package com.myapp.hsqldb;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
import javax.annotation.PreDestroy;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hsqldb.Server;
import org.hsqldb.cmdline.SqlFile;
import org.hsqldb.cmdline.SqlToolError;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
/**
 * Clase de Setup de HSQLDB
 * @author Federico Luppi - http://www.microgestion.com
 */
@Component("HSQLDBSetup")
@Order(value=Ordered.HIGHEST_PRECEDENCE)
public class HSQLDBSetup {
	private final Log log = LogFactory.getLog(HSQLDBSetup.class);
	
	private Connection connection;
	private Server server;
	
	public HSQLDBSetup(){
		this.init();
	}
	
	/**
	 * Inicializacion de HSQLDB
	 */
	public void init(){
		this.loadProperties();
		log.info("Starting HSQLDB...");
		this.initializeServer();
	    try {
			Class.forName("org.hsqldb.jdbcDriver");
	    } catch (ClassNotFoundException e) {
	        e.printStackTrace(System.out);
	    }
	    try {
	        connection = DriverManager.getConnection("jdbc:hsqldb:hsql://localhost:1234/myDB","SA","");
	        if(!this.existsDataModel()){
	          	this.createDataModel();
	        }
	    } catch (SQLException e) {
	        e.printStackTrace(System.out);
		} catch (IOException e) {
			e.printStackTrace(System.out);
		} catch (SqlToolError e) {
			e.printStackTrace(System.out);
		}		
	}
	
	/**
	 * Antes de destruir el Bean. Se detiene la base de datos.
	 */
	@PreDestroy
	public void destroy() {
		log.info("Stoping HSQLDB");
		server.stop();
	}
	
	/**
	 * Instancia e inicia el servidor HSQLDB
	 */
	private void initializeServer(){
		server = new Server();
        server.setAddress("localhost");
        server.setDatabaseName(0, "myDB");
        server.setDatabasePath(0, "file:C:/HSQLDBs/db");
        server.setPort(1234);
        server.setTrace(true);
        server.start();
	}
	
	/**
	 * Ejecuta los scripts de creación de la DB
	 * @throws IOException
	 * @throws SQLException
	 * @throws SqlToolError
	 */
	private void createDataModel() throws IOException, SQLException, SqlToolError{
		log.info("Creating Data Model.");
		SqlFile sqlFile;
		File file;
		file = new File(getClass().getResource("/properties/HSQLDB-DataModel.SQL").getPath());
		if(!file.isFile()){
			throw new IOException("SQL File not found in " + file.getAbsolutePath());
		}
		sqlFile = new SqlFile(file);
		sqlFile.setConnection(connection);
		sqlFile.setContinueOnError(true);
		sqlFile.execute();
		log.info("Successfully created data model.");
		
	}
	
	/**
	 * Verifica si el modelo de datos ya esta creado o es necesario crearlo
	 * @return true si esta creado el modelo de datos, en caso contrario, devuelve false
	 */
	private boolean existsDataModel(){
		try{
			log.info("Checking if data base model is created.");
			connection.createStatement().executeQuery("Select USERNAME from APPUSER");
			log.info("Data model created.");
			return true;
		}catch(SQLException e){
			log.info("Data model not created.");
			return false;
		}
		
	}
}

A tener en cuenta

@Component es una anotación de spring que nos servirá para que el framework se encargue de su instanciación como java bean.

@Order(value=”Ordered.HIGHEST_PRECEDENCE”) indicará a Spring que este bean tiene la más alta prioridad para instanciarse, entonces, será instanciado antes que cualquier otro bean que no tenga esta prioridad. (Por default, todos los beans tienen LOWEST_PRECEDENCE). 

@PreDestroy Spring ejecturará el método indicado con esta anotación antes de destruir el bean. Es importante apagar el servidor de la base de datos, en caso contrario el servidor de aplicaciones podría dejar de responder.   

createDataModel()

En este método se llevará a cabo la creación de las tablas de la base de datos. El método lee un archivo SQL de un paquete “properties” que está ubicado en el src de la aplicación y lo ejecuta. De esta manera no hace falta especificar un path a algún disco, sino que la aplicación contará siempre con el archivo SQL. 

Nota: Si el modelo de datos se exportó de otro motor de base de datos, tener en cuenta que puede no funcionar debido a cuestiones de compatibilidad con el lenguaje. En mi caso en particular, exporté el modelo de datos desde MySQL, y pude resolver los problemas de compatibilidad ejecutando el siguiente comando al principio del archivo SQL: 

SET DATABASE SQL SYNTAX MYS TRUE;  

En el siguiente link se encuentran los comandos de compatibilidad y otras opciones que se pueden ejecutar en HSQLDB: http://hsqldb.org/doc/guid/dbproperties-chapt

Paso 2: ApplicationContext.xml

En este xml se configurará el DataSourcer correspondiente a la conexión con HSQLDB y la configuración del SessionFactory de Hibernate.

<bean id="dataSourceHSQL" class="org.apache.commons.dbcp.BasicDataSource">
  <property name="driverClassName" value="org.hsqldb.jdbcDriver" />
  <property name="url" value="jdbc:hsqldb:hsql://localhost:1234/myDB" />
  <property name="username" value="SA" />
  <property name="password" value="" />
  <property name="initialSize" value="1" />
  <property name="maxActive" value="5" />
  <property name="poolPreparedStatements" value="true" />
  <property name="maxOpenPreparedStatements" value="10" />
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
	<property name="dataSource" ref="dataSourceHSQL />
	<property name="configLocation" value="/WEB-INF/hibernate.cfg.xml"/>
	<property name="hibernateProperties">
		<value>
			hibernate.connection.autocommit=true
			hibernate.dialect=org.hibernate.dialect.HSQLDialect
			hibernate.cache.use_second_level_cache=false
		</value>
	</property>
</bean>

Completados estos pasos, hemos finalizado la configuración de la base de datos HSQLDB y de la aplicación web. Sólo resta iniciar la aplicación y ver como se crea la base de datos y la aplicación se conecta a ella.

Se encuentra disponible para descargar la clase HSQLDBSetup.java


Modificado por última vez en Domingo, 21 Diciembre 2014 03:04

Acerca del autor

Federico Luppi

Federico cuenta con más de 4 años de experiencia en el desarrollo de aplicaciones Web bajo plataformas Java EE y 3 años de experiencia en el liderazgo de equipos de desarrollo. Actualmente se desempeña como Líder de Proyecto en el área de operaciones de MicroGestion Software.