/*
 * Copyright 2002-2019 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.jdbc.datasource.init;

import java.sql.Connection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.sql.DataSource;

import org.springframework.core.io.Resource;
import org.springframework.core.io.support.EncodedResource;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

Populates, initializes, or cleans up a database using SQL scripts defined in external resources.
  • Call addScript to add a single SQL script location.
  • Call addScripts to add multiple SQL script locations.
  • Consult the setter methods in this class for further configuration options.
  • Call populate or execute to initialize or clean up the database using the configured scripts.
Author:Keith Donald, Dave Syer, Juergen Hoeller, Chris Beams, Oliver Gierke, Sam Brannen, Chris Baldwin
See Also:
Since:3.0
/** * Populates, initializes, or cleans up a database using SQL scripts defined in * external resources. * * <ul> * <li>Call {@link #addScript} to add a single SQL script location. * <li>Call {@link #addScripts} to add multiple SQL script locations. * <li>Consult the setter methods in this class for further configuration options. * <li>Call {@link #populate} or {@link #execute} to initialize or clean up the * database using the configured scripts. * </ul> * * @author Keith Donald * @author Dave Syer * @author Juergen Hoeller * @author Chris Beams * @author Oliver Gierke * @author Sam Brannen * @author Chris Baldwin * @since 3.0 * @see DatabasePopulatorUtils * @see ScriptUtils */
public class ResourceDatabasePopulator implements DatabasePopulator { List<Resource> scripts = new ArrayList<>(); @Nullable private String sqlScriptEncoding; private String separator = ScriptUtils.DEFAULT_STATEMENT_SEPARATOR; private String commentPrefix = ScriptUtils.DEFAULT_COMMENT_PREFIX; private String blockCommentStartDelimiter = ScriptUtils.DEFAULT_BLOCK_COMMENT_START_DELIMITER; private String blockCommentEndDelimiter = ScriptUtils.DEFAULT_BLOCK_COMMENT_END_DELIMITER; private boolean continueOnError = false; private boolean ignoreFailedDrops = false;
Construct a new ResourceDatabasePopulator with default settings.
Since:4.0.3
/** * Construct a new {@code ResourceDatabasePopulator} with default settings. * @since 4.0.3 */
public ResourceDatabasePopulator() { }
Construct a new ResourceDatabasePopulator with default settings for the supplied scripts.
Params:
  • scripts – the scripts to execute to initialize or clean up the database (never null)
Since:4.0.3
/** * Construct a new {@code ResourceDatabasePopulator} with default settings * for the supplied scripts. * @param scripts the scripts to execute to initialize or clean up the database * (never {@code null}) * @since 4.0.3 */
public ResourceDatabasePopulator(Resource... scripts) { setScripts(scripts); }
Construct a new ResourceDatabasePopulator with the supplied values.
Params:
  • continueOnError – flag to indicate that all failures in SQL should be logged but not cause a failure
  • ignoreFailedDrops – flag to indicate that a failed SQL DROP statement can be ignored
  • sqlScriptEncoding – the encoding for the supplied SQL scripts (may be null or empty to indicate platform encoding)
  • scripts – the scripts to execute to initialize or clean up the database (never null)
Since:4.0.3
/** * Construct a new {@code ResourceDatabasePopulator} with the supplied values. * @param continueOnError flag to indicate that all failures in SQL should be * logged but not cause a failure * @param ignoreFailedDrops flag to indicate that a failed SQL {@code DROP} * statement can be ignored * @param sqlScriptEncoding the encoding for the supplied SQL scripts * (may be {@code null} or <em>empty</em> to indicate platform encoding) * @param scripts the scripts to execute to initialize or clean up the database * (never {@code null}) * @since 4.0.3 */
public ResourceDatabasePopulator(boolean continueOnError, boolean ignoreFailedDrops, @Nullable String sqlScriptEncoding, Resource... scripts) { this.continueOnError = continueOnError; this.ignoreFailedDrops = ignoreFailedDrops; setSqlScriptEncoding(sqlScriptEncoding); setScripts(scripts); }
Add a script to execute to initialize or clean up the database.
Params:
  • script – the path to an SQL script (never null)
/** * Add a script to execute to initialize or clean up the database. * @param script the path to an SQL script (never {@code null}) */
public void addScript(Resource script) { Assert.notNull(script, "Script must not be null"); this.scripts.add(script); }
Add multiple scripts to execute to initialize or clean up the database.
Params:
  • scripts – the scripts to execute (never null)
/** * Add multiple scripts to execute to initialize or clean up the database. * @param scripts the scripts to execute (never {@code null}) */
public void addScripts(Resource... scripts) { assertContentsOfScriptArray(scripts); this.scripts.addAll(Arrays.asList(scripts)); }
Set the scripts to execute to initialize or clean up the database, replacing any previously added scripts.
Params:
  • scripts – the scripts to execute (never null)
/** * Set the scripts to execute to initialize or clean up the database, * replacing any previously added scripts. * @param scripts the scripts to execute (never {@code null}) */
public void setScripts(Resource... scripts) { assertContentsOfScriptArray(scripts); // Ensure that the list is modifiable this.scripts = new ArrayList<>(Arrays.asList(scripts)); } private void assertContentsOfScriptArray(Resource... scripts) { Assert.notNull(scripts, "Scripts array must not be null"); Assert.noNullElements(scripts, "Scripts array must not contain null elements"); }
Specify the encoding for the configured SQL scripts, if different from the platform encoding.
Params:
  • sqlScriptEncoding – the encoding used in scripts (may be null or empty to indicate platform encoding)
See Also:
/** * Specify the encoding for the configured SQL scripts, * if different from the platform encoding. * @param sqlScriptEncoding the encoding used in scripts * (may be {@code null} or empty to indicate platform encoding) * @see #addScript(Resource) */
public void setSqlScriptEncoding(@Nullable String sqlScriptEncoding) { this.sqlScriptEncoding = (StringUtils.hasText(sqlScriptEncoding) ? sqlScriptEncoding : null); }
Specify the statement separator, if a custom one.

Defaults to ";" if not specified and falls back to "\n" as a last resort; may be set to ScriptUtils.EOF_STATEMENT_SEPARATOR to signal that each script contains a single statement without a separator.

Params:
  • separator – the script statement separator
/** * Specify the statement separator, if a custom one. * <p>Defaults to {@code ";"} if not specified and falls back to {@code "\n"} * as a last resort; may be set to {@link ScriptUtils#EOF_STATEMENT_SEPARATOR} * to signal that each script contains a single statement without a separator. * @param separator the script statement separator */
public void setSeparator(String separator) { this.separator = separator; }
Set the prefix that identifies single-line comments within the SQL scripts.

Defaults to "--".

Params:
  • commentPrefix – the prefix for single-line comments
/** * Set the prefix that identifies single-line comments within the SQL scripts. * <p>Defaults to {@code "--"}. * @param commentPrefix the prefix for single-line comments */
public void setCommentPrefix(String commentPrefix) { this.commentPrefix = commentPrefix; }
Set the start delimiter that identifies block comments within the SQL scripts.

Defaults to "/*".

Params:
  • blockCommentStartDelimiter – the start delimiter for block comments (never null or empty)
See Also:
Since:4.0.3
/** * Set the start delimiter that identifies block comments within the SQL * scripts. * <p>Defaults to {@code "/*"}. * @param blockCommentStartDelimiter the start delimiter for block comments * (never {@code null} or empty) * @since 4.0.3 * @see #setBlockCommentEndDelimiter */
public void setBlockCommentStartDelimiter(String blockCommentStartDelimiter) { Assert.hasText(blockCommentStartDelimiter, "BlockCommentStartDelimiter must not be null or empty"); this.blockCommentStartDelimiter = blockCommentStartDelimiter; }
Set the end delimiter that identifies block comments within the SQL scripts.

Defaults to "*/".

Params:
  • blockCommentEndDelimiter – the end delimiter for block comments (never null or empty)
See Also:
Since:4.0.3
/** * Set the end delimiter that identifies block comments within the SQL * scripts. * <p>Defaults to <code>"*&#47;"</code>. * @param blockCommentEndDelimiter the end delimiter for block comments * (never {@code null} or empty) * @since 4.0.3 * @see #setBlockCommentStartDelimiter */
public void setBlockCommentEndDelimiter(String blockCommentEndDelimiter) { Assert.hasText(blockCommentEndDelimiter, "BlockCommentEndDelimiter must not be null or empty"); this.blockCommentEndDelimiter = blockCommentEndDelimiter; }
Flag to indicate that all failures in SQL should be logged but not cause a failure.

Defaults to false.

Params:
  • continueOnError – true if script execution should continue on error
/** * Flag to indicate that all failures in SQL should be logged but not cause a failure. * <p>Defaults to {@code false}. * @param continueOnError {@code true} if script execution should continue on error */
public void setContinueOnError(boolean continueOnError) { this.continueOnError = continueOnError; }
Flag to indicate that a failed SQL DROP statement can be ignored.

This is useful for a non-embedded database whose SQL dialect does not support an IF EXISTS clause in a DROP statement.

The default is false so that if the populator runs accidentally, it will fail fast if a script starts with a DROP statement.

Params:
  • ignoreFailedDrops – true if failed drop statements should be ignored
/** * Flag to indicate that a failed SQL {@code DROP} statement can be ignored. * <p>This is useful for a non-embedded database whose SQL dialect does not * support an {@code IF EXISTS} clause in a {@code DROP} statement. * <p>The default is {@code false} so that if the populator runs accidentally, it will * fail fast if a script starts with a {@code DROP} statement. * @param ignoreFailedDrops {@code true} if failed drop statements should be ignored */
public void setIgnoreFailedDrops(boolean ignoreFailedDrops) { this.ignoreFailedDrops = ignoreFailedDrops; }
{@inheritDoc}
See Also:
/** * {@inheritDoc} * @see #execute(DataSource) */
@Override public void populate(Connection connection) throws ScriptException { Assert.notNull(connection, "Connection must not be null"); for (Resource script : this.scripts) { EncodedResource encodedScript = new EncodedResource(script, this.sqlScriptEncoding); ScriptUtils.executeSqlScript(connection, encodedScript, this.continueOnError, this.ignoreFailedDrops, this.commentPrefix, this.separator, this.blockCommentStartDelimiter, this.blockCommentEndDelimiter); } }
Execute this ResourceDatabasePopulator against the given DataSource.

Delegates to DatabasePopulatorUtils.execute.

Params:
  • dataSource – the DataSource to execute against (never null)
Throws:
See Also:
Since:4.1
/** * Execute this {@code ResourceDatabasePopulator} against the given * {@link DataSource}. * <p>Delegates to {@link DatabasePopulatorUtils#execute}. * @param dataSource the {@code DataSource} to execute against (never {@code null}) * @throws ScriptException if an error occurs * @since 4.1 * @see #populate(Connection) */
public void execute(DataSource dataSource) throws ScriptException { DatabasePopulatorUtils.execute(this, dataSource); } }