|
||||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | |||||||||
java.lang.Objectorg.dellroad.stuff.schema.AbstractSchemaUpdater<DataSource,Connection>
org.dellroad.stuff.schema.SQLSchemaUpdater
public class SQLSchemaUpdater
Concrete extension of AbstractSchemaUpdater for SQL databases.
Required properties are the database initialization, update table initialization, and the updates themselves.
Applied updates are recorded in a special update table, which contains two columns: one for the unique
update name and one for a timestamp. The update table and column names
are configurable via setUpdateTableName(),
setUpdateTableNameColumn(), and setUpdateTableTimeColumn().
By default, this class detects a completely uninitialized database by the absence of the update table itself
in the schema (see databaseNeedsInitialization()).
When an uninitialized database is encountered, the configured database initialization
and update table initialization actions are applied first to initialize
the database schema.
| Field Summary | |
|---|---|
static String |
DEFAULT_UPDATE_TABLE_NAME
Default nefault name of the table that tracks schema updates, "SchemaUpdate". |
static String |
DEFAULT_UPDATE_TABLE_NAME_COLUMN
Default name of the column in the updates table holding the unique update name, "updateName". |
static String |
DEFAULT_UPDATE_TABLE_TIME_COLUMN
Default name of the column in the updates table holding the update's time applied, "updateTime". |
| Fields inherited from class org.dellroad.stuff.schema.AbstractSchemaUpdater |
|---|
log |
| Constructor Summary | |
|---|---|
SQLSchemaUpdater()
|
|
| Method Summary | |
|---|---|
protected void |
apply(Connection c,
DatabaseAction<Connection> action)
Execute a database action within an existing transaction. |
protected void |
commitTransaction(Connection c)
Commit a previously opened transaction. |
protected boolean |
databaseNeedsInitialization(Connection c)
Determine if the database needs initialization. |
protected Set<String> |
getAppliedUpdateNames(Connection c)
Determine which updates have already been applied. |
SQLCommandList |
getDatabaseInitialization()
Get the empty database initialization. |
SQLCommandList |
getUpdateTableInitialization()
Get the update table initialization. |
String |
getUpdateTableName()
Get the name of the table that keeps track of applied updates. |
String |
getUpdateTableNameColumn()
Get the name of the update name column in the table that keeps track of applied updates. |
String |
getUpdateTableTimeColumn()
Get the name of the update timestamp column in the table that keeps track of applied updates. |
protected boolean |
indicatesUninitializedDatabase(Connection c,
SQLException e)
Determine if an exception thrown during databaseNeedsInitialization(java.sql.Connection) is consistent with
an uninitialized database. |
void |
initializeAndUpdateDatabase(DataSource dataSource)
Perform database schema initialization and updates. |
protected void |
initializeDatabase(Connection c)
Initialize an uninitialized database. |
protected Connection |
openTransaction(DataSource dataSource)
Begin a transaction on the given connection. |
protected void |
recordUpdateApplied(Connection c,
String updateName)
Record an update as having been applied. |
protected void |
rollbackTransaction(Connection c)
Roll back a previously opened transaction. |
void |
setDatabaseInitialization(SQLCommandList databaseInitialization)
Configure how an empty database gets initialized. |
void |
setUpdateTableInitialization(SQLCommandList updateTableInitialization)
Configure how the update table itself gets initialized. |
void |
setUpdateTableName(String updateTableName)
Set the name of the table that keeps track of applied updates. |
void |
setUpdateTableNameColumn(String updateTableNameColumn)
Set the name of the update name column in the table that keeps track of applied updates. |
void |
setUpdateTableTimeColumn(String updateTableTimeColumn)
Set the name of the update timestamp column in the table that keeps track of applied updates. |
| Methods inherited from class org.dellroad.stuff.schema.AbstractSchemaUpdater |
|---|
applyInTransaction, generateMultiUpdateName, getOrderingTieBreaker, getUpdates, isIgnoreUnrecognizedUpdates, isValidUpdateName, setIgnoreUnrecognizedUpdates, setUpdates |
| Methods inherited from class java.lang.Object |
|---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
| Field Detail |
|---|
public static final String DEFAULT_UPDATE_TABLE_NAME
"SchemaUpdate".
public static final String DEFAULT_UPDATE_TABLE_NAME_COLUMN
"updateName".
public static final String DEFAULT_UPDATE_TABLE_TIME_COLUMN
"updateTime".
| Constructor Detail |
|---|
public SQLSchemaUpdater()
| Method Detail |
|---|
public String getUpdateTableName()
setUpdateTableName()public void setUpdateTableName(String updateTableName)
DEFAULT_UPDATE_TABLE_NAME.
This name must be consistent with the update table initialization.
public String getUpdateTableNameColumn()
setUpdateTableNameColumn()public void setUpdateTableNameColumn(String updateTableNameColumn)
DEFAULT_UPDATE_TABLE_NAME_COLUMN.
This name must be consistent with the update table initialization.
public String getUpdateTableTimeColumn()
setUpdateTableTimeColumn()public void setUpdateTableTimeColumn(String updateTableTimeColumn)
DEFAULT_UPDATE_TABLE_TIME_COLUMN.
This name must be consistent with the update table initialization.
public SQLCommandList getUpdateTableInitialization()
setUpdateTableInitialization()public void setUpdateTableInitialization(SQLCommandList updateTableInitialization)
This initialization should create the update table where the name column is the primary key. The name column must have a length limit greater than or equal to the longest schema update name.
The table and column names must be consistent with the values configured via
setUpdateTableName(), setUpdateTableNameColumn(),
and setUpdateTableTimeColumn().
For convenience, pre-defined initialization scripts using the default table and column names are available
at the following resource locations. These can be used to configure a SQLCommandList:
| Database | Resource |
|---|---|
| MySQL (InnoDB) | classpath:org/dellroad/stuff/schema/updateTable-mysql.sql |
updateTableInitialization - update table schema initializationsetUpdateTableName(),
setUpdateTableNameColumn(),
setUpdateTableTimeColumn()public SQLCommandList getDatabaseInitialization()
setDatabaseInitialization()public void setDatabaseInitialization(SQLCommandList databaseInitialization)
This update is run when no update table found, which (we assume) implies an empty database with no tables or content. Typically this contains the SQL script that gets automatically generated by your favorite schema generation tool.
This script is expected to initialize the database schema (i.e., creating all the tables) so that when completed the database is "up to date" with respect to the configured schema updates. That is, when this action completes, we assume all updates have already been (implicitly) applied (and they will be recorded as such).
Note this script is not expected to create the update table that tracks schema updates; that function is handled by the update table initialization.
databaseInitialization - application database schema initialization
protected void apply(Connection c,
DatabaseAction<Connection> action)
throws SQLException
AbstractSchemaUpdater
All database operations in AbstractSchemaUpdater are performed via this method;
subclasses are encouraged to follow this pattern.
The implementation in AbstractSchemaUpdater simply invokes action.apply();
subclasses may override if desired.
apply in class AbstractSchemaUpdater<DataSource,Connection>SQLException
public void initializeAndUpdateDatabase(DataSource dataSource)
throws SQLException
AbstractSchemaUpdaterThis method applies the following logic: if the database needs initialization, then initialize the database and record each update as having been applied; otherwise, apply any unapplied updates as needed.
Note this implies the database initialization must initialize the database to its current, up-to-date state (with respect to the set of all available updates), not its original, pre-update state.
The database initialization step, and each of the update steps, is performed within its own transaction.
initializeAndUpdateDatabase in class AbstractSchemaUpdater<DataSource,Connection>dataSource - the database to initialize (if necessary) and update
Exception - if an update fails
IllegalStateException - if the database needs initialization and either the
database initialization or
the update table initialization has not been configured
IllegalStateException - if this instance is not configured to ignore
unrecognized updates and an unrecognized update has already been applied
IllegalArgumentException - if any configured update has a required predecessor which is not also a configured update
(i.e., if the updates are not transitively closed under predecessors)
SQLException
protected Connection openTransaction(DataSource dataSource)
throws SQLException
The implementation in SQLSchemaUpdater creates a serializable-level transaction.
openTransaction in class AbstractSchemaUpdater<DataSource,Connection>dataSource - the database on which to open the transaction
Connection with an open transaction
SQLException - if an error occurs while accessing the database
protected void commitTransaction(Connection c)
throws SQLException
The implementation in SQLSchemaUpdater just invokes Connection.commit().
commitTransaction in class AbstractSchemaUpdater<DataSource,Connection>c - the connection on which to commit the transaction
SQLException - if an error occurs while accessing the database
protected void rollbackTransaction(Connection c)
throws SQLException
commitTransaction() throws an exception.
The implementation in SQLSchemaUpdater just invokes Connection.rollback().
rollbackTransaction in class AbstractSchemaUpdater<DataSource,Connection>c - the connection on which to roll back the transaction
SQLException - if an error occurs while accessing the database
protected boolean databaseNeedsInitialization(Connection c)
throws SQLException
The implementation in SQLSchemaUpdater simply invokes SELECT COUNT(*) FROM UPDATETABLE
and checks for success or failure. If an exception is thrown, indicatesUninitializedDatabase(java.sql.Connection, java.sql.SQLException) is used
to distinguish between an exception caused by an uninitialized database and a truly unexpected one.
databaseNeedsInitialization in class AbstractSchemaUpdater<DataSource,Connection>c - connection to the database
SQLException - if an unexpected error occurs while accessing the database
protected boolean indicatesUninitializedDatabase(Connection c,
SQLException e)
throws SQLException
databaseNeedsInitialization(java.sql.Connection) is consistent with
an uninitialized database.
This should return true if the exception would be thrown by an SQL query that attempts to access a non-existent table. For exceptions thrown by other causes, this should return false.
The implementation in SQLSchemaUpdater always returns true. Subclasses are encouraged to override
with a more precise implementation.
c - connection on which the exception occurrede - exception thrown during database access in databaseNeedsInitialization(java.sql.Connection)
SQLException - if an error occursdatabaseNeedsInitialization(java.sql.Connection)
protected void recordUpdateApplied(Connection c,
String updateName)
throws SQLException
The implementation in SQLSchemaUpdater does the standard JDBC thing using an INSERT statement
into the update table.
recordUpdateApplied in class AbstractSchemaUpdater<DataSource,Connection>c - SQL connectionupdateName - update name
IllegalStateException - if the update has already been recorded in the database
SQLException - if an error occurs while accessing the database
protected Set<String> getAppliedUpdateNames(Connection c)
throws SQLException
The implementation in SQLSchemaUpdater does the standard JDBC thing using a SELECT statement
from the update table.
getAppliedUpdateNames in class AbstractSchemaUpdater<DataSource,Connection>c - open transaction
SQLException - if an error occurs while accessing the database
protected void initializeDatabase(Connection c)
throws SQLException
AbstractSchemaUpdater
initializeDatabase in class AbstractSchemaUpdater<DataSource,Connection>c - open transaction
SQLException
|
||||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | |||||||||