Skip to main content

Overview

The Database Access Tutorial uses a flexible configuration system based on config.ini files and Java Properties API to manage database connections. This approach allows switching between different database systems (HSQLDB and H2) without modifying the source code.

Configuration File Structure

The config.ini file stores database connection parameters using a simple key-value format:
#Configuracion de la base de datos
driverH2=h2
driverHSQLDB=hsqldb
nameDB=SA
The configuration file is automatically created if it doesn’t exist, using default values for quick setup.

Basic Configuration Implementation

The DB_Enterprise.java class demonstrates the fundamental configuration pattern:
DB_Enterprise.java:22-48
File f = new File("config.ini");
Properties properties = new Properties();

/* Si existe nuestro fichero config.ini cargaremos nuestro archivo y lo cargaremos en nuestra
  base de datos */
if (!f.exists()) {
    /* Si nuestro archivo no existe lo creamos 
    añadiendo dos propeiedades para cada driver que usaremos */

    properties.setProperty("driverH2", "h2");
    properties.setProperty("driverHSQLDB", "hsqldb");

    /* Añadimos otros 2 setProperty para poner 
    en el nombre de la base de datos */
    properties.setProperty("nameDB", "SA");

    /* Almacenamos las propiedades a un archivo config.ini para usarlo despues para aplicar las configuraciones */
    properties.store(new FileOutputStream("config.ini"), "Configuracion de la base de datos");
    
} else {
     
     /* Almacenamos en variables las propiedades de nuestro archivo de configuracion externo */
     properties.load(new FileInputStream(f));
     driverHSQLDB = properties.getProperty("driverHSQLDB");
     driverH2 = properties.getProperty("driverH2");
     nameDB = properties.getProperty("nameDB");
}

HSQLDB Configuration

The HSQLDB implementation in DB_EnterpriseHSQLDB.java uses a more sophisticated configuration approach with dynamic path resolution:
DB_EnterpriseHSQLDB.java:26-42
private static void cargarConfiguracion() throws IOException {
    File configFile = new File("config.ini");
    Properties properties = new Properties();
    
    if (!configFile.exists()) {
        // Crear configuración por defecto
        properties.setProperty("database.path", "./db_empresa");
        properties.store(new FileOutputStream(configFile), "Configuración HSQLDB");
        System.out.println("Archivo config.ini creado con ruta por defecto");
    }
    
    properties.load(new FileInputStream(configFile));
    String dbPath = properties.getProperty("database.path", "./db_empresa");
    URL = "jdbc:hsqldb:file:" + dbPath + ";shutdown=true;hsqldb.lock_file=false";
    
    System.out.println("Conectando a: " + URL);
}
  • shutdown=true: Ensures proper database shutdown when the connection closes
  • hsqldb.lock_file=false: Disables lock file creation (useful for development)
  • file: prefix: Specifies file-based storage (vs. in-memory)

H2 Database Configuration

The H2 implementation uses a simpler, hardcoded URL with specific H2 optimizations:
DB_EnterpriseH2.java:7-10
private static final String URL = "jdbc:h2:file:./db_empresa_h2;AUTO_SERVER=TRUE;DB_CLOSE_DELAY=-1";
private static final String USER = "SA";
private static final String PASSWORD = "";
  • AUTO_SERVER=TRUE: Allows multiple connections to the same database
  • DB_CLOSE_DELAY=-1: Keeps database open even when all connections close
  • file: prefix: Uses file-based storage instead of in-memory

Driver Loading

Both implementations explicitly load JDBC drivers before establishing connections:
Class.forName("org.hsqldb.jdbc.JDBCDriver");
Modern JDBC 4.0+ drivers support automatic loading, but explicit loading ensures compatibility with older Java versions.

Configuration Best Practices

Security

Never hardcode credentials in source code. Use external configuration files with proper file permissions.

Portability

Use relative paths (e.g., ./db_empresa) instead of absolute paths for better portability across environments.

Default Values

Always provide sensible defaults when configuration properties are missing using getProperty(key, defaultValue).

Error Handling

Wrap configuration loading in try-catch blocks to gracefully handle missing or malformed configuration files.

Comparison: HSQLDB vs H2

FeatureHSQLDBH2
ConfigurationDynamic from config.iniHardcoded constants
Lock FileDisabledDefault enabled
Multi-connectionManual setupAUTO_SERVER mode
Database PathConfigurableFixed relative path
ShutdownExplicit shutdown=trueClose delay control

Complete Configuration Example

Here’s a complete example showing initialization with configuration:
import java.io.*;
import java.sql.*;
import java.util.Properties;

public class DatabaseConfig {
    private static String URL;
    private static final String USER = "SA";
    private static final String PASSWORD = "";
    
    public static void main(String[] args) {
        try {
            Class.forName("org.hsqldb.jdbc.JDBCDriver");
            cargarConfiguracion();
            inicializarBaseDatos();
        } catch (Exception e) {
            System.out.println("Error: " + e.getMessage());
            e.printStackTrace();
        }
    }
    
    private static void cargarConfiguracion() throws IOException {
        File configFile = new File("config.ini");
        Properties properties = new Properties();
        
        if (!configFile.exists()) {
            properties.setProperty("database.path", "./db_empresa");
            properties.store(new FileOutputStream(configFile), 
                           "Database Configuration");
        }
        
        properties.load(new FileInputStream(configFile));
        String dbPath = properties.getProperty("database.path", "./db_empresa");
        URL = "jdbc:hsqldb:file:" + dbPath + ";shutdown=true;hsqldb.lock_file=false";
    }
    
    public static void inicializarBaseDatos() {
        try (Connection conn = DriverManager.getConnection(URL, USER, PASSWORD)) {
            DatabaseMetaData meta = conn.getMetaData();
            System.out.println("Connected to: " + meta.getDatabaseProductName());
        } catch (SQLException e) {
            System.out.println("Error: " + e.getMessage());
        }
    }
}

Next Steps

Now that you understand database configuration, explore:

Build docs developers (and LLMs) love