From 51f83b4501d04445066d9caf8ae9628fecd9b906 Mon Sep 17 00:00:00 2001 From: Robert Goldmann <deadlocker@gmx.de> Date: Wed, 20 Apr 2022 22:28:28 +0200 Subject: [PATCH] #663 - added support for mariadb --- BudgetMasterDatabaseMigrator/pom.xml | 4 + .../databasemigrator/CommandLineOptions.java | 3 +- .../src/main/resources/application.properties | 2 +- BudgetMasterServer/pom.xml | 5 ++ .../budgetmaster/migration/DatabaseType.java | 39 ++++++++ .../migration/MigrationArguments.java | 14 ++- .../migration/MigrationController.java | 8 +- .../migration/MigrationService.java | 2 +- .../migration/MigrationSettings.java | 88 ++++++++++++++++++- .../utils/DatabaseConfiguration.java | 2 +- .../DatabaseConfigurationProperties.java | 6 ++ .../resources/languages/base_de.properties | 3 +- .../resources/languages/base_en.properties | 3 +- .../templates/migration/migration.ftl | 16 ++++ 14 files changed, 183 insertions(+), 12 deletions(-) create mode 100644 BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/migration/DatabaseType.java diff --git a/BudgetMasterDatabaseMigrator/pom.xml b/BudgetMasterDatabaseMigrator/pom.xml index 5e98177fa..e3603b286 100644 --- a/BudgetMasterDatabaseMigrator/pom.xml +++ b/BudgetMasterDatabaseMigrator/pom.xml @@ -41,6 +41,10 @@ <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> </dependency> + <dependency> + <groupId>org.mariadb.jdbc</groupId> + <artifactId>mariadb-java-client</artifactId> + </dependency> <dependency> <groupId>org.projectlombok</groupId> diff --git a/BudgetMasterDatabaseMigrator/src/main/java/de/deadlocker8/budgetmaster/databasemigrator/CommandLineOptions.java b/BudgetMasterDatabaseMigrator/src/main/java/de/deadlocker8/budgetmaster/databasemigrator/CommandLineOptions.java index 966fa806d..88746d544 100644 --- a/BudgetMasterDatabaseMigrator/src/main/java/de/deadlocker8/budgetmaster/databasemigrator/CommandLineOptions.java +++ b/BudgetMasterDatabaseMigrator/src/main/java/de/deadlocker8/budgetmaster/databasemigrator/CommandLineOptions.java @@ -3,7 +3,8 @@ package de.deadlocker8.budgetmaster.databasemigrator; public enum CommandLineOptions { SOURCE_URL("spring.datasource.jdbc-url", "source h2 database JDBC url, e.g. jdbc:h2:/C:/Users/Admin/AppData/Roaming/Deadlocker/BudgetMaster/debug/budgetmaster"), - DESTINATION_URL("spring.seconddatasource.jdbc-url", "destination postresql database JDBC url, e.g. jdbc:postgresql://localhost:5432/budgetmaster"), + DESTINATION_URL("spring.seconddatasource.jdbc-url", "destination database JDBC url (postgres ir mariadb), e.g. jdbc:postgresql://localhost:5432/budgetmaster"), + DESTINATION_DRIVER_CLASS_NAME("spring.seconddatasource.driver-class-name", "destination database driver class name, e.g. org.postgresql.Driver or org.mariadb.jdbc.Driver"), DESTINATION_USER_NAME("spring.seconddatasource.username", "destination postresql user name, e.g. budgetmaster"), DESTINATION_PASSWORD("spring.seconddatasource.password", "destination postresql password, e.g. BudgetMaster"); diff --git a/BudgetMasterDatabaseMigrator/src/main/resources/application.properties b/BudgetMasterDatabaseMigrator/src/main/resources/application.properties index 8f534251f..8c007825b 100644 --- a/BudgetMasterDatabaseMigrator/src/main/resources/application.properties +++ b/BudgetMasterDatabaseMigrator/src/main/resources/application.properties @@ -7,7 +7,7 @@ spring.datasource.driver-class-name=org.h2.Driver #spring.seconddatasource.jdbc-url= #spring.seconddatasource.username= #spring.seconddatasource.password= -spring.seconddatasource.driver-class-name=org.postgresql.Driver +#spring.seconddatasource.driver-class-name= spring.jpa.database=default spring.jpa.show-sql=false diff --git a/BudgetMasterServer/pom.xml b/BudgetMasterServer/pom.xml index 2aee70c85..4425e571d 100644 --- a/BudgetMasterServer/pom.xml +++ b/BudgetMasterServer/pom.xml @@ -110,6 +110,11 @@ <artifactId>postgresql</artifactId> </dependency> + <dependency> + <groupId>org.mariadb.jdbc</groupId> + <artifactId>mariadb-java-client</artifactId> + </dependency> + <dependency> <groupId>com.itextpdf</groupId> <artifactId>itextpdf</artifactId> diff --git a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/migration/DatabaseType.java b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/migration/DatabaseType.java new file mode 100644 index 000000000..df5e54567 --- /dev/null +++ b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/migration/DatabaseType.java @@ -0,0 +1,39 @@ +package de.deadlocker8.budgetmaster.migration; + +public enum DatabaseType +{ + POSTGRESQL("PostgreSQL", "org.postgresql.Driver"), + MARIADB("MariaDB", "org.mariadb.jdbc.Driver"); + + private final String name; + private final String driverClassName; + + DatabaseType(String name, String driverClassName) + { + this.name = name; + this.driverClassName = driverClassName; + } + + public String getName() + { + return name; + } + + public String getDriverClassName() + { + return driverClassName; + } + + public static DatabaseType fromName(String name) + { + for(DatabaseType type : values()) + { + if(type.getName().equalsIgnoreCase(name)) + { + return type; + } + } + + return null; + } +} \ No newline at end of file diff --git a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/migration/MigrationArguments.java b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/migration/MigrationArguments.java index b19d71f50..a105cf0af 100644 --- a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/migration/MigrationArguments.java +++ b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/migration/MigrationArguments.java @@ -3,6 +3,7 @@ package de.deadlocker8.budgetmaster.migration; import java.text.MessageFormat; import java.util.ArrayList; import java.util.List; +import java.util.Locale; public class MigrationArguments { @@ -10,6 +11,7 @@ public class MigrationArguments { private String sourceUrl; private String destinationUrl; + private String destinationDriverClassName; private String destinationUsername; private String destinationPassword; @@ -20,9 +22,10 @@ public class MigrationArguments return this; } - public MigrationArgumentBuilder withDestinationUrl(String hostname, Integer port, String databaseName) + public MigrationArgumentBuilder withDestinationUrl(DatabaseType databaseType, String hostname, Integer port, String databaseName) { - this.destinationUrl = MessageFormat.format("jdbc:postgresql://{0}:{1,number,#}/{2}", hostname, port, databaseName); + this.destinationDriverClassName = databaseType.getDriverClassName(); + this.destinationUrl = MessageFormat.format("jdbc:{0}://{1}:{2,number,#}/{3}", databaseType.getName().toLowerCase(), hostname, port, databaseName); return this; } @@ -35,19 +38,21 @@ public class MigrationArguments public MigrationArguments build() { - return new MigrationArguments(sourceUrl, destinationUrl, destinationUsername, destinationPassword); + return new MigrationArguments(sourceUrl, destinationUrl, destinationDriverClassName, destinationUsername, destinationPassword); } } private final String sourceUrl; private final String destinationUrl; + private final String destinationDriverClassName; private final String destinationUsername; private final String destinationPassword; - private MigrationArguments(String sourceUrl, String destinationUrl, String destinationUsername, String destinationPassword) + private MigrationArguments(String sourceUrl, String destinationUrl, String driverClassName, String destinationUsername, String destinationPassword) { this.sourceUrl = sourceUrl; this.destinationUrl = destinationUrl; + this.destinationDriverClassName = driverClassName; this.destinationUsername = destinationUsername; this.destinationPassword = destinationPassword; } @@ -57,6 +62,7 @@ public class MigrationArguments final ArrayList<String> arguments = new ArrayList<>(); arguments.add(MessageFormat.format("--spring.datasource.jdbc-url={0}", sourceUrl)); arguments.add(MessageFormat.format("--spring.seconddatasource.jdbc-url={0}", destinationUrl)); + arguments.add(MessageFormat.format("--spring.seconddatasource.driver-class-name={0}", destinationDriverClassName)); arguments.add(MessageFormat.format("--spring.seconddatasource.username={0}", destinationUsername)); arguments.add(MessageFormat.format("--spring.seconddatasource.password={0}", destinationPassword)); return arguments; diff --git a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/migration/MigrationController.java b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/migration/MigrationController.java index 17cc1df1c..4103efd70 100644 --- a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/migration/MigrationController.java +++ b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/migration/MigrationController.java @@ -14,6 +14,7 @@ import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest; import javax.validation.Valid; +import java.util.List; @Controller @@ -26,6 +27,7 @@ public class MigrationController extends BaseController public static final String MIGRATION_SETTINGS = "migrationSettings"; public static final String STATUS = "status"; public static final String SUMMARY = "summary"; + public static final String DATABASE_TYPES = "databaseTypes"; } private static class ReturnValues @@ -59,14 +61,17 @@ public class MigrationController extends BaseController public String migrate(Model model) { model.addAttribute(ModelAttributes.MIGRATION_SETTINGS, migrationService.getPrefilledMigrationSettings()); + model.addAttribute(ModelAttributes.DATABASE_TYPES, List.of(DatabaseType.values())); return ReturnValues.MIGRATION_SETTINGS; } @PostMapping public String post(Model model, @ModelAttribute("MigrationSettings") @Valid MigrationSettings migrationSettings, BindingResult bindingResult, + @RequestParam(value = "databaseTypeName") String databaseTypeName, @RequestParam(value = "verificationPassword") String verificationPassword) { + migrationSettings.setDatabaseType(DatabaseType.fromName(databaseTypeName)); final MigrationSettingsValidator migrationSettingsValidator = new MigrationSettingsValidator(); migrationSettingsValidator.validate(migrationSettings, bindingResult); @@ -82,12 +87,13 @@ public class MigrationController extends BaseController if(bindingResult.hasErrors()) { model.addAttribute(ModelAttributes.ERROR, bindingResult); + model.addAttribute(ModelAttributes.DATABASE_TYPES, List.of(DatabaseType.values())); return ReturnValues.MIGRATION_SETTINGS; } final MigrationArguments migrationArguments = new MigrationArguments.MigrationArgumentBuilder() .withSourceUrl(migrationService.getDatabaseFromPreviousVersionPathWithoutExtension().toString()) - .withDestinationUrl(migrationSettings.hostname(), migrationSettings.port(), migrationSettings.databaseName()) + .withDestinationUrl(migrationSettings.databaseType(), migrationSettings.hostname(), migrationSettings.port(), migrationSettings.databaseName()) .withDestinationCredentials(migrationSettings.username(), migrationSettings.password()) .build(); migrationService.startMigration(migrationArguments); diff --git a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/migration/MigrationService.java b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/migration/MigrationService.java index b5aaf0f91..493c73e80 100644 --- a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/migration/MigrationService.java +++ b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/migration/MigrationService.java @@ -50,7 +50,7 @@ public class MigrationService public MigrationSettings getPrefilledMigrationSettings() { - return new MigrationSettings(databaseConfig.getHostname(), databaseConfig.getPort(), databaseConfig.getDatabaseName(), databaseConfig.getUsername(), databaseConfig.getPassword()); + return new MigrationSettings(databaseConfig.getHostname(), databaseConfig.getPort(), databaseConfig.getDatabaseName(), databaseConfig.getUsername(), databaseConfig.getPassword(), databaseConfig.getDatabaseType()); } public boolean needToShowMigrationDialog(String loadedPage) diff --git a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/migration/MigrationSettings.java b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/migration/MigrationSettings.java index c909cb3fa..b4f9682ac 100644 --- a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/migration/MigrationSettings.java +++ b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/migration/MigrationSettings.java @@ -1,5 +1,91 @@ package de.deadlocker8.budgetmaster.migration; -public record MigrationSettings(String hostname, Integer port, String databaseName, String username, String password) +import java.util.Objects; + +public final class MigrationSettings { + private final String hostname; + private final Integer port; + private final String databaseName; + private final String username; + private final String password; + private DatabaseType databaseType; + + public MigrationSettings(String hostname, Integer port, String databaseName, String username, String password, DatabaseType databaseType) + { + this.hostname = hostname; + this.port = port; + this.databaseName = databaseName; + this.username = username; + this.password = password; + this.databaseType = databaseType; + } + + public String hostname() + { + return hostname; + } + + public Integer port() + { + return port; + } + + public String databaseName() + { + return databaseName; + } + + public String username() + { + return username; + } + + public String password() + { + return password; + } + + public DatabaseType databaseType() + { + return databaseType; + } + + public void setDatabaseType(DatabaseType databaseType) + { + this.databaseType = databaseType; + } + + @Override + public boolean equals(Object obj) + { + if(obj == this) return true; + if(obj == null || obj.getClass() != this.getClass()) return false; + var that = (MigrationSettings) obj; + return Objects.equals(this.hostname, that.hostname) && + Objects.equals(this.port, that.port) && + Objects.equals(this.databaseName, that.databaseName) && + Objects.equals(this.username, that.username) && + Objects.equals(this.password, that.password) && + Objects.equals(this.databaseType, that.databaseType); + } + + @Override + public int hashCode() + { + return Objects.hash(hostname, port, databaseName, username, password, databaseType); + } + + @Override + public String toString() + { + return "MigrationSettings[" + + "hostname=" + hostname + ", " + + "port=" + port + ", " + + "databaseName=" + databaseName + ", " + + "username=" + username + ", " + + "password=" + password + ", " + + "databaseType=" + databaseType + ']'; + } + } diff --git a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/utils/DatabaseConfiguration.java b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/utils/DatabaseConfiguration.java index f1bd49f16..c34e996f2 100644 --- a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/utils/DatabaseConfiguration.java +++ b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/utils/DatabaseConfiguration.java @@ -41,7 +41,7 @@ public class DatabaseConfiguration .username(databaseConfig.getUsername()) .password(databaseConfig.getPassword()) .url(jdbcString) - .driverClassName(MessageFormat.format("org.{0}.Driver", databaseConfig.getType())) + .driverClassName(databaseConfig.getDatabaseType().getDriverClassName()) .build(); } else diff --git a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/utils/DatabaseConfigurationProperties.java b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/utils/DatabaseConfigurationProperties.java index 0bf84b162..deba17314 100644 --- a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/utils/DatabaseConfigurationProperties.java +++ b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/utils/DatabaseConfigurationProperties.java @@ -1,5 +1,6 @@ package de.deadlocker8.budgetmaster.utils; +import de.deadlocker8.budgetmaster.migration.DatabaseType; import org.springframework.boot.context.properties.ConfigurationProperties; import javax.validation.constraints.Max; @@ -38,6 +39,11 @@ public class DatabaseConfigurationProperties return type; } + public DatabaseType getDatabaseType() + { + return DatabaseType.fromName(type); + } + public void setType(String type) { this.type = type; diff --git a/BudgetMasterServer/src/main/resources/languages/base_de.properties b/BudgetMasterServer/src/main/resources/languages/base_de.properties index ad1ca8120..6bd31dac8 100644 --- a/BudgetMasterServer/src/main/resources/languages/base_de.properties +++ b/BudgetMasterServer/src/main/resources/languages/base_de.properties @@ -638,9 +638,10 @@ import.entity.chart=Es werden nur die benutzerdefinierten Diagramme importiert.< copied=Kopiert! -migration.settings.description=Alle Daten aus deiner bestehenden BudgetMaster Datenbank werden in die neue Datenbank migriert.<br> Bitte gib die Einstellungen für das neue Datenbank-Backend (z.B. postgresql) ein.<br><br><span class="bold">Bitte stelle sicher, dass deine Datenbank mindestens einmal mit BudgetMaster v2.9.2 geöffnet wurde, bevor du diese Migration durchführst!</span> +migration.settings.description=Alle Daten aus deiner bestehenden BudgetMaster Datenbank werden in die neue Datenbank migriert.<br> Bitte gib die Einstellungen für das neue Datenbank-Backend (z.B. postgresql) ein.<br><br><span class="bold">Bitte stelle sicher, dass deine bestehende Datenbank mindestens einmal mit BudgetMaster v2.9.2 geöffnet wurde, bevor du diese Migration durchführst!</span> migration.settings.description.warning=Alle vorhandenen Daten der Zieldatenbank werden unwiderruflich gelöscht! migration.settings.description.info=Die Einstellungen werden mit der aktuell verwendeten Datenbank vorbefüllt. +migration.settings.databaseType=Datenbanktyp migration.settings.hostname=Hostname migration.settings.port=Port migration.settings.databaseName=Datenbankname diff --git a/BudgetMasterServer/src/main/resources/languages/base_en.properties b/BudgetMasterServer/src/main/resources/languages/base_en.properties index 4a8e50b8e..c79600afc 100644 --- a/BudgetMasterServer/src/main/resources/languages/base_en.properties +++ b/BudgetMasterServer/src/main/resources/languages/base_en.properties @@ -637,9 +637,10 @@ import.entity.chart=Only user-defined charts will be imported.<br>The import of copied=Copied! -migration.settings.description=All data from your existing BudgetMaster database will be migrated to the new database.<br>Please enter the settings for the new database backend (e.g. postgresql).<br><br><span class="bold">Please make sure your database has been opened at least once with BudgetMaster v2.9.2 before running this migration!</span> +migration.settings.description=All data from your existing BudgetMaster database will be migrated to the new database.<br>Please enter the settings for the new database backend (e.g. postgresql).<br><br><span class="bold">Please make sure your existing database has been opened at least once with BudgetMaster v2.9.2 before running this migration!</span> migration.settings.description.warning=All existing data of the target database will be permanently deleted! migration.settings.description.info=The settings are prefilled with the currently used database. +migration.settings.databaseType=Database type migration.settings.hostname=Hostname migration.settings.port=Port migration.settings.databaseName=Database name diff --git a/BudgetMasterServer/src/main/resources/templates/migration/migration.ftl b/BudgetMasterServer/src/main/resources/templates/migration/migration.ftl index 9a470f388..79bf0559e 100644 --- a/BudgetMasterServer/src/main/resources/templates/migration/migration.ftl +++ b/BudgetMasterServer/src/main/resources/templates/migration/migration.ftl @@ -51,6 +51,22 @@ </div> </div> + <div class="row"> + <div class="input-field col s12 m12 l8 offset-l2"> + <i class="material-icons prefix">widgets</i> + <select id="migration-database-type" name="databaseTypeName"> + <#list databaseTypes as databaseType> + <#if migrationSettings.databaseType() == databaseType> + <option selected value="${databaseType.getName()}">${databaseType.getName()}</option> + <#else> + <option value="${databaseType.getName()}">${databaseType.getName()}</option> + </#if> + </#list> + </select> + <label for="migration-database-type">${locale.getString("migration.settings.databaseType")}</label> + </div> + </div> + <div class="row"> <div class="input-field col s12 m12 l8 offset-l2"> <i class="material-icons prefix">public</i> -- GitLab