Guide for Liferay database migration and upgrade processes. Use when creating UpgradeStepRegistrators, modifying database schemas, running upgrade tools, or managing database-level changes in Liferay modules. Triggers on keywords like UpgradeProcess, UpgradeStepRegistrator, database upgrade liferay, alter column liferay, schema version, database migration, upgrade step, Liferay-Require-SchemaVersion.
Liferay provides an Upgrade Framework for managing database schema changes across module versions. This is essential for Service Builder modules and any module that modifies database structure.
public class AddStatusColumnUpgradeProcess extends UpgradeProcess {
@Override
protected void doUpgrade() throws Exception {
// Add column (safe — checks existence)
if (!hasColumn("MyApp_MyEntry", "status")) {
alter(
MyEntryTable.class,
new AddColumn("status", "INTEGER default 0 not null")
);
}
// Rename column
alter(
MyEntryTable.class,
new AlterColumnName("oldName", "newName VARCHAR(75) null")
);
// Change column type
alter(
MyEntryTable.class,
new AlterColumnType("description", "TEXT null")
);
// Create new table
if (!hasTable("NewTable")) {
runSQL(
"create table NewTable (" +
" id_ LONG not null primary key," +
" name VARCHAR(75) null," +
" createDate DATE null" +
")");
}
// Execute SQL from file
String template = StringUtil.read(
getClass().getResourceAsStream("dependencies/update.sql"));
runSQLTemplateString(template, false, false);
}
}
| Method | Description |
|---|---|
hasColumn(table, column) | Check if column exists |
hasTable(table) | Check if table exists |
alter(table, ...alterations) | Apply column changes |
runSQL(sql) | Execute raw SQL |
runSQLTemplateString(sql, false, false) | Execute SQL template |
AddColumn(name, definition) | Add a column |
AlterColumnName(oldName, newDefinition) | Rename a column |
AlterColumnType(name, newType) | Change column type |
DropColumn(name) | Remove a column |
import com.liferay.portal.upgrade.registry.UpgradeStepRegistrator;
import org.osgi.service.component.annotations.Component;
@Component(
immediate = true,
service = UpgradeStepRegistrator.class
)
public class MyModuleUpgradeStepRegistrator implements UpgradeStepRegistrator {
@Override
public void register(Registry registry) {
// Upgrade from 1.0.0 → 1.1.0
registry.register(
"1.0.0", "1.1.0",
new AddStatusColumnUpgradeProcess()
);
// Upgrade from 1.1.0 → 2.0.0 (multiple steps)
registry.register(
"1.1.0", "2.0.0",
new RenameTablesUpgradeProcess(),
new MigrateDataUpgradeProcess(),
new CleanupUpgradeProcess()
);
}
}
bnd.bnd Schema VersionBundle-Name: My Module Service
Bundle-SymbolicName: com.acme.my.module.service
Bundle-Version: 2.0.0
Liferay-Require-SchemaVersion: 2.0.0
Critical:
Liferay-Require-SchemaVersionmust match the last version inUpgradeStepRegistrator.
my-module-service/
└── src/main/resources/
└── com/acme/myapp/internal/upgrade/v1_1_0/
└── dependencies/
└── update.sql
For major Liferay version upgrades:
cd liferay-home/tools/portal-tools-db-upgrade-client
./db_upgrade_client.sh -j "-Dfile.encoding=UTF-8 -Duser.timezone=GMT -Xmx4096m"
portal-upgrade-database.propertiesjdbc.default.driverClassName=com.mysql.cj.jdbc.Driver
jdbc.default.url=jdbc:mysql://localhost:3306/lportal?useSSL=false
jdbc.default.username=root
jdbc.default.password=password
| Database | JDBC Driver | Production Ready |
|---|---|---|
| MySQL 8.x | com.mysql.cj.jdbc.Driver | ✅ |
| PostgreSQL 16.x | org.postgresql.Driver | ✅ |
| MariaDB 10.x | org.mariadb.jdbc.Driver | ✅ |
| Oracle 19c+ | oracle.jdbc.OracleDriver | ✅ |
| SQL Server 2019+ | com.microsoft.sqlserver.jdbc.SQLServerDriver | ✅ |
| HSQL | org.hsqldb.jdbc.JDBCDriver | ❌ Demo only |
User_, Group_, Layout) directlyalter(), hasColumn(), hasTable() helpers)Liferay-Require-SchemaVersion and registrator versionshasColumn, hasTable)runSQLTemplateString for complex SQL from files