diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0a177be100..d0580124b2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,7 +8,8 @@ Not yet released
### New features
-* None yet
+* Fire CDI event for `CriteriaBuilderConfiguration` on boot also in Quarkus integration
+* Create custom integrations for Hibernate 5.5 and 5.6 to avoid confusion
### Bug fixes
@@ -18,6 +19,7 @@ Not yet released
### Backwards-incompatible changes
* Throw exception if non-streaming capable object builder is used for streaming
+* Replace `blaze-persistence-integration-hibernate-5.4-jakarta` with `blaze-persistence-integration-hibernate-5.5-jakarta`
## 1.6.4
diff --git a/core/testsuite/pom.xml b/core/testsuite/pom.xml
index de5e1addd0..f567c04a38 100644
--- a/core/testsuite/pom.xml
+++ b/core/testsuite/pom.xml
@@ -1669,7 +1669,7 @@
${project.groupId}
- blaze-persistence-integration-hibernate-5.4
+ blaze-persistence-integration-hibernate-5.5
test
@@ -1801,7 +1801,7 @@
${project.groupId}
- blaze-persistence-integration-hibernate-5.4
+ blaze-persistence-integration-hibernate-5.6
test
@@ -2694,26 +2694,26 @@
org.hibernate
hibernate-entitymanager
- ${version.hibernate-5.4}
+ ${version.hibernate-5.6}
org.hibernate
hibernate-envers
- ${version.hibernate-5.4}
+ ${version.hibernate-5.6}
org.hibernate
hibernate-testing
- ${version.hibernate-5.4}
+ ${version.hibernate-5.6}
com.vladmihalcea
- hibernate-types-52
+ hibernate-types-55
${version.hibernate-types}
${project.groupId}
- blaze-persistence-integration-hibernate-5.4
+ blaze-persistence-integration-hibernate-5.6
test
@@ -2725,7 +2725,7 @@
org.hibernate
hibernate-jpamodelgen
- ${version.hibernate-5.4}
+ ${version.hibernate-5.6}
provided
@@ -2789,7 +2789,7 @@
org.hibernate
hibernate-jpamodelgen
- ${version.hibernate-5.4}
+ ${version.hibernate-5.6}
jakarta.xml.bind
diff --git a/dist/bom/pom.xml b/dist/bom/pom.xml
index ce0f9d514c..a4165bdf70 100644
--- a/dist/bom/pom.xml
+++ b/dist/bom/pom.xml
@@ -211,7 +211,25 @@
${project.groupId}
- blaze-persistence-integration-hibernate-5.4-jakarta
+ blaze-persistence-integration-hibernate-5.5
+ ${project.version}
+ runtime
+
+
+ ${project.groupId}
+ blaze-persistence-integration-hibernate-5.5-jakarta
+ ${project.version}
+ runtime
+
+
+ ${project.groupId}
+ blaze-persistence-integration-hibernate-5.6
+ ${project.version}
+ runtime
+
+
+ ${project.groupId}
+ blaze-persistence-integration-hibernate-5.6-jakarta
${project.version}
runtime
diff --git a/dist/full/pom.xml b/dist/full/pom.xml
index 7742a87fc0..d86fd25262 100644
--- a/dist/full/pom.xml
+++ b/dist/full/pom.xml
@@ -105,6 +105,22 @@
${project.groupId}
blaze-persistence-integration-hibernate-5.4
+
+ ${project.groupId}
+ blaze-persistence-integration-hibernate-5.5
+
+
+ ${project.groupId}
+ blaze-persistence-integration-hibernate-5.5-jakarta
+
+
+ ${project.groupId}
+ blaze-persistence-integration-hibernate-5.6
+
+
+ ${project.groupId}
+ blaze-persistence-integration-hibernate-5.6-jakarta
+
${project.groupId}
blaze-persistence-integration-hibernate-6.0
diff --git a/documentation/src/main/asciidoc/core/manual/en_US/getting_started.adoc b/documentation/src/main/asciidoc/core/manual/en_US/getting_started.adoc
index 9ee5636732..d6f7c84671 100644
--- a/documentation/src/main/asciidoc/core/manual/en_US/getting_started.adoc
+++ b/documentation/src/main/asciidoc/core/manual/en_US/getting_started.adoc
@@ -76,25 +76,60 @@ or if you are using Jakarta JPA
Depending on the JPA provider that should be used, one of the following integrations is required
-[[maven-setup-hibernate54-jakarta]]
-===== Hibernate 5.4+ Jakarta
+[[maven-setup-hibernate56-jakarta]]
+===== Hibernate 5.6+ Jakarta
-This integration works for Hibernate 5.4, 5.5 and 5.6
+[source,xml]
+----
+
+ com.blazebit
+ blaze-persistence-integration-hibernate-5.6-jakarta
+ ${blaze-persistence.version}
+ runtime
+
+----
+
+[[maven-setup-hibernate56]]
+===== Hibernate 5.6
[source,xml]
----
com.blazebit
- blaze-persistence-integration-hibernate-5.4-jakarta
+ blaze-persistence-integration-hibernate-5.6
${blaze-persistence.version}
runtime
----
-[[maven-setup-hibernate54]]
-===== Hibernate 5.4+
+[[maven-setup-hibernate55-jakarta]]
+===== Hibernate 5.5 Jakarta
+
+[source,xml]
+----
+
+ com.blazebit
+ blaze-persistence-integration-hibernate-5.5-jakarta
+ ${blaze-persistence.version}
+ runtime
+
+----
-This integration works for Hibernate 5.4, 5.5 and 5.6
+[[maven-setup-hibernate55]]
+===== Hibernate 5.5
+
+[source,xml]
+----
+
+ com.blazebit
+ blaze-persistence-integration-hibernate-5.5
+ ${blaze-persistence.version}
+ runtime
+
+----
+
+[[maven-setup-hibernate54]]
+===== Hibernate 5.4
[source,xml]
----
diff --git a/documentation/src/main/asciidoc/core/manual/en_US/querydsl.adoc b/documentation/src/main/asciidoc/core/manual/en_US/querydsl.adoc
index 512a407f84..a1e8e281cb 100644
--- a/documentation/src/main/asciidoc/core/manual/en_US/querydsl.adoc
+++ b/documentation/src/main/asciidoc/core/manual/en_US/querydsl.adoc
@@ -31,7 +31,7 @@ As outlined in the <> you need the following
com.blazebit
- blaze-persistence-integration-hibernate-5.4
+ blaze-persistence-integration-hibernate-5.6
${blaze-persistence.version}
runtime
@@ -49,7 +49,7 @@ or if you are using Jakarta JPA
com.blazebit
- blaze-persistence-integration-hibernate-5.4-jakarta
+ blaze-persistence-integration-hibernate-5.6-jakarta
${blaze-persistence.version}
runtime
diff --git a/documentation/src/main/asciidoc/entity-view/manual/en_US/quarkus.adoc b/documentation/src/main/asciidoc/entity-view/manual/en_US/quarkus.adoc
index a7292b9885..c3416440f6 100644
--- a/documentation/src/main/asciidoc/entity-view/manual/en_US/quarkus.adoc
+++ b/documentation/src/main/asciidoc/entity-view/manual/en_US/quarkus.adoc
@@ -290,3 +290,21 @@ In order to make proper use of a custom type in entity views, it is necessary to
Configure default values for optional parameters::
Sometimes it is useful to provide access to services into entity views through optional parameters, for which a global default value can be registered on `EntityViewConfiguration`.
+
+As of version 1.6.5, also a CDI event of the type `CriteriaBuilderConfiguration` is fired with an optional `@BlazePersistenceInstance` qualifier at boot time.
+This allows to further customize the configuration which is often necessary if the context-less variant `CriteriaBuilderConfigurationContributor` isn't enough
+
+Register named type for VALUES::
+If you want to use a type that isn't supported out of the box, it needs to be registered under a name.
+
+Register custom JpqlFunctionGroup::
+If you want to register a CDI context aware `JpqlFunctionGroup`.
+
+Register JpqlMacro::
+If you want to register a CDI context aware `JpqlMacro`.
+
+Register custom dialect::
+When a dialect has a bug, needs a customization, or a new kind of dialect should be registered.
+
+Configure properties::
+Sometimes it is simply necessary to override a configuration property through `setProperty`
diff --git a/documentation/src/main/asciidoc/entity-view/manual/en_US/spring_data.adoc b/documentation/src/main/asciidoc/entity-view/manual/en_US/spring_data.adoc
index 788acd2dd4..96faed2f2c 100644
--- a/documentation/src/main/asciidoc/entity-view/manual/en_US/spring_data.adoc
+++ b/documentation/src/main/asciidoc/entity-view/manual/en_US/spring_data.adoc
@@ -22,7 +22,7 @@ In short, the following Maven dependencies are required
com.blazebit
- blaze-persistence-integration-hibernate-5.4
+ blaze-persistence-integration-hibernate-5.6
${blaze-persistence.version}
runtime
diff --git a/documentation/src/main/asciidoc/entity-view/manual/en_US/spring_hateoas.adoc b/documentation/src/main/asciidoc/entity-view/manual/en_US/spring_hateoas.adoc
index e0b0cc6e74..61e33de7c7 100644
--- a/documentation/src/main/asciidoc/entity-view/manual/en_US/spring_hateoas.adoc
+++ b/documentation/src/main/asciidoc/entity-view/manual/en_US/spring_hateoas.adoc
@@ -20,7 +20,7 @@ In short, the following Maven dependencies are required
com.blazebit
- blaze-persistence-integration-hibernate-5.4
+ blaze-persistence-integration-hibernate-5.6
${blaze-persistence.version}
runtime
diff --git a/entity-view/testsuite/pom.xml b/entity-view/testsuite/pom.xml
index f1f01f73dd..badd13c630 100644
--- a/entity-view/testsuite/pom.xml
+++ b/entity-view/testsuite/pom.xml
@@ -1249,7 +1249,7 @@
${project.groupId}
- blaze-persistence-integration-hibernate-5.4
+ blaze-persistence-integration-hibernate-5.5
test
@@ -1349,7 +1349,7 @@
${project.groupId}
- blaze-persistence-integration-hibernate-5.4
+ blaze-persistence-integration-hibernate-5.6
test
@@ -2176,11 +2176,11 @@
org.hibernate
hibernate-entitymanager
- ${version.hibernate-5.4}
+ ${version.hibernate-5.6}
${project.groupId}
- blaze-persistence-integration-hibernate-5.4
+ blaze-persistence-integration-hibernate-5.6
test
@@ -2192,7 +2192,7 @@
org.hibernate
hibernate-jpamodelgen
- ${version.hibernate-5.4}
+ ${version.hibernate-5.6}
provided
@@ -2234,7 +2234,7 @@
org.hibernate
hibernate-jpamodelgen
- ${version.hibernate-5.4}
+ ${version.hibernate-5.6}
${project.groupId}
diff --git a/examples/quarkus/base/src/main/java/com/blazebit/persistence/examples/quarkus/base/config/BlazePersistenceConfigurator.java b/examples/quarkus/base/src/main/java/com/blazebit/persistence/examples/quarkus/base/config/BlazePersistenceConfigurator.java
index 1d63b536bb..8cd58431e6 100644
--- a/examples/quarkus/base/src/main/java/com/blazebit/persistence/examples/quarkus/base/config/BlazePersistenceConfigurator.java
+++ b/examples/quarkus/base/src/main/java/com/blazebit/persistence/examples/quarkus/base/config/BlazePersistenceConfigurator.java
@@ -16,6 +16,9 @@
package com.blazebit.persistence.examples.quarkus.base.config;
+import com.blazebit.persistence.spi.CriteriaBuilderConfiguration;
+import com.blazebit.persistence.spi.FunctionRenderContext;
+import com.blazebit.persistence.spi.JpqlMacro;
import com.blazebit.persistence.view.spi.EntityViewConfiguration;
import javax.enterprise.context.ApplicationScoped;
@@ -24,6 +27,15 @@
@ApplicationScoped
public class BlazePersistenceConfigurator {
+ public void observe(@Observes CriteriaBuilderConfiguration config) {
+ config.registerMacro("my_macro", new JpqlMacro() {
+ @Override
+ public void render(FunctionRenderContext context) {
+ context.addArgument(0);
+ }
+ });
+ }
+
public void observe(@Observes EntityViewConfiguration config) {
config.setOptionalParameter("optionalParameter", "test");
}
diff --git a/examples/quarkus/base/src/main/java/com/blazebit/persistence/examples/quarkus/base/view/DocumentView.java b/examples/quarkus/base/src/main/java/com/blazebit/persistence/examples/quarkus/base/view/DocumentView.java
index f9c02060b2..b961d860da 100644
--- a/examples/quarkus/base/src/main/java/com/blazebit/persistence/examples/quarkus/base/view/DocumentView.java
+++ b/examples/quarkus/base/src/main/java/com/blazebit/persistence/examples/quarkus/base/view/DocumentView.java
@@ -41,4 +41,7 @@ public interface DocumentView {
@MappingParameter("optionalParameter")
String getOptionalParameter();
+
+ @Mapping("my_macro(name)")
+ String getMacroName();
}
diff --git a/examples/quarkus/testsuite/base/src/main/java/com/blazebit/persistence/examples/quarkus/testsuite/base/AbstractQuarkusExampleTest.java b/examples/quarkus/testsuite/base/src/main/java/com/blazebit/persistence/examples/quarkus/testsuite/base/AbstractQuarkusExampleTest.java
index c45ab3b289..0dda098897 100644
--- a/examples/quarkus/testsuite/base/src/main/java/com/blazebit/persistence/examples/quarkus/testsuite/base/AbstractQuarkusExampleTest.java
+++ b/examples/quarkus/testsuite/base/src/main/java/com/blazebit/persistence/examples/quarkus/testsuite/base/AbstractQuarkusExampleTest.java
@@ -99,6 +99,7 @@ public void getDocumentsWithJsonIgnoredName() {
assertFalse(document.containsKey("name"));
assertEquals("test", document.get("optionalParameter"));
+ assertEquals("Doc1", document.get("macroName"));
}
@Test
diff --git a/integration/deltaspike-data/testsuite/pom.xml b/integration/deltaspike-data/testsuite/pom.xml
index 95c6167bd5..8ec1d86e70 100644
--- a/integration/deltaspike-data/testsuite/pom.xml
+++ b/integration/deltaspike-data/testsuite/pom.xml
@@ -1227,7 +1227,7 @@
${project.groupId}
- blaze-persistence-integration-hibernate-5.4
+ blaze-persistence-integration-hibernate-5.5
test
@@ -1327,7 +1327,7 @@
${project.groupId}
- blaze-persistence-integration-hibernate-5.4
+ blaze-persistence-integration-hibernate-5.6
test
@@ -2163,11 +2163,11 @@
org.hibernate
hibernate-entitymanager
- ${version.hibernate-5.4}
+ ${version.hibernate-5.6}
${project.groupId}
- blaze-persistence-integration-hibernate-5.4
+ blaze-persistence-integration-hibernate-5.6
test
@@ -2179,7 +2179,7 @@
org.hibernate
hibernate-jpamodelgen
- ${version.hibernate-5.4}
+ ${version.hibernate-5.6}
provided
@@ -2229,7 +2229,7 @@
org.hibernate
hibernate-jpamodelgen
- ${version.hibernate-5.4}
+ ${version.hibernate-5.6}
${project.groupId}
diff --git a/integration/hibernate-5.3/src/main/java/com/blazebit/persistence/integration/hibernate/Hibernate53DelegatingDialect.java b/integration/hibernate-5.3/src/main/java/com/blazebit/persistence/integration/hibernate/Hibernate53DelegatingDialect.java
index 2afccdd0bf..d8a4a04cef 100644
--- a/integration/hibernate-5.3/src/main/java/com/blazebit/persistence/integration/hibernate/Hibernate53DelegatingDialect.java
+++ b/integration/hibernate-5.3/src/main/java/com/blazebit/persistence/integration/hibernate/Hibernate53DelegatingDialect.java
@@ -36,6 +36,7 @@
import org.hibernate.engine.jdbc.env.spi.IdentifierHelperBuilder;
import org.hibernate.engine.jdbc.env.spi.NameQualifierSupport;
import org.hibernate.engine.jdbc.env.spi.SchemaNameResolver;
+import org.hibernate.engine.spi.QueryParameters;
import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
import org.hibernate.exception.spi.SQLExceptionConverter;
import org.hibernate.exception.spi.ViolatedConstraintNameExtracter;
@@ -902,6 +903,91 @@ public void augmentRecognizedTableTypes(List tableTypesList) {
delegate.augmentRecognizedTableTypes(tableTypesList);
}
+ @Override
+ public String getNativeIdentifierGeneratorStrategy() {
+ return delegate.getNativeIdentifierGeneratorStrategy();
+ }
+
+ @Override
+ public String getWriteLockString(String aliases, int timeout) {
+ return delegate.getWriteLockString(aliases, timeout);
+ }
+
+ @Override
+ public String getReadLockString(String aliases, int timeout) {
+ return delegate.getReadLockString(aliases, timeout);
+ }
+
+ @Override
+ public String getAlterTableString(String tableName) {
+ return delegate.getAlterTableString(tableName);
+ }
+
+ @Override
+ public String getAddForeignKeyConstraintString(String constraintName, String foreignKeyDefinition) {
+ return delegate.getAddForeignKeyConstraintString(constraintName, foreignKeyDefinition);
+ }
+
+ @Override
+ public boolean supportsIfExistsAfterAlterTable() {
+ return delegate.supportsIfExistsAfterAlterTable();
+ }
+
+ @Override
+ public boolean useFollowOnLocking(QueryParameters parameters) {
+ return delegate.useFollowOnLocking(parameters);
+ }
+
+ @Override
+ public String getQueryHintString(String query, String hints) {
+ return delegate.getQueryHintString(query, hints);
+ }
+
+ @Override
+ public boolean supportsNamedParameters(DatabaseMetaData databaseMetaData) throws SQLException {
+ return delegate.supportsNamedParameters(databaseMetaData);
+ }
+
+ @Override
+ public boolean supportsNationalizedTypes() {
+ return delegate.supportsNationalizedTypes();
+ }
+
+ @Override
+ public boolean supportsNonQueryWithCTE() {
+ return delegate.supportsNonQueryWithCTE();
+ }
+
+ @Override
+ public boolean supportsValuesList() {
+ return delegate.supportsValuesList();
+ }
+
+ @Override
+ public boolean supportsSkipLocked() {
+ return delegate.supportsSkipLocked();
+ }
+
+ @Override
+ public boolean supportsNoWait() {
+ return delegate.supportsNoWait();
+ }
+
+ @Override
+ public boolean isLegacyLimitHandlerBehaviorEnabled() {
+ return delegate.isLegacyLimitHandlerBehaviorEnabled();
+ }
+
+ @Override
+ public String inlineLiteral(String literal) {
+ return delegate.inlineLiteral(literal);
+ }
+
+ @Override
+ public String addSqlHintOrComment(String sql, QueryParameters parameters, boolean commentsEnabled) {
+ return delegate.addSqlHintOrComment(sql, parameters, commentsEnabled);
+ }
+
@Override
public boolean supportsPartitionBy() {
// NOTE: we can't delegate because this is called in constructor
diff --git a/integration/hibernate-5.4-jakarta/pom.xml b/integration/hibernate-5.5-jakarta/pom.xml
similarity index 97%
rename from integration/hibernate-5.4-jakarta/pom.xml
rename to integration/hibernate-5.5-jakarta/pom.xml
index f563b2e713..d007af5663 100644
--- a/integration/hibernate-5.4-jakarta/pom.xml
+++ b/integration/hibernate-5.5-jakarta/pom.xml
@@ -25,13 +25,13 @@
../pom.xml
- blaze-persistence-integration-hibernate-5.4-jakarta
+ blaze-persistence-integration-hibernate-5.5-jakarta
jar
${project.groupId}
- blaze-persistence-integration-hibernate-5.4
+ blaze-persistence-integration-hibernate-5.5
provided
@@ -66,7 +66,7 @@
-
+
@@ -90,7 +90,7 @@
-
+
@@ -117,7 +117,7 @@
-
+
diff --git a/integration/hibernate-5.5/pom.xml b/integration/hibernate-5.5/pom.xml
new file mode 100644
index 0000000000..560c1e0186
--- /dev/null
+++ b/integration/hibernate-5.5/pom.xml
@@ -0,0 +1,170 @@
+
+
+
+
+ 4.0.0
+
+
+ com.blazebit
+ blaze-persistence-integration
+ 1.6.5-SNAPSHOT
+ ../pom.xml
+
+
+ blaze-persistence-integration-hibernate-5.5
+ jar
+
+ Blazebit Persistence Integration Hibernate 5.5
+
+
+ com.blazebit.persistence.integration.hibernate
+
+
+
+
+ ${project.groupId}
+ blaze-persistence-core-api
+
+
+ ${project.groupId}
+ blaze-persistence-integration-hibernate-base
+
+
+ com.blazebit
+ blaze-persistence-integration-hibernate-5.3
+ ${project.version}
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+
+
+ package
+
+ shade
+
+
+ true
+
+
+ ${project.groupId}:blaze-persistence-integration-hibernate-5.3
+
+
+
+
+
+
+
+ org.moditect
+ moditect-maven-plugin
+
+
+ add-module-infos
+ package
+
+ add-module-info
+
+
+
+
+ module ${module.name} {
+ requires java.sql;
+ requires java.persistence;
+ requires org.hibernate.orm.core;
+ requires com.blazebit.persistence.core;
+ requires transitive com.blazebit.persistence.integration.hibernate.base;
+ requires static com.blazebit.persistence.view;
+ provides com.blazebit.persistence.integration.hibernate.base.HibernateAccess with com.blazebit.persistence.integration.hibernate.Hibernate53Access;
+ provides com.blazebit.persistence.spi.EntityManagerFactoryIntegrator with com.blazebit.persistence.integration.hibernate.Hibernate53EntityManagerFactoryIntegrator;
+ provides com.blazebit.persistence.view.spi.TransactionAccessFactory with com.blazebit.persistence.integration.hibernate.Hibernate5TransactionAccessFactory;
+ provides org.hibernate.integrator.spi.Integrator with com.blazebit.persistence.integration.hibernate.Hibernate53Integrator;
+ provides org.hibernate.persister.spi.PersisterClassResolver with com.blazebit.persistence.integration.hibernate.CustomPersisterClassResolver;
+ provides org.hibernate.boot.spi.MetadataContributor with com.blazebit.persistence.integration.hibernate.Hibernate53MetadataContributor;
+ provides org.hibernate.service.spi.ServiceContributor with com.blazebit.persistence.integration.hibernate.Hibernate53ServiceContributor;
+ exports com.blazebit.persistence.integration.hibernate;
+ }
+
+
+
+
+
+
+
+
+
+
+
+ blazebit-release
+
+
+
+ maven-dependency-plugin
+
+
+ shade-javadoc
+
+ copy
+
+
+
+
+ ${project.groupId}
+ blaze-persistence-integration-hibernate-5.3
+ ${project.version}
+ jar
+ javadoc
+ true
+ ${project.build.directory}
+ ${project.artifactId}-${project.version}-javadoc.jar
+
+
+
+
+
+
+
+ org.codehaus.mojo
+ build-helper-maven-plugin
+
+
+ attach-artifacts
+ package
+
+ attach-artifact
+
+
+
+
+ ${project.build.directory}/${project.artifactId}-${project.version}-javadoc.jar
+ javadoc
+ jar
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/integration/hibernate-5.6-jakarta/pom.xml b/integration/hibernate-5.6-jakarta/pom.xml
new file mode 100644
index 0000000000..40fc0bc3fe
--- /dev/null
+++ b/integration/hibernate-5.6-jakarta/pom.xml
@@ -0,0 +1,219 @@
+
+
+
+
+ 4.0.0
+
+
+ com.blazebit
+ blaze-persistence-integration
+ 1.6.5-SNAPSHOT
+ ../pom.xml
+
+
+ blaze-persistence-integration-hibernate-5.6-jakarta
+ jar
+
+
+
+ ${project.groupId}
+ blaze-persistence-integration-hibernate-5.6
+ provided
+
+
+ jakarta.persistence
+ jakarta.persistence-api
+ ${version.jakarta-jpa-api}
+
+
+ ${project.groupId}
+ blaze-persistence-core-api-jakarta
+
+
+
+ ${project.groupId}
+ blaze-persistence-integration-hibernate-base-jakarta
+
+
+
+
+
+
+ maven-antrun-plugin
+
+
+ transform-jar
+ package
+
+ run
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ transform-sources-jar
+ package
+
+ run
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ transform-javadoc
+ package
+
+ run
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ org.eclipse.transformer
+ org.eclipse.transformer.cli
+ 0.2.0
+
+
+ ant-contrib
+ ant-contrib
+ 1.0b3
+
+
+ ant
+ ant
+
+
+
+
+
+
+
+ org.codehaus.mojo
+ build-helper-maven-plugin
+
+
+ attach-artifacts
+ package
+
+ attach-artifact
+
+
+
+
+ ${project.build.directory}/${project.build.finalName}-sources.jar
+ sources
+ jar
+
+
+
+
+
+
+
+
+
+
+ blazebit-release
+
+
+
+ org.codehaus.mojo
+ build-helper-maven-plugin
+
+
+ attach-artifacts
+ package
+
+ attach-artifact
+
+
+
+
+ ${project.build.directory}/${project.build.finalName}-sources.jar
+ sources
+ jar
+
+
+ ${project.build.directory}/${project.build.finalName}-javadoc.jar
+ javadoc
+ jar
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/integration/hibernate-5.6/pom.xml b/integration/hibernate-5.6/pom.xml
new file mode 100644
index 0000000000..dc9895dde0
--- /dev/null
+++ b/integration/hibernate-5.6/pom.xml
@@ -0,0 +1,145 @@
+
+
+
+
+ 4.0.0
+
+
+ com.blazebit
+ blaze-persistence-integration
+ 1.6.5-SNAPSHOT
+ ../pom.xml
+
+
+ blaze-persistence-integration-hibernate-5.6
+ jar
+
+ Blazebit Persistence Integration Hibernate 5.6
+
+
+ com.blazebit.persistence.integration.hibernate
+
+
+
+
+ ${project.groupId}
+ blaze-persistence-core-api
+
+
+ ${project.groupId}
+ blaze-persistence-integration-hibernate-base
+
+
+ ${project.groupId}
+ blaze-persistence-entity-view-api
+ provided
+
+
+
+ ${project.groupId}
+ blaze-apt-utils
+ provided
+
+
+
+ org.hibernate
+ hibernate-core
+ ${version.hibernate-5.6}
+ provided
+
+
+
+
+
+
+ org.codehaus.mojo
+ build-helper-maven-plugin
+
+
+ add-resource
+ generate-resources
+
+ add-resource
+
+
+
+
+ target/generated/resources
+
+
+
+
+
+
+
+ org.bsc.maven
+ maven-processor-plugin
+
+
+ process-resources
+
+ process
+
+ generate-resources
+
+ target/generated/resources
+
+
+ com.blazebit.apt.service.ServiceProviderAnnotationProcessor
+
+
+
+
+
+
+ org.moditect
+ moditect-maven-plugin
+
+
+ add-module-infos
+ package
+
+ add-module-info
+
+
+
+
+ module ${module.name} {
+ requires java.sql;
+ requires java.persistence;
+ requires org.hibernate.orm.core;
+ requires com.blazebit.persistence.core;
+ requires transitive com.blazebit.persistence.integration.hibernate.base;
+ requires static com.blazebit.persistence.view;
+ provides com.blazebit.persistence.integration.hibernate.base.HibernateAccess with com.blazebit.persistence.integration.hibernate.Hibernate56Access;
+ provides com.blazebit.persistence.spi.EntityManagerFactoryIntegrator with com.blazebit.persistence.integration.hibernate.Hibernate56EntityManagerFactoryIntegrator;
+ provides com.blazebit.persistence.view.spi.TransactionAccessFactory with com.blazebit.persistence.integration.hibernate.Hibernate5TransactionAccessFactory;
+ provides org.hibernate.integrator.spi.Integrator with com.blazebit.persistence.integration.hibernate.Hibernate56Integrator;
+ provides org.hibernate.persister.spi.PersisterClassResolver with com.blazebit.persistence.integration.hibernate.CustomPersisterClassResolver;
+ provides org.hibernate.boot.spi.MetadataContributor with com.blazebit.persistence.integration.hibernate.Hibernate56MetadataContributor;
+ provides org.hibernate.service.spi.ServiceContributor with com.blazebit.persistence.integration.hibernate.Hibernate56ServiceContributor;
+ exports com.blazebit.persistence.integration.hibernate;
+ }
+
+
+
+
+
+
+
+
+
diff --git a/integration/hibernate-5.6/src/main/java/com/blazebit/persistence/integration/hibernate/CustomBasicCollectionPersister.java b/integration/hibernate-5.6/src/main/java/com/blazebit/persistence/integration/hibernate/CustomBasicCollectionPersister.java
new file mode 100644
index 0000000000..890e5f473b
--- /dev/null
+++ b/integration/hibernate-5.6/src/main/java/com/blazebit/persistence/integration/hibernate/CustomBasicCollectionPersister.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2014 - 2022 Blazebit.
+ *
+ * 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 com.blazebit.persistence.integration.hibernate;
+
+import com.blazebit.persistence.integration.hibernate.base.CustomCollectionPersister;
+import org.hibernate.MappingException;
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.spi.access.CollectionDataAccess;
+import org.hibernate.engine.spi.SharedSessionContractImplementor;
+import org.hibernate.engine.spi.SubselectFetch;
+import org.hibernate.loader.collection.CollectionInitializer;
+import org.hibernate.mapping.Collection;
+import org.hibernate.persister.collection.BasicCollectionPersister;
+import org.hibernate.persister.spi.PersisterCreationContext;
+
+/**
+ * @author Christian Beikov
+ * @since 1.2.0
+ */
+public class CustomBasicCollectionPersister extends BasicCollectionPersister implements CustomCollectionPersister {
+
+ public CustomBasicCollectionPersister(Collection collectionBinding, CollectionDataAccess cacheAccessStrategy, PersisterCreationContext creationContext) throws MappingException, CacheException {
+ super(collectionBinding, cacheAccessStrategy, creationContext);
+ }
+
+ @Override
+ protected CollectionInitializer createSubselectInitializer(SubselectFetch subselect, SharedSessionContractImplementor session) {
+ return new CustomSubselectCollectionLoader(
+ this,
+ subselect.toSubselectString( getCollectionType().getLHSPropertyName() ),
+ subselect.getResult(),
+ subselect.getQueryParameters(),
+ subselect.getNamedParameterLocMap(),
+ session.getFactory(),
+ session.getLoadQueryInfluencers()
+ );
+ }
+
+}
diff --git a/integration/hibernate-5.6/src/main/java/com/blazebit/persistence/integration/hibernate/CustomMultiTableBulkIdStrategy.java b/integration/hibernate-5.6/src/main/java/com/blazebit/persistence/integration/hibernate/CustomMultiTableBulkIdStrategy.java
new file mode 100644
index 0000000000..e09ee8abf5
--- /dev/null
+++ b/integration/hibernate-5.6/src/main/java/com/blazebit/persistence/integration/hibernate/CustomMultiTableBulkIdStrategy.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2014 - 2022 Blazebit.
+ *
+ * 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 com.blazebit.persistence.integration.hibernate;
+
+import org.hibernate.boot.model.relational.SqlStringGenerationContext;
+import org.hibernate.boot.spi.MetadataImplementor;
+import org.hibernate.boot.spi.SessionFactoryOptions;
+import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
+import org.hibernate.engine.jdbc.spi.JdbcServices;
+import org.hibernate.engine.spi.SessionFactoryImplementor;
+import org.hibernate.hql.internal.ast.HqlSqlWalker;
+import org.hibernate.hql.internal.ast.tree.FromElement;
+import org.hibernate.hql.internal.ast.tree.UpdateStatement;
+import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy;
+import org.hibernate.hql.spi.id.TableBasedUpdateHandlerImpl;
+import org.hibernate.persister.entity.AbstractEntityPersister;
+
+import java.util.logging.Logger;
+
+/**
+ * @author Christian Beikov
+ * @since 1.3.0
+ */
+public class CustomMultiTableBulkIdStrategy implements MultiTableBulkIdStrategy {
+
+ private static final Logger LOG = Logger.getLogger(CustomMultiTableBulkIdStrategy.class.getName());
+ private final MultiTableBulkIdStrategy delegate;
+
+ public CustomMultiTableBulkIdStrategy(MultiTableBulkIdStrategy delegate) {
+ this.delegate = delegate;
+ }
+
+ @Override
+ public UpdateHandler buildUpdateHandler(SessionFactoryImplementor factory, HqlSqlWalker walker) {
+ UpdateHandler updateHandler = delegate.buildUpdateHandler(factory, walker);
+
+ final UpdateStatement updateStatement = (UpdateStatement) walker.getAST();
+ final FromElement fromElement = updateStatement.getFromClause().getFromElement();
+ final AbstractEntityPersister targetedPersister = (AbstractEntityPersister) fromElement.getQueryable();
+
+ // Only do this when we have secondary tables
+ if (targetedPersister.getConstraintOrderedTableNameClosure().length > 1) {
+ if (updateHandler instanceof TableBasedUpdateHandlerImpl) {
+ return new CustomTableBasedUpdateHandlerImpl((TableBasedUpdateHandlerImpl) updateHandler, walker);
+ } else {
+ LOG.warning("Unsupported update handler that can't be adapted to support updates to secondary tables: " + updateHandler);
+ }
+ }
+
+ return updateHandler;
+ }
+
+ @Override
+ public DeleteHandler buildDeleteHandler(SessionFactoryImplementor factory, HqlSqlWalker walker) {
+ return delegate.buildDeleteHandler(factory, walker);
+ }
+
+ @Override
+ public void prepare(JdbcServices jdbcServices, JdbcConnectionAccess connectionAccess, MetadataImplementor metadata, SessionFactoryOptions sessionFactoryOptions, SqlStringGenerationContext sqlStringGenerationContext) {
+ delegate.prepare(jdbcServices, connectionAccess, metadata, sessionFactoryOptions, sqlStringGenerationContext);
+ }
+
+ @Override
+ public void release(JdbcServices jdbcServices, JdbcConnectionAccess connectionAccess) {
+ delegate.release(jdbcServices, connectionAccess);
+ }
+}
diff --git a/integration/hibernate-5.6/src/main/java/com/blazebit/persistence/integration/hibernate/CustomOneToManyPersister.java b/integration/hibernate-5.6/src/main/java/com/blazebit/persistence/integration/hibernate/CustomOneToManyPersister.java
new file mode 100644
index 0000000000..ef248cdfc6
--- /dev/null
+++ b/integration/hibernate-5.6/src/main/java/com/blazebit/persistence/integration/hibernate/CustomOneToManyPersister.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2014 - 2022 Blazebit.
+ *
+ * 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 com.blazebit.persistence.integration.hibernate;
+
+import com.blazebit.persistence.integration.hibernate.base.CustomCollectionPersister;
+import org.hibernate.MappingException;
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.spi.access.CollectionDataAccess;
+import org.hibernate.engine.spi.SharedSessionContractImplementor;
+import org.hibernate.engine.spi.SubselectFetch;
+import org.hibernate.loader.collection.CollectionInitializer;
+import org.hibernate.mapping.Collection;
+import org.hibernate.persister.collection.OneToManyPersister;
+import org.hibernate.persister.spi.PersisterCreationContext;
+
+/**
+ *
+ * @author Christian Beikov
+ * @since 1.2.0
+ */
+public class CustomOneToManyPersister extends OneToManyPersister implements CustomCollectionPersister {
+
+ public CustomOneToManyPersister(Collection collectionBinding, CollectionDataAccess cacheAccessStrategy, PersisterCreationContext creationContext) throws MappingException, CacheException {
+ super(collectionBinding, cacheAccessStrategy, creationContext);
+ }
+
+ @Override
+ protected CollectionInitializer createSubselectInitializer(SubselectFetch subselect, SharedSessionContractImplementor session) {
+ return new CustomSubselectOneToManyLoader(
+ this,
+ subselect.toSubselectString( getCollectionType().getLHSPropertyName() ),
+ subselect.getResult(),
+ subselect.getQueryParameters(),
+ subselect.getNamedParameterLocMap(),
+ session.getFactory(),
+ session.getLoadQueryInfluencers()
+ );
+ }
+}
\ No newline at end of file
diff --git a/integration/hibernate-5.6/src/main/java/com/blazebit/persistence/integration/hibernate/CustomPersisterClassResolver.java b/integration/hibernate-5.6/src/main/java/com/blazebit/persistence/integration/hibernate/CustomPersisterClassResolver.java
new file mode 100644
index 0000000000..d0a438e85d
--- /dev/null
+++ b/integration/hibernate-5.6/src/main/java/com/blazebit/persistence/integration/hibernate/CustomPersisterClassResolver.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2014 - 2022 Blazebit.
+ *
+ * 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 com.blazebit.persistence.integration.hibernate;
+
+import com.blazebit.apt.service.ServiceProvider;
+import org.hibernate.mapping.Collection;
+import org.hibernate.persister.collection.CollectionPersister;
+import org.hibernate.persister.internal.StandardPersisterClassResolver;
+import org.hibernate.persister.spi.PersisterClassResolver;
+
+/**
+ * @author Jan-Willem Gmelig Meyling
+ * @since 1.2.0
+ */
+@ServiceProvider(PersisterClassResolver.class)
+public class CustomPersisterClassResolver extends StandardPersisterClassResolver implements PersisterClassResolver {
+
+ @Override
+ public Class extends CollectionPersister> getCollectionPersisterClass(Collection metadata) {
+ return metadata.isOneToMany() ? CustomOneToManyPersister.class : CustomBasicCollectionPersister.class;
+ }
+
+}
diff --git a/integration/hibernate-5.6/src/main/java/com/blazebit/persistence/integration/hibernate/CustomSubselectCollectionLoader.java b/integration/hibernate-5.6/src/main/java/com/blazebit/persistence/integration/hibernate/CustomSubselectCollectionLoader.java
new file mode 100644
index 0000000000..c719eadda1
--- /dev/null
+++ b/integration/hibernate-5.6/src/main/java/com/blazebit/persistence/integration/hibernate/CustomSubselectCollectionLoader.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2014 - 2022 Blazebit.
+ *
+ * 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 com.blazebit.persistence.integration.hibernate;
+
+import com.blazebit.persistence.integration.hibernate.base.SubselectLoaderUtils;
+import org.hibernate.MappingException;
+import org.hibernate.engine.spi.LoadQueryInfluencers;
+import org.hibernate.engine.spi.QueryParameters;
+import org.hibernate.engine.spi.SessionFactoryImplementor;
+import org.hibernate.engine.spi.SharedSessionContractImplementor;
+import org.hibernate.loader.collection.SubselectCollectionLoader;
+import org.hibernate.persister.collection.QueryableCollection;
+
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.util.Collection;
+import java.util.Map;
+
+import static com.blazebit.persistence.integration.hibernate.base.SubselectLoaderUtils.getPreparedStatementProxy;
+
+/**
+ * @author Jan-Willem Gmelig Meyling
+ * @since 1.2.0
+ */
+public class CustomSubselectCollectionLoader extends SubselectCollectionLoader {
+
+ private final int cteParameterCount;
+ private final int selectParameterCount;
+
+ public CustomSubselectCollectionLoader(QueryableCollection persister, String subquery, Collection entityKeys, QueryParameters queryParameters, Map namedParameterLocMap, SessionFactoryImplementor factory, LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
+ super(persister, subquery, entityKeys, queryParameters, namedParameterLocMap, factory, loadQueryInfluencers);
+ String originalSql = queryParameters.getFilteredSQL();
+ if (originalSql.startsWith("with ")) {
+ StringBuilder sb = new StringBuilder(sql.length() + originalSql.length());
+ cteParameterCount = SubselectLoaderUtils.applyCteAndCountParameters(originalSql, sb);
+ selectParameterCount = SubselectLoaderUtils.countSelectParameters(originalSql, sb.length());
+ sb.append(sql);
+ this.sql = sb.toString();
+ } else {
+ cteParameterCount = 0;
+ selectParameterCount = 0;
+ }
+ }
+
+ @Override
+ protected int bindParameterValues(PreparedStatement statement, QueryParameters queryParameters, int startIndex, SharedSessionContractImplementor session) throws SQLException {
+ if (cteParameterCount > 0) {
+ statement = getPreparedStatementProxy(statement, queryParameters, cteParameterCount, selectParameterCount);
+ }
+ return super.bindParameterValues(statement, queryParameters, startIndex, session);
+ }
+
+}
diff --git a/integration/hibernate-5.6/src/main/java/com/blazebit/persistence/integration/hibernate/CustomSubselectOneToManyLoader.java b/integration/hibernate-5.6/src/main/java/com/blazebit/persistence/integration/hibernate/CustomSubselectOneToManyLoader.java
new file mode 100644
index 0000000000..44b993ab69
--- /dev/null
+++ b/integration/hibernate-5.6/src/main/java/com/blazebit/persistence/integration/hibernate/CustomSubselectOneToManyLoader.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2014 - 2022 Blazebit.
+ *
+ * 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 com.blazebit.persistence.integration.hibernate;
+
+import com.blazebit.persistence.integration.hibernate.base.SubselectLoaderUtils;
+import org.hibernate.MappingException;
+import org.hibernate.engine.spi.LoadQueryInfluencers;
+import org.hibernate.engine.spi.QueryParameters;
+import org.hibernate.engine.spi.SessionFactoryImplementor;
+import org.hibernate.engine.spi.SharedSessionContractImplementor;
+import org.hibernate.loader.collection.SubselectOneToManyLoader;
+import org.hibernate.persister.collection.QueryableCollection;
+
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.util.Map;
+
+import static com.blazebit.persistence.integration.hibernate.base.SubselectLoaderUtils.getPreparedStatementProxy;
+
+/**
+ *
+ * @author Christian Beikov
+ * @since 1.2.0
+ */
+public class CustomSubselectOneToManyLoader extends SubselectOneToManyLoader {
+
+ private final int cteParameterCount;
+ private final int selectParameterCount;
+
+ public CustomSubselectOneToManyLoader(QueryableCollection persister, String subquery, java.util.Collection entityKeys, QueryParameters queryParameters, Map namedParameterLocMap, SessionFactoryImplementor factory, LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
+ super(persister, subquery, entityKeys, queryParameters, namedParameterLocMap, factory, loadQueryInfluencers);
+ String originalSql = queryParameters.getFilteredSQL();
+ if (originalSql.startsWith("with ")) {
+ StringBuilder sb = new StringBuilder(sql.length() + originalSql.length());
+ cteParameterCount = SubselectLoaderUtils.applyCteAndCountParameters(originalSql, sb);
+ selectParameterCount = SubselectLoaderUtils.countSelectParameters(originalSql, sb.length());
+ sb.append(sql);
+ this.sql = sb.toString();
+ } else {
+ cteParameterCount = 0;
+ selectParameterCount = 0;
+ }
+ }
+
+ @Override
+ protected int bindParameterValues(PreparedStatement statement, QueryParameters queryParameters, int startIndex, SharedSessionContractImplementor session) throws SQLException {
+ if (cteParameterCount > 0) {
+ statement = getPreparedStatementProxy(statement, queryParameters, cteParameterCount, selectParameterCount);
+ }
+ return super.bindParameterValues(statement, queryParameters, startIndex, session);
+ }
+
+}
\ No newline at end of file
diff --git a/integration/hibernate-5.6/src/main/java/com/blazebit/persistence/integration/hibernate/CustomTableBasedUpdateHandlerImpl.java b/integration/hibernate-5.6/src/main/java/com/blazebit/persistence/integration/hibernate/CustomTableBasedUpdateHandlerImpl.java
new file mode 100644
index 0000000000..bb99a8e61a
--- /dev/null
+++ b/integration/hibernate-5.6/src/main/java/com/blazebit/persistence/integration/hibernate/CustomTableBasedUpdateHandlerImpl.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2014 - 2022 Blazebit.
+ *
+ * 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 com.blazebit.persistence.integration.hibernate;
+
+import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
+import org.hibernate.engine.spi.QueryParameters;
+import org.hibernate.engine.spi.SessionImplementor;
+import org.hibernate.engine.spi.SharedSessionContractImplementor;
+import org.hibernate.event.spi.EventSource;
+import org.hibernate.hql.internal.ast.HqlSqlWalker;
+import org.hibernate.hql.internal.ast.tree.AssignmentSpecification;
+import org.hibernate.hql.internal.ast.tree.FromElement;
+import org.hibernate.hql.internal.ast.tree.UpdateStatement;
+import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy;
+import org.hibernate.hql.spi.id.TableBasedUpdateHandlerImpl;
+import org.hibernate.persister.entity.AbstractEntityPersister;
+import org.hibernate.persister.entity.Queryable;
+
+import java.lang.reflect.Proxy;
+import java.sql.PreparedStatement;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Christian Beikov
+ * @since 1.3.0
+ */
+public class CustomTableBasedUpdateHandlerImpl implements MultiTableBulkIdStrategy.UpdateHandler {
+
+ private final TableBasedUpdateHandlerImpl delegate;
+ private final String[] secondaryTableUpdates;
+ private final String[] secondaryTableInserts;
+
+ public CustomTableBasedUpdateHandlerImpl(TableBasedUpdateHandlerImpl delegate, HqlSqlWalker walker) {
+ this.delegate = delegate;
+ // Here comes the madness...
+ // We need to somehow execute our code within the temporary table scope, but since there is no way for use to do this externally,
+ // we need to use invocation handlers to get a callback at the right time
+ // First, we reduce the update statements
+ String[] updates = delegate.getSqlStatements();
+ UpdateStatement updateStatement = (UpdateStatement) walker.getAST();
+ FromElement fromElement = updateStatement.getFromClause().getFromElement();
+ AbstractEntityPersister targetedPersister = (AbstractEntityPersister) fromElement.getQueryable();
+ String[] tableNames = targetedPersister.getConstraintOrderedTableNameClosure();
+ String[][] columnNames = targetedPersister.getContraintOrderedTableKeyColumnClosure();
+
+ int subclassCount = delegate.getTargetedQueryable().getEntityMetamodel().getSubclassEntityNames().size();
+ Set subclassTableNames = new HashSet<>();
+ for (int i = 0; i < subclassCount; i++) {
+ subclassTableNames.add(delegate.getTargetedQueryable().getSubclassTableName(i));
+ }
+
+ final String[] secondaryTableUpdates = updates.clone();
+ final String[] secondaryTableInserts = new String[updates.length];
+
+ StringBuilder sb = new StringBuilder();
+ StringBuilder selectSb = new StringBuilder();
+ String selectString = "select ";
+ String inString = "IN (";
+ for (int tableIndex = 0; tableIndex < tableNames.length; tableIndex++) {
+ if (updates[tableIndex] != null) {
+ // We introduce a dummy update statement that we react upon
+ if (subclassTableNames.contains(tableNames[tableIndex])) {
+ secondaryTableUpdates[tableIndex] = null;
+ } else {
+ sb.setLength(0);
+ selectSb.setLength(0);
+
+ boolean affected = false;
+ String idSubselect = updates[tableIndex].substring(updates[tableIndex].lastIndexOf(inString) + inString.length(), updates[tableIndex].length() - 1);
+
+ sb.append("insert into ").append(tableNames[tableIndex]);
+ String[] keyColumnNames = columnNames[tableIndex];
+ sb.append('(');
+
+ final List assignmentSpecifications = walker.getAssignmentSpecifications();
+ for (AssignmentSpecification assignmentSpecification : assignmentSpecifications) {
+ if (assignmentSpecification.affectsTable(tableNames[tableIndex])) {
+ String sqlAssignmentFragment = assignmentSpecification.getSqlAssignmentFragment();
+ int eqIndex = sqlAssignmentFragment.indexOf('=');
+ sb.append(sqlAssignmentFragment, 0, eqIndex);
+ sb.append(',');
+ selectSb.append(sqlAssignmentFragment, eqIndex + 1, sqlAssignmentFragment.length());
+ selectSb.append(',');
+
+ affected = true;
+ }
+ }
+ if (affected) {
+ for (int i = 0; i < keyColumnNames.length; i++) {
+ sb.append(keyColumnNames[i]);
+ sb.append(',');
+ }
+ sb.setCharAt(sb.length() - 1, ')');
+ sb.append(' ').append(selectString);
+ sb.append(selectSb);
+ sb.append(idSubselect, selectString.length(), idSubselect.length());
+ sb.append(" where not exists (select 1 from ");
+ sb.append(tableNames[tableIndex]);
+ sb.append(" a where ");
+
+ for (int i = 0; i < keyColumnNames.length; i++) {
+ sb.append("a.");
+ sb.append(keyColumnNames[i]);
+ sb.append(" = ");
+ sb.append(keyColumnNames[i]);
+ sb.append(" and ");
+ }
+
+ sb.setLength(sb.length() - " and ".length());
+ sb.append(")");
+
+ secondaryTableInserts[tableIndex] = sb.toString();
+ }
+
+ updates[tableIndex] = "";
+ }
+ }
+ }
+
+ this.secondaryTableUpdates = secondaryTableUpdates;
+ this.secondaryTableInserts = secondaryTableInserts;
+ }
+
+ @Override
+ public int execute(SharedSessionContractImplementor s, QueryParameters queryParameters) {
+ final SessionImplementor session = (SessionImplementor) s;
+ final JdbcCoordinator jdbcCoordinator = session.getJdbcCoordinator();
+
+ Object jdbcCoordinatorProxy = Proxy.newProxyInstance(jdbcCoordinator.getClass().getClassLoader(), new Class[]{JdbcCoordinator.class}, new JdbcCoordinatorInvocationHandler(jdbcCoordinator, new DelegatingStatementPreparerImpl(jdbcCoordinator.getStatementPreparer()) {
+ PreparedStatement statementProxy;
+ SecondaryTableUpdateSupportingPreparedStatementInvocationHandler invocationHandler;
+
+ @Override
+ public PreparedStatement prepareStatement(String sql, boolean isCallable) {
+ if (sql.isEmpty()) {
+ // Return the statement proxy which collects parameters and then executes update/insert statements for secondary tables
+ invocationHandler.prepareNext();
+ return statementProxy;
+ } else {
+ PreparedStatement insertStatement = super.prepareStatement(sql, isCallable);
+ this.invocationHandler = new SecondaryTableUpdateSupportingPreparedStatementInvocationHandler(session, jdbcCoordinator.getStatementPreparer(), insertStatement, secondaryTableUpdates, secondaryTableInserts);
+ this.statementProxy = (PreparedStatement) Proxy.newProxyInstance(getClass().getClassLoader(), new Class[]{PreparedStatement.class}, invocationHandler);
+ return statementProxy;
+ }
+ }
+ }));
+ SessionImplementor sessionProxy = (SessionImplementor) Proxy.newProxyInstance(session.getClass().getClassLoader(), new Class[]{SessionImplementor.class, EventSource.class}, new Hibernate56SessionInvocationHandler(session, jdbcCoordinatorProxy));
+
+ return delegate.execute(sessionProxy, queryParameters);
+ }
+
+ @Override
+ public Queryable getTargetedQueryable() {
+ return delegate.getTargetedQueryable();
+ }
+
+ @Override
+ public String[] getSqlStatements() {
+ return delegate.getSqlStatements();
+ }
+}
diff --git a/integration/hibernate-5.6/src/main/java/com/blazebit/persistence/integration/hibernate/DelegatingStatementPreparerImpl.java b/integration/hibernate-5.6/src/main/java/com/blazebit/persistence/integration/hibernate/DelegatingStatementPreparerImpl.java
new file mode 100644
index 0000000000..fa550d5abd
--- /dev/null
+++ b/integration/hibernate-5.6/src/main/java/com/blazebit/persistence/integration/hibernate/DelegatingStatementPreparerImpl.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2014 - 2022 Blazebit.
+ *
+ * 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 com.blazebit.persistence.integration.hibernate;
+
+import org.hibernate.ScrollMode;
+import org.hibernate.engine.jdbc.spi.StatementPreparer;
+
+import java.sql.PreparedStatement;
+import java.sql.Statement;
+
+/**
+ * @author Christian Beikov
+ * @since 1.3.0
+ */
+public class DelegatingStatementPreparerImpl implements StatementPreparer {
+
+ private StatementPreparer delegate;
+
+ public DelegatingStatementPreparerImpl(StatementPreparer delegate) {
+ this.delegate = delegate;
+ }
+
+ @Override
+ public Statement createStatement() {
+ return delegate.createStatement();
+ }
+
+ @Override
+ public PreparedStatement prepareStatement(String sql) {
+ return delegate.prepareStatement(sql);
+ }
+
+ @Override
+ public PreparedStatement prepareStatement(String sql, boolean isCallable) {
+ return delegate.prepareStatement(sql, isCallable);
+ }
+
+ @Override
+ public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) {
+ return delegate.prepareStatement(sql, autoGeneratedKeys);
+ }
+
+ @Override
+ public PreparedStatement prepareStatement(String sql, String[] columnNames) {
+ return delegate.prepareStatement(sql, columnNames);
+ }
+
+ @Override
+ public PreparedStatement prepareQueryStatement(String sql, boolean isCallable, ScrollMode scrollMode) {
+ return delegate.prepareQueryStatement(sql, isCallable, scrollMode);
+ }
+}
diff --git a/integration/hibernate-5.6/src/main/java/com/blazebit/persistence/integration/hibernate/Hibernate56Access.java b/integration/hibernate-5.6/src/main/java/com/blazebit/persistence/integration/hibernate/Hibernate56Access.java
new file mode 100644
index 0000000000..79720d2bd6
--- /dev/null
+++ b/integration/hibernate-5.6/src/main/java/com/blazebit/persistence/integration/hibernate/Hibernate56Access.java
@@ -0,0 +1,263 @@
+/*
+ * Copyright 2014 - 2022 Blazebit.
+ *
+ * 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 com.blazebit.persistence.integration.hibernate;
+
+import com.blazebit.apt.service.ServiceProvider;
+import com.blazebit.persistence.integration.hibernate.base.HibernateAccess;
+import com.blazebit.persistence.integration.hibernate.base.HibernateReturningResult;
+import com.blazebit.persistence.integration.hibernate.base.ScrollableResultsIterator;
+import com.blazebit.persistence.spi.DbmsDialect;
+import org.hibernate.HibernateException;
+import org.hibernate.LockOptions;
+import org.hibernate.Query;
+import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
+import org.hibernate.engine.query.spi.HQLQueryPlan;
+import org.hibernate.engine.spi.ExceptionConverter;
+import org.hibernate.engine.spi.QueryParameters;
+import org.hibernate.engine.spi.RowSelection;
+import org.hibernate.engine.spi.SessionFactoryImplementor;
+import org.hibernate.engine.spi.SessionImplementor;
+import org.hibernate.engine.spi.SharedSessionContractImplementor;
+import org.hibernate.engine.spi.TypedValue;
+import org.hibernate.event.spi.EventSource;
+import org.hibernate.hql.internal.ast.ParameterTranslationsImpl;
+import org.hibernate.hql.internal.ast.exec.BasicExecutor;
+import org.hibernate.hql.internal.ast.exec.StatementExecutor;
+import org.hibernate.hql.spi.ParameterTranslations;
+import org.hibernate.loader.hql.QueryLoader;
+import org.hibernate.param.ParameterSpecification;
+import org.hibernate.query.internal.AbstractProducedQuery;
+import org.hibernate.query.internal.QueryParameterBindingsImpl;
+import org.hibernate.query.spi.QueryImplementor;
+import org.hibernate.query.spi.ScrollableResultsImplementor;
+import org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionCoordinatorImpl;
+import org.hibernate.resource.transaction.spi.TransactionCoordinator;
+import org.hibernate.type.Type;
+
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceException;
+import java.io.Serializable;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Spliterator;
+import java.util.Spliterators;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+
+/**
+ * @author Christian Beikov
+ * @since 1.2.0
+ */
+@ServiceProvider(HibernateAccess.class)
+public class Hibernate56Access implements HibernateAccess {
+
+ private static final Method DO_EXECUTE_METHOD;
+ private static final Method DO_EXECUTE_METHOD_NEW;
+ private static final Constructor PARAMETER_TRANSLATIONS_CONSTRUCTOR;
+
+ static {
+ Method m = null;
+ Method mNew = null;
+ try {
+ m = BasicExecutor.class.getDeclaredMethod("doExecute", QueryParameters.class, SharedSessionContractImplementor.class, String.class, List.class);
+ m.setAccessible(true);
+ } catch (Exception e) {
+ // As of Hibernate 5.4.21 the signature changed...
+ try {
+ mNew = BasicExecutor.class.getDeclaredMethod("doExecute", String.class, QueryParameters.class, List.class, SharedSessionContractImplementor.class);
+ mNew.setAccessible(true);
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+ DO_EXECUTE_METHOD = m;
+ DO_EXECUTE_METHOD_NEW = mNew;
+ try {
+ Constructor c = ParameterTranslationsImpl.class.getDeclaredConstructor(List.class);
+ c.setAccessible(true);
+ PARAMETER_TRANSLATIONS_CONSTRUCTOR = c;
+ } catch (Exception ex) {
+ // As of Hibernate 5.4.21 the signature changed...
+ throw new RuntimeException(ex);
+ }
+ }
+
+ @Override
+ public SessionImplementor wrapSession(SessionImplementor session, DbmsDialect dbmsDialect, String[][] columns, int[] returningSqlTypes, HibernateReturningResult> returningResult) {
+ JdbcCoordinator jdbcCoordinator = session.getJdbcCoordinator();
+
+ Object jdbcCoordinatorProxy = Proxy.newProxyInstance(jdbcCoordinator.getClass().getClassLoader(), new Class[]{ JdbcCoordinator.class }, new JdbcCoordinatorInvocationHandler(jdbcCoordinator, new StatementPreparerImpl(jdbcCoordinator, session.getFactory(), dbmsDialect, columns, returningSqlTypes, returningResult)));
+ Object sessionProxy = Proxy.newProxyInstance(session.getClass().getClassLoader(), new Class[]{ SessionImplementor.class, EventSource.class }, new Hibernate56SessionInvocationHandler(session, jdbcCoordinatorProxy));
+ return (SessionImplementor) sessionProxy;
+ }
+
+ @Override
+ public SessionFactoryImplementor wrapSessionFactory(SessionFactoryImplementor sessionFactory, DbmsDialect dbmsDialect) {
+ Object dialectProxy = new Hibernate56LimitHandlingDialect(sessionFactory.getDialect(), dbmsDialect);
+ Object sessionFactoryProxy = Proxy.newProxyInstance(sessionFactory.getClass().getClassLoader(), new Class[]{ SessionFactoryImplementor.class }, new Hibernate56SessionFactoryInvocationHandler(sessionFactory, dialectProxy));
+ return (SessionFactoryImplementor) sessionFactoryProxy;
+ }
+
+ @Override
+ public void checkTransactionSynchStatus(SessionImplementor session) {
+ TransactionCoordinator coordinator = session.getTransactionCoordinator();
+ coordinator.pulse();
+ if (coordinator instanceof JtaTransactionCoordinatorImpl) {
+ ((JtaTransactionCoordinatorImpl) coordinator).getSynchronizationCallbackCoordinator().processAnyDelayedAfterCompletion();
+ }
+ }
+
+ @Override
+ public void afterTransaction(SessionImplementor session, boolean success) {
+ TransactionCoordinator coordinator = session.getTransactionCoordinator();
+ if (!session.isTransactionInProgress() ) {
+ session.getJdbcCoordinator().afterTransaction();
+ }
+ if (coordinator instanceof JtaTransactionCoordinatorImpl) {
+ ((JtaTransactionCoordinatorImpl) coordinator).getSynchronizationCallbackCoordinator().processAnyDelayedAfterCompletion();
+ }
+ }
+
+ @Override
+ @SuppressWarnings({ "unchecked" })
+ public List