Skip to content

Commit 57d9afa

Browse files
committed
update hibernate orm config persistence unit doc to include supporting zip files as import files.
unzip zip files in hibernate HBM2DDL_IMPORT_FILES setting.
1 parent 75b67ec commit 57d9afa

19 files changed

+227
-1
lines changed

docs/src/main/asciidoc/hibernate-orm.adoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -739,6 +739,7 @@ your entity changes or any change to your `import.sql` is immediately picked up
739739
====
740740
By default, in `dev` and `test` modes, Hibernate ORM, upon boot, will read and execute the SQL statements in the `/import.sql` file (if present).
741741
You can change the file name by changing the property `quarkus.hibernate-orm.sql-load-script` in `application.properties`.
742+
You can also provide a `.zip` file in the same way which should contain only the files containing the sql statements to be executed.
742743
====
743744

744745
The second approach is to use `quarkus.hibernate-orm.database.generation=update`.

extensions/hibernate-orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/HibernateOrmConfigPersistenceUnit.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ public interface HibernateOrmConfigPersistenceUnit {
7474
*
7575
* [NOTE]
7676
* ====
77-
* Quarkus supports `.sql` file with SQL statements or comments spread over multiple lines.
77+
* Quarkus supports files with SQL statements or comments spread over multiple lines,
78+
* or `.zip` files containing those files.
7879
* Each SQL statement must be terminated by a semicolon.
7980
* ====
8081
*
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package io.quarkus.hibernate.orm.sql_load_script;
2+
3+
import org.hamcrest.Matchers;
4+
import org.junit.jupiter.api.Test;
5+
import org.junit.jupiter.api.extension.RegisterExtension;
6+
7+
import io.quarkus.hibernate.orm.MyEntity;
8+
import io.quarkus.test.QuarkusUnitTest;
9+
import io.restassured.RestAssured;
10+
11+
public class ImportMultipleSqlLoadScriptsAsZipFileTestCase {
12+
@RegisterExtension
13+
static QuarkusUnitTest runner = new QuarkusUnitTest()
14+
.withApplicationRoot((jar) -> jar
15+
.addClasses(MyEntity.class, SqlLoadScriptTestResource.class)
16+
.addAsResource("application-multiple-load-script-files-as-zip-file-test.properties",
17+
"application.properties")
18+
.addAsResource("multiple-load-script-files.zip"));
19+
20+
@Test
21+
public void testMultipleLoadScriptFilesAsZipFile() {
22+
String name1 = "import-1.sql load script entity";
23+
String name2 = "import-2.sql load script entity";
24+
25+
RestAssured.when().get("/orm-sql-load-script/1").then().body(Matchers.is(name1));
26+
RestAssured.when().get("/orm-sql-load-script/2").then().body(Matchers.is(name2));
27+
}
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package io.quarkus.hibernate.orm.sql_load_script;
2+
3+
import org.hamcrest.Matchers;
4+
import org.junit.jupiter.api.Test;
5+
import org.junit.jupiter.api.extension.RegisterExtension;
6+
7+
import io.quarkus.hibernate.orm.MyEntity;
8+
import io.quarkus.test.QuarkusUnitTest;
9+
import io.restassured.RestAssured;
10+
11+
public class ImportSqlLoadScriptAsZipFileTestCase {
12+
@RegisterExtension
13+
static QuarkusUnitTest runner = new QuarkusUnitTest()
14+
.withApplicationRoot((jar) -> jar
15+
.addClasses(MyEntity.class, SqlLoadScriptTestResource.class)
16+
.addAsResource("application-load-script-as-zip-file-test.properties", "application.properties")
17+
.addAsResource("load-script-test.zip"));
18+
19+
@Test
20+
public void testSqlLoadScriptAsZipFile() {
21+
String name = "other-load-script sql load script entity";
22+
RestAssured.when().get("/orm-sql-load-script/3").then().body(Matchers.is(name));
23+
}
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package io.quarkus.hibernate.orm.sql_load_script;
2+
3+
import org.hamcrest.Matchers;
4+
import org.junit.jupiter.api.Test;
5+
import org.junit.jupiter.api.extension.RegisterExtension;
6+
7+
import io.quarkus.hibernate.orm.MyEntity;
8+
import io.quarkus.test.QuarkusUnitTest;
9+
import io.restassured.RestAssured;
10+
11+
public class ImportSqlLoadScriptsAsMultipleZipFilesTestCase {
12+
@RegisterExtension
13+
static QuarkusUnitTest runner = new QuarkusUnitTest()
14+
.withApplicationRoot((jar) -> jar
15+
.addClasses(MyEntity.class, SqlLoadScriptTestResource.class)
16+
.addAsResource("application-load-scripts-as-multiple-zip-files-test.properties",
17+
"application.properties")
18+
.addAsResource("import-multiple-load-scripts-1.zip")
19+
.addAsResource("import-multiple-load-scripts-2.zip"));
20+
21+
@Test
22+
public void testSqlLoadScriptsAsMultipleZipFiles() {
23+
String name1 = "import-1.sql load script entity";
24+
String name2 = "import-2.sql load script entity";
25+
26+
RestAssured.when().get("/orm-sql-load-script/1").then().body(Matchers.is(name1));
27+
RestAssured.when().get("/orm-sql-load-script/2").then().body(Matchers.is(name2));
28+
}
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package io.quarkus.hibernate.orm.sql_load_script;
2+
3+
import org.hamcrest.Matchers;
4+
import org.junit.jupiter.api.Test;
5+
import org.junit.jupiter.api.extension.RegisterExtension;
6+
7+
import io.quarkus.hibernate.orm.MyEntity;
8+
import io.quarkus.test.QuarkusUnitTest;
9+
import io.restassured.RestAssured;
10+
11+
public class ImportSqlLoadScriptsAsZipFilesAndSqlFileTestCase {
12+
@RegisterExtension
13+
static QuarkusUnitTest runner = new QuarkusUnitTest()
14+
.withApplicationRoot((jar) -> jar
15+
.addClasses(MyEntity.class, SqlLoadScriptTestResource.class)
16+
.addAsResource("application-load-scripts-as-multiple-zip-files-and-sql-file-test.properties",
17+
"application.properties")
18+
.addAsResource("load-script-test.sql")
19+
.addAsResource("import-multiple-load-scripts-1.zip")
20+
.addAsResource("import-multiple-load-scripts-2.zip"));
21+
22+
@Test
23+
public void testSqlLoadScriptsAsZipFilesAndSqlFile() {
24+
String name = "other-load-script sql load script entity";
25+
String name1 = "import-1.sql load script entity";
26+
String name2 = "import-2.sql load script entity";
27+
28+
RestAssured.when().get("/orm-sql-load-script/1").then().body(Matchers.is(name1));
29+
RestAssured.when().get("/orm-sql-load-script/2").then().body(Matchers.is(name2));
30+
RestAssured.when().get("/orm-sql-load-script/3").then().body(Matchers.is(name));
31+
}
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
quarkus.datasource.db-kind=h2
2+
quarkus.datasource.jdbc.url=jdbc:h2:mem:test
3+
4+
quarkus.hibernate-orm.database.generation=drop-and-create
5+
quarkus.hibernate-orm.sql-load-script=load-script-test.zip
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
quarkus.datasource.db-kind=h2
2+
quarkus.datasource.jdbc.url=jdbc:h2:mem:test
3+
4+
quarkus.hibernate-orm.database.generation=drop-and-create
5+
quarkus.hibernate-orm.sql-load-script=load-script-test.sql, import-multiple-load-scripts-1.zip, import-multiple-load-scripts-2.zip
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
quarkus.datasource.db-kind=h2
2+
quarkus.datasource.jdbc.url=jdbc:h2:mem:test
3+
4+
quarkus.hibernate-orm.database.generation=drop-and-create
5+
quarkus.hibernate-orm.sql-load-script=import-multiple-load-scripts-1.zip, import-multiple-load-scripts-2.zip
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
quarkus.datasource.db-kind=h2
2+
quarkus.datasource.jdbc.url=jdbc:h2:mem:test
3+
4+
quarkus.hibernate-orm.database.generation=drop-and-create
5+
quarkus.hibernate-orm.sql-load-script=multiple-load-script-files.zip
Binary file not shown.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package io.quarkus.hibernate.orm.runtime;
2+
3+
public final class Constants {
4+
public static final String COMMA = ",";
5+
public static final String ZIP_FILE_EXTENSION = ".zip";
6+
public static final String SQL_LOAD_SCRIPT_UNZIPPED_DIR_PREFIX = "import-sql-unzip-";
7+
8+
private Constants() {
9+
}
10+
}

extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/FastBootHibernatePersistenceProvider.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ private RuntimeSettings buildRuntimeSettings(String persistenceUnitName, Recorde
208208
final BuildTimeSettings buildTimeSettings = recordedState.getBuildTimeSettings();
209209
final IntegrationSettings integrationSettings = recordedState.getIntegrationSettings();
210210
Builder runtimeSettingsBuilder = new Builder(buildTimeSettings, integrationSettings);
211+
unzipZipFilesAndReplaceZipsInImportFiles(runtimeSettingsBuilder);
211212

212213
Optional<String> dataSourceName = recordedState.getBuildTimeSettings().getSource().getDataSource();
213214
if (dataSourceName.isPresent()) {
@@ -288,6 +289,12 @@ private RuntimeSettings buildRuntimeSettings(String persistenceUnitName, Recorde
288289
return runtimeSettingsBuilder.build();
289290
}
290291

292+
private void unzipZipFilesAndReplaceZipsInImportFiles(Builder runtimeSettingsBuilder) {
293+
String newValue = SchemaToolingUtil.unzipZipFilesAndReplaceZips(
294+
(String) runtimeSettingsBuilder.get(AvailableSettings.HBM2DDL_IMPORT_FILES));
295+
runtimeSettingsBuilder.put(AvailableSettings.HBM2DDL_IMPORT_FILES, newValue);
296+
}
297+
291298
private StandardServiceRegistry rewireMetadataAndExtractServiceRegistry(String persistenceUnitName, RecordedState rs,
292299
HibernateOrmRuntimeConfigPersistenceUnit puConfig, RuntimeSettings runtimeSettings) {
293300
PreconfiguredServiceRegistryBuilder serviceRegistryBuilder = new PreconfiguredServiceRegistryBuilder(
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package io.quarkus.hibernate.orm.runtime;
2+
3+
import static io.quarkus.hibernate.orm.runtime.Constants.COMMA;
4+
import static io.quarkus.hibernate.orm.runtime.Constants.SQL_LOAD_SCRIPT_UNZIPPED_DIR_PREFIX;
5+
import static io.quarkus.hibernate.orm.runtime.Constants.ZIP_FILE_EXTENSION;
6+
7+
import java.net.URL;
8+
import java.nio.file.DirectoryStream;
9+
import java.nio.file.Files;
10+
import java.nio.file.Path;
11+
import java.nio.file.Paths;
12+
import java.util.LinkedList;
13+
import java.util.List;
14+
15+
import org.jboss.logging.Logger;
16+
17+
import io.quarkus.fs.util.ZipUtils;
18+
19+
public class SchemaToolingUtil {
20+
private static final Logger log = Logger.getLogger(SchemaToolingUtil.class);
21+
22+
public static String unzipZipFilesAndReplaceZips(String commaSeparatedFileNames) {
23+
List<String> unzippedFilesNames = new LinkedList<>();
24+
if (commaSeparatedFileNames != null) {
25+
String[] fileNames = commaSeparatedFileNames.split(COMMA);
26+
for (String fileName : fileNames) {
27+
if (fileName.endsWith(ZIP_FILE_EXTENSION)) {
28+
try {
29+
Path unzipDir = Files.createTempDirectory(SQL_LOAD_SCRIPT_UNZIPPED_DIR_PREFIX);
30+
URL resource = Thread.currentThread()
31+
.getContextClassLoader()
32+
.getResource(fileName);
33+
Path zipFile = Paths.get(resource.toURI());
34+
ZipUtils.unzip(zipFile, unzipDir);
35+
try (DirectoryStream<Path> paths = Files.newDirectoryStream(unzipDir)) {
36+
for (Path path : paths) {
37+
unzippedFilesNames.add(path.toAbsolutePath().toUri().toString());
38+
}
39+
}
40+
} catch (Exception e) {
41+
log.errorf("Error unzipping import file %s: %s", fileName, e.getMessage());
42+
throw new IllegalStateException(e);
43+
}
44+
} else {
45+
unzippedFilesNames.add(fileName);
46+
}
47+
}
48+
return String.join(COMMA, unzippedFilesNames);
49+
} else {
50+
return null;
51+
}
52+
}
53+
}

extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/service/FlatClassLoaderService.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package io.quarkus.hibernate.orm.runtime.service;
22

3+
import java.io.File;
34
import java.io.IOException;
45
import java.io.InputStream;
56
import java.lang.reflect.InvocationHandler;
7+
import java.net.MalformedURLException;
68
import java.net.URL;
79
import java.util.ArrayList;
810
import java.util.Collection;
@@ -41,6 +43,17 @@ public <T> Class<T> classForName(String className) {
4143

4244
@Override
4345
public URL locateResource(String name) {
46+
if (name.startsWith("file://")) {
47+
try {
48+
var file = new File(name.substring(7));
49+
log.tracef("Successfully loaded resource '%s' from file", name);
50+
return file.toURI().toURL();
51+
} catch (MalformedURLException e) {
52+
log.errorf("Error while trying to load resource %s from file", name);
53+
throw new IllegalArgumentException(e);
54+
}
55+
}
56+
4457
URL resource = getClassLoader().getResource(name);
4558
if (resource == null) {
4659
log.debugf(

extensions/hibernate-reactive/runtime/src/main/java/io/quarkus/hibernate/reactive/runtime/FastBootHibernateReactivePersistenceProvider.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import io.quarkus.hibernate.orm.runtime.PersistenceUnitsHolder;
4242
import io.quarkus.hibernate.orm.runtime.RuntimeSettings;
4343
import io.quarkus.hibernate.orm.runtime.RuntimeSettings.Builder;
44+
import io.quarkus.hibernate.orm.runtime.SchemaToolingUtil;
4445
import io.quarkus.hibernate.orm.runtime.boot.QuarkusPersistenceUnitDescriptor;
4546
import io.quarkus.hibernate.orm.runtime.integration.HibernateOrmIntegrationRuntimeDescriptor;
4647
import io.quarkus.hibernate.orm.runtime.integration.HibernateOrmIntegrationRuntimeInitListener;
@@ -158,6 +159,7 @@ private EntityManagerFactoryBuilder getEntityManagerFactoryBuilderOrNull(String
158159
final IntegrationSettings integrationSettings = recordedState.getIntegrationSettings();
159160
RuntimeSettings.Builder runtimeSettingsBuilder = new RuntimeSettings.Builder(buildTimeSettings,
160161
integrationSettings);
162+
unzipZipFilesAndReplaceZipsInImportFiles(runtimeSettingsBuilder);
161163

162164
var puConfig = hibernateOrmRuntimeConfig.persistenceUnits().get(persistenceUnit.getConfigurationName());
163165
if (puConfig.active().isPresent() && !puConfig.active().get()) {
@@ -224,6 +226,12 @@ private EntityManagerFactoryBuilder getEntityManagerFactoryBuilderOrNull(String
224226
return null;
225227
}
226228

229+
private void unzipZipFilesAndReplaceZipsInImportFiles(Builder runtimeSettingsBuilder) {
230+
String newValue = SchemaToolingUtil.unzipZipFilesAndReplaceZips(
231+
(String) runtimeSettingsBuilder.get(AvailableSettings.HBM2DDL_IMPORT_FILES));
232+
runtimeSettingsBuilder.put(AvailableSettings.HBM2DDL_IMPORT_FILES, newValue);
233+
}
234+
227235
private StandardServiceRegistry rewireMetadataAndExtractServiceRegistry(String persistenceUnitName, RecordedState rs,
228236
RuntimeSettings runtimeSettings, HibernateOrmRuntimeConfigPersistenceUnit puConfig) {
229237
PreconfiguredReactiveServiceRegistryBuilder serviceRegistryBuilder = new PreconfiguredReactiveServiceRegistryBuilder(

0 commit comments

Comments
 (0)