001
002 /*
003 * Copyright (C) 2011 Archie L. Cobbs. All rights reserved.
004 *
005 * $Id: SpringSQLSchemaUpdate.java 205 2012-01-06 22:43:05Z archie.cobbs $
006 */
007
008 package org.dellroad.stuff.schema;
009
010 import java.sql.Connection;
011 import java.util.ArrayList;
012 import java.util.List;
013
014 /**
015 * Spring-enabled SQL {@link SchemaUpdate}.
016 *
017 * <p>
018 * The {@link #setSQLCommandList sqlCommandList} property is required.
019 *
020 * <p>
021 * Instances can be created succintly in Spring using the <code><dellroad-stuff:sql-update></code> custom XML element,
022 * which works just like <code><dellroad-stuff:sql></code> except that it wraps the resulting {@link SQLCommandList}
023 * as a delegate inside an instance of this class.
024 *
025 * <p>
026 * For example:
027 * <blockquote><pre>
028 * <beans xmlns="http://www.springframework.org/schema/beans"
029 * <b>xmlns:dellroad-stuff="http://dellroad-stuff.googlecode.com/schema/dellroad-stuff"</b>
030 * xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
031 * xsi:schemaLocation="
032 * http://www.springframework.org/schema/beans
033 * http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
034 * <b>http://dellroad-stuff.googlecode.com/schema/dellroad-stuff
035 * http://dellroad-stuff.googlecode.com/svn/wiki/schemas/dellroad-stuff-1.0.xsd</b>">
036 *
037 * <!-- Schema update to add the 'phone' column to the 'User' table -->
038 * <b><dellroad-stuff:sql-update id="addPhone">ALTER TABLE User ADD phone VARCHAR(64)</dellroad-stuff:sql-update></b>
039 *
040 * <!-- Schema update to run some complicated external SQL script -->
041 * <b><dellroad-stuff:sql-update id="majorChanges" depends-on="addPhone" resource="classpath:majorChanges.sql"/></b>
042 *
043 * <!-- more beans... -->
044 *
045 * </beans>
046 * </pre></blockquote>
047 * </p>
048 *
049 * <p>
050 * A multi-statement SQL script is normally treated as a set of individual updates. For example:
051 * <blockquote><pre>
052 * <b><dellroad-stuff:sql-update id="renameColumn">
053 * ALTER TABLE User ADD newName VARCHAR(64);
054 * ALTER TABLE User SET newName = oldName;
055 * ALTER TABLE User DROP oldName;
056 * </dellroad-stuff:sql-update></b>
057 * </pre></blockquote>
058 * This will create three separate update beans named <code>renameColumn-00001</code>, <code>renameColumn-00002</code>, and
059 * <code>renameColumn-00003</code>. You can disable this behavior by adding the attribute <code>single-action="true"</code>,
060 * in which case all three of the statements will be executed together in the same transaction and recorded under the name
061 * <code>renameColumn</code>; this means that they must all complete successfully or you could end up with a partially
062 * completed update.
063 * </p>
064 *
065 * <p>
066 * Note that if the nested SQL script only contains one SQL statement, any <code>single-action</code> attribute is
067 * ignored and the bean's given name (e.g., <code>renameColumn</code>) is always used as the name of the single update.
068 * </p>
069 *
070 * @see SQLCommandList
071 */
072 public class SpringSQLSchemaUpdate extends AbstractSpringSchemaUpdate<Connection> {
073
074 private SQLCommandList sqlCommandList;
075
076 @Override
077 public void afterPropertiesSet() throws Exception {
078 super.afterPropertiesSet();
079 if (this.sqlCommandList == null)
080 throw new Exception("no SQLCommandList configured");
081 }
082
083 /**
084 * Configure the {@link SQLCommandList}. This is a required property.
085 *
086 * @see DatabaseAction
087 */
088 public void setSQLCommandList(SQLCommandList sqlCommandList) {
089 this.sqlCommandList = sqlCommandList;
090 }
091
092 public SQLCommandList getSQLCommandList() {
093 return this.sqlCommandList;
094 }
095
096 @Override
097 public List<DatabaseAction<Connection>> getDatabaseActions() {
098 return new ArrayList<DatabaseAction<Connection>>(this.getSQLCommandList().split());
099 }
100 }
101