HHH-11817 Allow schema-export commands written to file to truncate in addition to current appending

This commit is contained in:
Andrea Boriero 2021-06-16 16:03:50 +02:00 committed by Yoann Rodière
parent 107849c3c8
commit 8fc45a9004
8 changed files with 120 additions and 26 deletions

View File

@ -887,6 +887,10 @@ For cases where the `javax.persistence.schema-generation.scripts.action` value i
`*javax.persistence.schema-generation.scripts.drop-target*`::
For cases where the `javax.persistence.schema-generation.scripts.action` value indicates that schema dropping commands should be written to DDL script file, `javax.persistence.schema-generation.scripts.drop-target` specifies either a `java.io.Writer` configured for output of the DDL script or a string specifying the file URL for the DDL script.
`*hibernate.hbm2ddl.schema-generation.script.append*` (e.g. `true` (default value) or `false`)::
For cases where the `javax.persistence.schema-generation.scripts.action` value indicates that schema commands should be written to DDL script file, `hibernate.hbm2ddl.schema-generation.script.append` specifies if schema commands should be appended to the end of the file rather than written at the beginning of the file.
Values are `true` for appending schema commands to the end of the file, `false` for writing achema commands at the beginning of the file.
`*javax.persistence.hibernate.hbm2ddl.import_files*` (e.g. `import.sql` (default value))::
Comma-separated names of the optional files containing SQL DML statements executed during the `SessionFactory` creation.
File order matters, the statements of a given file are executed before the statements of the following one.

View File

