Class SpringSQLSchemaUpdater
- All Implemented Interfaces:
Aware
,BeanFactoryAware
,InitializingBean
SQLSchemaUpdater
optimized for use with Spring.
apply()
is overridden so SpringDataAccessException
s are thrown.indicatesUninitializedDatabase()
is overridden to examine exceptions and more precisely using Spring's exception translation infrastructure to filter out false positives.getOrderingTieBreaker()
is overridden to break ties by ordering updates in the same order as they are defined in the bean factory.- This class implements
InitializingBean
and verifies all required properties are set. - If no updates are explicitly configured, then all
SpringSQLSchemaUpdate
s found in the containing bean factory are automatically configured.
An example of how this class can be combined with custom XML to define an updater, all its updates,
and a SchemaUpdatingDataSource
that automatically updates the database schema:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:dellroad-stuff="http://dellroad-stuff.googlecode.com/schema/dellroad-stuff"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://dellroad-stuff.googlecode.com/schema/dellroad-stuff
http://dellroad-stuff.googlecode.com/svn/wiki/schemas/dellroad-stuff-1.0.xsd">
<!-- DataSource that automatically updates the database schema -->
<bean id="dataSource" class="org.dellroad.stuff.schema.SchemaUpdatingDataSource"
p:dataSource-ref="realDataSource" p:schemaUpdater-ref="schemaUpdater"/>
<!--
Database updater bean. This is used on first access to the DataSource above. Notes:
- "databaseInitialization" is used to initialize the schema (first time only)
- "updateTableInitialization" is used to initialize the update table (first time only)
- In this example, we just use dellroad-stuff's update table initialization for MySQL
- The <dellroad-stuff:sql-update> beans below will be auto-detected
-->
<bean id="schemaUpdater" class="org.dellroad.stuff.spring.SpringSQLSchemaUpdater">
<property name="databaseInitialization">
<dellroad-stuff:sql resource="classpath:databaseInit.sql"/>
</property>
<property name="updateTableInitialization">
<dellroad-stuff:sql resource="classpath:org/dellroad/stuff/schema/updateTable-mysql.sql"/>
</property>
</bean>
<!-- Schema update to add the 'phone' column to the 'User' table -->
<dellroad-stuff:sql-update id="addPhone">ALTER TABLE User ADD phone VARCHAR(64)</dellroad-stuff:sql-update>
<!-- Schema update to run some complicated external SQL script -->
<dellroad-stuff:sql-update id="majorChanges" depends-on="addPhone" resource="classpath:majorChanges.sql"/>
<!-- Multiple SQL commands that will be automatically separated into distinct updates -->
<dellroad-stuff:sql-update id="renameColumn">
ALTER TABLE User ADD newName VARCHAR(64);
ALTER TABLE User SET newName = oldName;
ALTER TABLE User DROP oldName;
</dellroad-stuff:sql-update>
<!-- Add more schema updates over time as needed and everything just works... -->
</beans>
In the case no schema updates are explicitly configured, it is required that this updater and all of its
schema updates are defined in the same ListableBeanFactory
.
-
Field Summary
Fields inherited from class org.dellroad.stuff.schema.SQLSchemaUpdater
DEFAULT_UPDATE_TABLE_NAME, DEFAULT_UPDATE_TABLE_NAME_COLUMN, DEFAULT_UPDATE_TABLE_TIME_COLUMN
Fields inherited from class org.dellroad.stuff.schema.AbstractSchemaUpdater
log
-
Constructor Summary
-
Method Summary
Modifier and TypeMethodDescriptionvoid
protected void
apply
(Connection c, DatabaseAction<Connection> action) Apply aDatabaseAction
to aConnection
.protected Comparator<SchemaUpdate<Connection>>
Get the preferred ordering of two updates that do not have any predecessor constraints (including implied indirect constraints) between them.protected boolean
Determine if an exception thrown duringSQLSchemaUpdater.databaseNeedsInitialization(java.sql.Connection)
is consistent with an uninitialized database.void
setBeanFactory
(BeanFactory beanFactory) protected DataAccessException
translate
(SQLException e, Connection c, String sql) ConvertsSQLException
s into SpringDataAccessException
s.Methods inherited from class org.dellroad.stuff.schema.SQLSchemaUpdater
commitTransaction, databaseNeedsInitialization, getAppliedUpdateNames, getDatabaseInitialization, getTransactionIsolation, getUpdateTableInitialization, getUpdateTableName, getUpdateTableNameColumn, getUpdateTableTimeColumn, initializeAndUpdateDatabase, initializeDatabase, openTransaction, recordUpdateApplied, rollbackTransaction, setDatabaseInitialization, setTransactionIsolation, setUpdateTableInitialization, setUpdateTableName, setUpdateTableNameColumn, setUpdateTableTimeColumn
Methods inherited from class org.dellroad.stuff.schema.AbstractSchemaUpdater
applyInTransaction, generateMultiUpdateName, getAllUpdateNames, getUpdates, isIgnoreUnrecognizedUpdates, isValidUpdateName, setIgnoreUnrecognizedUpdates, setUpdates
-
Constructor Details
-
SpringSQLSchemaUpdater
public SpringSQLSchemaUpdater()
-
-
Method Details
-
afterPropertiesSet
- Specified by:
afterPropertiesSet
in interfaceInitializingBean
- Throws:
Exception
-
setBeanFactory
- Specified by:
setBeanFactory
in interfaceBeanFactoryAware
-
indicatesUninitializedDatabase
Determine if an exception thrown duringSQLSchemaUpdater.databaseNeedsInitialization(java.sql.Connection)
is consistent with an uninitialized database.The implementation in
SpringSQLSchemaUpdater
looks for aBadSqlGrammarException
.- Overrides:
indicatesUninitializedDatabase
in classSQLSchemaUpdater
- Parameters:
c
- connection on which the exception occurrede
- exception thrown during database access inSQLSchemaUpdater.databaseNeedsInitialization(java.sql.Connection)
- Returns:
- true if
e
indicates an uninitialized database - Throws:
SQLException
- if an error occurs- See Also:
-
apply
Apply aDatabaseAction
to aConnection
.The implementation in
SQLSchemaUpdater
invokes the action and delegates totranslate()
to convert anySQLException
thrown.- Overrides:
apply
in classSQLSchemaUpdater
- Parameters:
c
- transaction within which to applyaction
action
- operation to perform- Throws:
SQLException
- if an error occurs attempting to translate a thrown SQLExceptionDataAccessException
- if an error occurs accessing the database- See Also:
-
translate
protected DataAccessException translate(SQLException e, Connection c, String sql) throws SQLException ConvertsSQLException
s into SpringDataAccessException
s.- Parameters:
e
- original exceptionc
- the connection on which the exception coccurredsql
- the SQL statement that generated the exception- Returns:
- the corresponding Spring
DataAccessException
- Throws:
SQLException
- if exception translation fails
-
getOrderingTieBreaker
Get the preferred ordering of two updates that do not have any predecessor constraints (including implied indirect constraints) between them.In the case no schema updates are explicitly configured, the
Comparator
returned by the implementation inSpringSQLSchemaUpdater
sorts updates in the same order that they appear in the containingListableBeanFactory
. Otherwise, the superclass method is used.- Overrides:
getOrderingTieBreaker
in classAbstractSchemaUpdater<DataSource,
Connection> - Returns:
- a
Comparator
that sorts incomparable updates in the order they should be applied
-