Liquibase is a tool for managing and executing database changes.
—
This document covers Liquibase's multi-database abstraction layer, including the Database interface, factory system, and platform-specific implementations.
import liquibase.database.Database;
import liquibase.database.DatabaseFactory;
import liquibase.database.DatabaseConnection;
// Core database implementations
import liquibase.database.core.*;
// JDBC connection wrapper
import liquibase.database.jvm.JdbcConnection;
// Exception handling
import liquibase.exception.DatabaseException;
import liquibase.exception.LiquibaseException;
// Schema and catalog support
import liquibase.CatalogAndSchema;
import java.sql.Connection;
import java.util.List;The Database interface provides the core abstraction for all database implementations.
/**
* Check if this database implementation supports the given connection
* @param conn Database connection to check
* @return true if this implementation can handle the connection
*/
public boolean isCorrectDatabaseImplementation(DatabaseConnection conn) throws DatabaseException
/**
* Get the default JDBC driver for a given database URL
* @param url Database URL
* @return JDBC driver class name
*/
public String getDefaultDriver(String url)
/**
* Get the current database connection
* @return DatabaseConnection instance
*/
public DatabaseConnection getConnection()
/**
* Set the database connection
* @param conn DatabaseConnection to use
*/
public void setConnection(DatabaseConnection conn) throws DatabaseException/**
* Get the database product name
* @return Database product name (e.g., "PostgreSQL", "MySQL")
*/
public String getDatabaseProductName() throws DatabaseException
/**
* Get the database product version
* @return Database version string
*/
public String getDatabaseProductVersion() throws DatabaseException
/**
* Get short name for user selection
* @return Short database name (e.g., "postgresql", "mysql")
*/
public String getShortName()
/**
* Get formatted display name
* @return Display name for user interfaces
*/
public String getDisplayName()
/**
* Get default port for this database type
* @return Default port number, or null if not applicable
*/
public Integer getDefaultPort()/**
* Get the default catalog name
* @return Default catalog name
*/
public String getDefaultCatalogName() throws DatabaseException
/**
* Set the default catalog name
* @param catalogName Catalog name to use
*/
public void setDefaultCatalogName(String catalogName) throws DatabaseException
/**
* Get the default schema name
* @return Default schema name
*/
public String getDefaultSchemaName() throws DatabaseException
/**
* Set the default schema name
* @param schemaName Schema name to use
*/
public void setDefaultSchemaName(String schemaName) throws DatabaseException
/**
* Get catalog name for Liquibase objects
* @return Liquibase catalog name
*/
public String getLiquibaseCatalogName()
/**
* Get schema name for Liquibase objects
* @return Liquibase schema name
*/
public String getLiquibaseSchemaName()/**
* Check if database supports auto-increment columns
* @return true if auto-increment is supported
*/
public boolean supportsAutoIncrement()
/**
* Check if database supports sequences
* @return true if sequences are supported
* @deprecated Use supportsSequences() on specific database objects
*/
@Deprecated
public boolean supportsSequences()
/**
* Check if database supports initially deferred columns
* @return true if initially deferred is supported
*/
public boolean supportsInitiallyDeferrableColumns()
/**
* Check if database supports DROP TABLE CASCADE CONSTRAINTS
* @return true if cascade drop is supported
*/
public boolean supportsDropTableCascadeConstraints()
/**
* Check if database supports DDL in transactions
* @return true if DDL can be run in transactions
*/
public boolean supportsDDLInTransaction()/**
* Generate date literal for this database
* @param isoDate ISO date string
* @return Database-specific date literal
*/
public String getDateLiteral(String isoDate)
/**
* Get current datetime function for this database
* @return Function name/expression for current datetime
*/
public String getCurrentDateTimeFunction()
/**
* Generate concatenation SQL for this database
* @param values Values to concatenate
* @return Database-specific concatenation expression
*/
public String getConcatSql(String... values)
/**
* Generate auto-increment clause for column definition
* @return Auto-increment clause, or empty string if not supported
*/
public String getAutoIncrementClause()The DatabaseFactory provides database instance creation and management.
/**
* Get the singleton DatabaseFactory instance
* @return DatabaseFactory instance
*/
public static DatabaseFactory getInstance()
/**
* Find correct database implementation for connection
* @param connection Database connection
* @return Database implementation
* @throws DatabaseException if no suitable implementation found
*/
public Database findCorrectDatabaseImplementation(DatabaseConnection connection) throws DatabaseException
/**
* Open database connection with parameters
* @param url Database URL
* @param username Database username
* @param password Database password
* @param driver JDBC driver class name (optional)
* @param driverPropertiesFile Driver properties file (optional)
* @param propertyProviderClass Property provider class (optional)
* @return Database instance
* @throws DatabaseException if connection fails
*/
public Database openDatabase(String url, String username, String password,
String driver, String driverPropertiesFile,
String propertyProviderClass) throws DatabaseException
/**
* Open database connection
* @param url Database URL
* @param username Database username
* @param password Database password
* @param driver JDBC driver class name
* @return DatabaseConnection instance
* @throws DatabaseException if connection fails
*/
public DatabaseConnection openConnection(String url, String username, String password, String driver) throws DatabaseException
/**
* Find default driver for database URL
* @param url Database URL
* @return JDBC driver class name
*/
public String findDefaultDriver(String url)
/**
* Get all implemented database types
* @return List of available Database implementations
*/
public List<Database> getImplementedDatabases()public class PostgresDatabase extends AbstractJdbcDatabase {
// PostgreSQL-specific implementation
public String getShortName() { return "postgresql"; }
public String getDefaultDriver(String url) { return "org.postgresql.Driver"; }
public Integer getDefaultPort() { return 5432; }
// PostgreSQL capabilities
public boolean supportsSequences() { return true; }
public boolean supportsAutoIncrement() { return true; }
public boolean supportsDDLInTransaction() { return true; }
}public class MySQLDatabase extends AbstractJdbcDatabase {
// MySQL-specific implementation
public String getShortName() { return "mysql"; }
public String getDefaultDriver(String url) { return "com.mysql.cj.jdbc.Driver"; }
public Integer getDefaultPort() { return 3306; }
// MySQL capabilities
public boolean supportsSequences() { return false; }
public boolean supportsAutoIncrement() { return true; }
public boolean supportsDDLInTransaction() { return false; }
}public class OracleDatabase extends AbstractJdbcDatabase {
// Oracle-specific implementation
public String getShortName() { return "oracle"; }
public String getDefaultDriver(String url) { return "oracle.jdbc.OracleDriver"; }
public Integer getDefaultPort() { return 1521; }
// Oracle capabilities
public boolean supportsSequences() { return true; }
public boolean supportsAutoIncrement() { return false; } // Before 12c
public boolean supportsDDLInTransaction() { return false; }
}public class MSSQLDatabase extends AbstractJdbcDatabase {
// SQL Server-specific implementation
public String getShortName() { return "mssql"; }
public String getDefaultDriver(String url) { return "com.microsoft.sqlserver.jdbc.SQLServerDriver"; }
public Integer getDefaultPort() { return 1433; }
// SQL Server capabilities
public boolean supportsSequences() { return true; } // SQL Server 2012+
public boolean supportsAutoIncrement() { return true; }
public boolean supportsDDLInTransaction() { return true; }
}public class H2Database extends AbstractJdbcDatabase {
// H2-specific implementation (in-memory/embedded)
public String getShortName() { return "h2"; }
public String getDefaultDriver(String url) { return "org.h2.Driver"; }
public Integer getDefaultPort() { return null; } // Embedded database
// H2 capabilities
public boolean supportsSequences() { return true; }
public boolean supportsAutoIncrement() { return true; }
public boolean supportsDDLInTransaction() { return true; }
}public class SQLiteDatabase extends AbstractJdbcDatabase {
// SQLite-specific implementation
public String getShortName() { return "sqlite"; }
public String getDefaultDriver(String url) { return "org.sqlite.JDBC"; }
public Integer getDefaultPort() { return null; } // File-based database
// SQLite capabilities
public boolean supportsSequences() { return false; }
public boolean supportsAutoIncrement() { return true; }
public boolean supportsDDLInTransaction() { return true; }
}All database implementations available in Liquibase:
// Core relational databases
OracleDatabase // Oracle Database
MySQLDatabase // MySQL
MariaDBDatabase // MariaDB
PostgresDatabase // PostgreSQL
MSSQLDatabase // Microsoft SQL Server
DB2Database // IBM DB2
SybaseDatabase // Sybase ASE
// Embedded/lightweight databases
H2Database // H2 Database Engine
SQLiteDatabase // SQLite
DerbyDatabase // Apache Derby
HsqlDatabase // HSQLDB
// Specialized databases
FirebirdDatabase // Firebird
CockroachDatabase // CockroachDB
// Testing and fallback
MockDatabase // Mock database for testing
UnsupportedDatabase // Fallback for unknown databasesimport liquibase.database.DatabaseFactory;
import liquibase.database.Database;
import liquibase.database.jvm.JdbcConnection;
import java.sql.DriverManager;
// Create JDBC connection
Connection jdbcConnection = DriverManager.getConnection(
"jdbc:postgresql://localhost:5432/mydb",
"username",
"password"
);
// Wrap in Liquibase connection
DatabaseConnection databaseConnection = new JdbcConnection(jdbcConnection);
// Get appropriate database implementation
DatabaseFactory factory = DatabaseFactory.getInstance();
Database database = factory.findCorrectDatabaseImplementation(databaseConnection);
System.out.println("Database type: " + database.getShortName());
System.out.println("Database product: " + database.getDatabaseProductName());
System.out.println("Database version: " + database.getDatabaseProductVersion());// Let factory handle connection creation
DatabaseFactory factory = DatabaseFactory.getInstance();
Database database = factory.openDatabase(
"jdbc:mysql://localhost:3306/mydb",
"username",
"password",
"com.mysql.cj.jdbc.Driver",
null, // driver properties file
null // property provider class
);
// Use database
System.out.println("Connected to: " + database.getDatabaseProductName());// Check database capabilities
if (database.supportsAutoIncrement()) {
System.out.println("Database supports auto-increment columns");
}
if (database.supportsSequences()) {
System.out.println("Database supports sequences");
}
if (database.supportsDDLInTransaction()) {
System.out.println("Database supports DDL in transactions");
} else {
System.out.println("DDL changes will be auto-committed");
}
// Check specific features
if (database.supportsInitiallyDeferrableColumns()) {
System.out.println("Database supports deferred constraints");
}
if (database.supportsDropTableCascadeConstraints()) {
System.out.println("Database supports CASCADE DROP");
}// Set default schema and catalog
database.setDefaultSchemaName("app_schema");
database.setDefaultCatalogName("app_catalog");
// Get current settings
String currentSchema = database.getDefaultSchemaName();
String currentCatalog = database.getDefaultCatalogName();
System.out.println("Current schema: " + currentSchema);
System.out.println("Current catalog: " + currentCatalog);
// Liquibase table placement
String liquibaseSchema = database.getLiquibaseSchemaName();
String liquibaseCatalog = database.getLiquibaseCatalogName();
System.out.println("Liquibase tables in: " + liquibaseCatalog + "." + liquibaseSchema);// Generate database-specific SQL
String dateSQL = database.getDateLiteral("2023-12-25");
System.out.println("Date literal: " + dateSQL);
String currentTimeSQL = database.getCurrentDateTimeFunction();
System.out.println("Current time function: " + currentTimeSQL);
String concatSQL = database.getConcatSql("'Hello'", "' '", "'World'");
System.out.println("Concatenation SQL: " + concatSQL);
String autoIncSQL = database.getAutoIncrementClause();
if (!autoIncSQL.isEmpty()) {
System.out.println("Auto-increment clause: " + autoIncSQL);
}// Support multiple database types
public class MultiDatabaseService {
public Database connectToDatabase(String type, String url, String user, String pass)
throws DatabaseException {
DatabaseFactory factory = DatabaseFactory.getInstance();
Database database = factory.openDatabase(url, user, pass, null, null, null);
// Configure based on database type
switch (database.getShortName()) {
case "postgresql":
configurePostgreSQL(database);
break;
case "mysql":
configureMySQL(database);
break;
case "oracle":
configureOracle(database);
break;
case "mssql":
configureSQLServer(database);
break;
default:
configureGeneric(database);
}
return database;
}
private void configurePostgreSQL(Database database) throws DatabaseException {
// PostgreSQL-specific configuration
database.setDefaultSchemaName("public");
}
private void configureMySQL(Database database) throws DatabaseException {
// MySQL-specific configuration
// MySQL doesn't use schemas in the same way
}
private void configureOracle(Database database) throws DatabaseException {
// Oracle-specific configuration
// Set appropriate tablespace if needed
}
private void configureSQLServer(Database database) throws DatabaseException {
// SQL Server-specific configuration
database.setDefaultSchemaName("dbo");
}
private void configureGeneric(Database database) throws DatabaseException {
// Generic configuration for unknown databases
}
}import liquibase.database.core.MockDatabase;
// Create mock database for testing
MockDatabase mockDatabase = new MockDatabase();
mockDatabase.setConnection(new MockDatabaseConnection());
// Mock database provides controllable behavior for testing
System.out.println("Mock database type: " + mockDatabase.getShortName());
// All operations will be simulated without actual database interactiontry {
DatabaseFactory factory = DatabaseFactory.getInstance();
Database database = factory.findCorrectDatabaseImplementation(connection);
if (database instanceof UnsupportedDatabase) {
System.err.println("Database type not supported by Liquibase");
// Handle unsupported database scenario
}
} catch (DatabaseException e) {
System.err.println("Database connection failed: " + e.getMessage());
// Handle connection errors
throw e;
}Install with Tessl CLI
npx tessl i tessl/maven-org-liquibase--liquibase-core