@ -1588,6 +1588,16 @@ public interface AvailableSettings extends org.hibernate.jpa.AvailableSettings {
@SuppressWarnings("JavaDoc")
String HBM2DDL_SCRIPTS_CREATE_TARGET = "javax.persistence.schema-generation.scripts.create-target";
/**
* For cases where the {@value #HBM2DDL_SCRIPTS_ACTION} value indicates that schema commands should
* be written to DDL script file, specifies if schema commands should be appended to the end of the file rather than written at the beginning of the file.
*
* Values are: {@code true} for appending schema commands to the end of the file, {@code false} for writing schema commands at the beginning.
*
* The default value is {@code true}
*/
String HBM2DDL_SCRIPTS_CREATE_APPEND = "hibernate.hbm2ddl.schema-generation.script.append";
/**
* For cases where the {@value #HBM2DDL_SCRIPTS_ACTION} value indicates that schema drop commands should
* be written to DDL script file, {@value #HBM2DDL_SCRIPTS_DROP_TARGET} specifies either a

View File

@ -135,6 +135,7 @@ public class SchemaExport {
}
}
boolean append = true;
boolean haltOnError = false;
boolean format = false;
boolean manageNamespaces = false;
@ -159,6 +160,18 @@ public class SchemaExport {
return this;
}
/**
* For generating a export script file, by default the content will be appended at the begin or end of the file.
*
* The sql will be written at the beginning of the file rather append to the end.
*
* @return this
*/
public SchemaExport setOverrideOutputFileContent() {
append = false;
return this;
}
/**
* Comma-separated list of resource names to use for database init commands on create.
*
@ -244,7 +257,12 @@ public class SchemaExport {
LOG.runningHbm2ddlSchemaExport();
final TargetDescriptor targetDescriptor = buildTargetDescriptor( targetTypes, outputFile, serviceRegistry );
final TargetDescriptor targetDescriptor = buildTargetDescriptor(
targetTypes,
outputFile,
append,
serviceRegistry
);
doExecution( action, needsJdbcConnection( targetTypes ), metadata, serviceRegistry, targetDescriptor );
}
@ -316,6 +334,14 @@ public class SchemaExport {
EnumSet<TargetType> targetTypes,
String outputFile,
ServiceRegistry serviceRegistry) {
return buildTargetDescriptor( targetTypes, outputFile, true, serviceRegistry );
}
public static TargetDescriptor buildTargetDescriptor(
EnumSet<TargetType> targetTypes,
String outputFile,
boolean append,
ServiceRegistry serviceRegistry) {
final ScriptTargetOutput scriptTarget;
if ( targetTypes.contains( TargetType.SCRIPT ) ) {
if ( outputFile == null ) {
@ -324,7 +350,8 @@ public class SchemaExport {
scriptTarget = Helper.interpretScriptTargetSetting(
outputFile,
serviceRegistry.getService( ClassLoaderService.class ),
(String) serviceRegistry.getService( ConfigurationService.class ).getSettings().get( AvailableSettings.HBM2DDL_CHARSET_NAME )
(String) serviceRegistry.getService( ConfigurationService.class ).getSettings().get( AvailableSettings.HBM2DDL_CHARSET_NAME ),
append
);
}
else {

View File

@ -55,6 +55,7 @@ public class SchemaUpdate {
boolean haltOnError = false;
private String outputFile;
private boolean append = true;
private String delimiter;
private boolean format;
@ -87,7 +88,7 @@ public class SchemaUpdate {
exceptionHandler
);
final TargetDescriptor targetDescriptor = SchemaExport.buildTargetDescriptor( targetTypes, outputFile, serviceRegistry );
final TargetDescriptor targetDescriptor = SchemaExport.buildTargetDescriptor( targetTypes, outputFile, append, serviceRegistry );
try {
tool.getSchemaMigrator( config ).doMigration( metadata, executionOptions, targetDescriptor );
@ -123,6 +124,18 @@ public class SchemaUpdate {
return this;
}
/**
* For generating a export script file, by default the content will be appended at the begin or end of the file.
*
* The sql will be written at the beginning of the file rather append to the end.
*
* @return this
*/
public SchemaUpdate setOverrideOutputFileContent() {
append = false;
return this;
}
/**
* Set the end of statement delimiter
*

View File

@ -93,7 +93,8 @@ public class Helper {
public static ScriptTargetOutput interpretScriptTargetSetting(
Object scriptTargetSetting,
ClassLoaderService classLoaderService,
String charsetName ) {
String charsetName,
boolean append) {
if ( scriptTargetSetting == null ) {
return null;
}
@ -118,7 +119,7 @@ public class Helper {
// assume it is a File path
final File file = new File( scriptTargetSettingString );
return new ScriptTargetOutputToFile( file, charsetName );
return new ScriptTargetOutputToFile( file, charsetName, append );
}
}

View File

@ -28,6 +28,7 @@ public class ScriptTargetOutputToFile extends AbstractScriptTargetOutput impleme
private final File file;
private final String charsetName;
private final boolean append;
private Writer writer;
@ -36,10 +37,24 @@ public class ScriptTargetOutputToFile extends AbstractScriptTargetOutput impleme
*
* @param file The file to read from
* @param charsetName The charset name
* @param append If true, then bytes will be written to the end of the file rather than the beginning
*/
public ScriptTargetOutputToFile(File file, String charsetName) {
public ScriptTargetOutputToFile(File file, String charsetName, boolean append) {
this.file = file;
this.charsetName = charsetName;
this.append = append;
}
/**
* Constructs a ScriptTargetOutputToFile instance,
* the bytes will be written to the end of the file rather than the beginning
*
* @param file The file to read from
* @param charsetName The charset name
*
*/
public ScriptTargetOutputToFile(File file, String charsetName ) {
this(file, charsetName, true);
}
@Override
@ -53,7 +68,7 @@ public class ScriptTargetOutputToFile extends AbstractScriptTargetOutput impleme
@Override
public void prepare() {
super.prepare();
this.writer = toFileWriter( this.file, this.charsetName );
this.writer = toFileWriter( this.file, this.charsetName, append );
}
@Override
@ -63,7 +78,7 @@ public class ScriptTargetOutputToFile extends AbstractScriptTargetOutput impleme
writer.close();
}
catch (IOException e) {
throw new SchemaManagementException( "Unable to close file writer : " + e.toString() );
throw new SchemaManagementException( "Unable to close file writer : " + e );
}
finally {
writer = null;
@ -72,7 +87,7 @@ public class ScriptTargetOutputToFile extends AbstractScriptTargetOutput impleme
}
@SuppressWarnings("ResultOfMethodCallIgnored")
static Writer toFileWriter( File file, String charsetName ) {
static Writer toFileWriter(File file, String charsetName, boolean append) {
try {
if ( ! file.exists() ) {
// best effort, since this is very likely not allowed in EE environments
@ -84,17 +99,17 @@ public class ScriptTargetOutputToFile extends AbstractScriptTargetOutput impleme
}
}
catch (Exception e) {
log.debug( "Exception calling File#createNewFile : " + e.toString() );
log.debug( "Exception calling File#createNewFile : " + e );
}
try {
return charsetName != null ?
new OutputStreamWriter(
new FileOutputStream( file, true ),
new FileOutputStream( file, append ),
charsetName
) :
new OutputStreamWriter( new FileOutputStream(
file,
true
append
) );
}
catch (IOException e) {

View File

@ -28,6 +28,7 @@ public class ScriptTargetOutputToUrl extends AbstractScriptTargetOutput implemen
private final URL url;
private final String charsetName;
private final boolean append;
private Writer writer;
@ -36,10 +37,23 @@ public class ScriptTargetOutputToUrl extends AbstractScriptTargetOutput implemen
*
* @param url The url to read from
* @param charsetName The charset name
* @param append If true, then bytes will be written to the end of the file rather than the beginning
*/
public ScriptTargetOutputToUrl(URL url, String charsetName) {
public ScriptTargetOutputToUrl(URL url, String charsetName, boolean append) {
this.url = url;
this.charsetName = charsetName;
this.append = append;
}
/**
* Constructs a ScriptTargetOutputToUrl instance
* the bytes will be written to the end of the file rather than the beginning
*
* @param url The url to read from
* @param charsetName The charset name
*/
public ScriptTargetOutputToUrl(URL url, String charsetName) {
this( url, charsetName, true );
}
@Override
@ -53,7 +67,7 @@ public class ScriptTargetOutputToUrl extends AbstractScriptTargetOutput implemen
@Override
public void prepare() {
super.prepare();
this.writer = toWriter( url, charsetName );
this.writer = toWriter( url, charsetName, append );
}
@Override
@ -62,17 +76,17 @@ public class ScriptTargetOutputToUrl extends AbstractScriptTargetOutput implemen
writer().close();
}
catch (IOException e) {
throw new SchemaManagementException( "Unable to close file writer : " + e.toString() );
throw new SchemaManagementException( "Unable to close file writer : " + e );
}
}
private static Writer toWriter( URL url, String charsetName ) {
private static Writer toWriter( URL url, String charsetName, boolean append ) {
log.debug( "Attempting to resolve writer for URL : " + url );
// technically only "strings corresponding to file URLs" are supported, which I take to mean URLs whose
// protocol is "file"
try {
return ScriptTargetOutputToFile.toFileWriter( new File( url.toURI() ), charsetName );
return ScriptTargetOutputToFile.toFileWriter( new File( url.toURI() ), charsetName, append );
}
catch (URISyntaxException e) {
throw new SchemaManagementException(

View File

@ -77,7 +77,7 @@ public class SchemaManagementToolCoordinator {
ExceptionHandlerLoggedImpl.INSTANCE
);
performScriptAction( actions.getScriptAction(), metadata, tool, serviceRegistry, executionOptions );
performScriptAction( actions.getScriptAction(), metadata, tool, serviceRegistry, executionOptions, configService );
performDatabaseAction( actions.getDatabaseAction(), metadata, tool, serviceRegistry, executionOptions );
if ( actions.getDatabaseAction() == Action.CREATE_DROP ) {
@ -260,13 +260,15 @@ public class SchemaManagementToolCoordinator {
Metadata metadata,
SchemaManagementTool tool,
ServiceRegistry serviceRegistry,
ExecutionOptions executionOptions) {
ExecutionOptions executionOptions,
ConfigurationService configurationService) {
switch ( scriptAction ) {
case CREATE_ONLY: {
final JpaTargetAndSourceDescriptor createDescriptor = buildScriptTargetDescriptor(
executionOptions.getConfigurationValues(),
CreateSettingSelector.INSTANCE,
serviceRegistry
serviceRegistry,
configurationService
);
tool.getSchemaCreator( executionOptions.getConfigurationValues() ).doCreation(
metadata,
@ -281,7 +283,8 @@ public class SchemaManagementToolCoordinator {
final JpaTargetAndSourceDescriptor dropDescriptor = buildScriptTargetDescriptor(
executionOptions.getConfigurationValues(),
DropSettingSelector.INSTANCE,
serviceRegistry
serviceRegistry,
configurationService
);
tool.getSchemaDropper( executionOptions.getConfigurationValues() ).doDrop(
metadata,
@ -292,7 +295,8 @@ public class SchemaManagementToolCoordinator {
final JpaTargetAndSourceDescriptor createDescriptor = buildScriptTargetDescriptor(
executionOptions.getConfigurationValues(),
CreateSettingSelector.INSTANCE,
serviceRegistry
serviceRegistry,
configurationService
);
tool.getSchemaCreator( executionOptions.getConfigurationValues() ).doCreation(
metadata,
@ -306,7 +310,8 @@ public class SchemaManagementToolCoordinator {
final JpaTargetAndSourceDescriptor dropDescriptor = buildScriptTargetDescriptor(
executionOptions.getConfigurationValues(),
DropSettingSelector.INSTANCE,
serviceRegistry
serviceRegistry,
configurationService
);
tool.getSchemaDropper( executionOptions.getConfigurationValues() ).doDrop(
metadata,
@ -320,7 +325,8 @@ public class SchemaManagementToolCoordinator {
final JpaTargetAndSourceDescriptor migrateDescriptor = buildScriptTargetDescriptor(
executionOptions.getConfigurationValues(),
MigrateSettingSelector.INSTANCE,
serviceRegistry
serviceRegistry,
configurationService
);
tool.getSchemaMigrator( executionOptions.getConfigurationValues() ).doMigration(
metadata,
@ -338,7 +344,8 @@ public class SchemaManagementToolCoordinator {
private static JpaTargetAndSourceDescriptor buildScriptTargetDescriptor(
Map configurationValues,
SettingSelector settingSelector,
ServiceRegistry serviceRegistry) {
ServiceRegistry serviceRegistry,
ConfigurationService configurationService) {
final Object scriptSourceSetting = settingSelector.getScriptSourceSetting( configurationValues );
final SourceType sourceType = SourceType.interpret(
settingSelector.getSourceTypeSetting( configurationValues ),
@ -358,10 +365,13 @@ public class SchemaManagementToolCoordinator {
? Helper.interpretScriptSourceSetting( scriptSourceSetting, serviceRegistry.getService( ClassLoaderService.class ), charsetName )
: null;
boolean append = configurationService.getSetting( AvailableSettings.HBM2DDL_SCRIPTS_CREATE_APPEND, StandardConverters.BOOLEAN, true );
final ScriptTargetOutput scriptTargetOutput = Helper.interpretScriptTargetSetting(
settingSelector.getScriptTargetSetting( configurationValues ),
serviceRegistry.getService( ClassLoaderService.class ),
charsetName
charsetName,
append
);
return new JpaTargetAndSourceDescriptor() {