diff --git a/persistence-modules/hibernate-annotations/pom.xml b/persistence-modules/hibernate-annotations/pom.xml
index 6f11888643..12a5298e95 100644
--- a/persistence-modules/hibernate-annotations/pom.xml
+++ b/persistence-modules/hibernate-annotations/pom.xml
@@ -81,6 +81,16 @@
hypersistence-utils-hibernate-60
${hypersistance-utils-hibernate-60.version}
+
+ org.liquibase
+ liquibase-core
+ ${liquibase-core.version}
+
+
+ org.projectlombok
+ lombok
+ ${lombok.version}
+
@@ -91,6 +101,8 @@
true
9.0.0.M26
3.3.1
+ 1.18.30
+ 4.24.0
\ No newline at end of file
diff --git a/persistence-modules/hibernate-annotations/src/main/java/com/baeldung/hibernate/oneToMany/config/HibernateAnnotationUtil.java b/persistence-modules/hibernate-annotations/src/main/java/com/baeldung/hibernate/oneToMany/config/HibernateAnnotationUtil.java
index 99410e1f76..0bf03e3fee 100644
--- a/persistence-modules/hibernate-annotations/src/main/java/com/baeldung/hibernate/oneToMany/config/HibernateAnnotationUtil.java
+++ b/persistence-modules/hibernate-annotations/src/main/java/com/baeldung/hibernate/oneToMany/config/HibernateAnnotationUtil.java
@@ -4,6 +4,7 @@ import com.baeldung.hibernate.oneToMany.model.Cart;
import com.baeldung.hibernate.oneToMany.model.CartOIO;
import com.baeldung.hibernate.oneToMany.model.Item;
import com.baeldung.hibernate.oneToMany.model.ItemOIO;
+import com.baeldung.hibernate.subselect.RuntimeConfiguration;
import org.hibernate.SessionFactory;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources;
@@ -38,6 +39,7 @@ public class HibernateAnnotationUtil {
.addAnnotatedClass(CartOIO.class)
.addAnnotatedClass(Item.class)
.addAnnotatedClass(ItemOIO.class)
+ .addAnnotatedClass(RuntimeConfiguration.class)
.buildMetadata();
return metadata.buildSessionFactory();
diff --git a/persistence-modules/hibernate-annotations/src/main/java/com/baeldung/hibernate/subselect/RuntimeConfiguration.java b/persistence-modules/hibernate-annotations/src/main/java/com/baeldung/hibernate/subselect/RuntimeConfiguration.java
new file mode 100644
index 0000000000..0f995bfe03
--- /dev/null
+++ b/persistence-modules/hibernate-annotations/src/main/java/com/baeldung/hibernate/subselect/RuntimeConfiguration.java
@@ -0,0 +1,43 @@
+package com.baeldung.hibernate.subselect;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.Id;
+import java.time.Instant;
+import lombok.Data;
+import lombok.experimental.Accessors;
+import org.hibernate.annotations.Subselect;
+
+@Data
+@Accessors(chain = true)
+@Entity
+// language=sql
+@Subselect(value =
+ "SELECT\n"
+ + " ss.id,\n"
+ + " ss.attr_key,\n"
+ + " ss.val,\n"
+ + " ss.created_at\n"
+ + " FROM system_settings AS ss\n"
+ + " INNER JOIN (\n"
+ + " SELECT\n"
+ + " ss2.attr_key as k2,\n"
+ + " MAX(ss2.created_at) as ca2\n"
+ + " FROM system_settings ss2\n"
+ + " GROUP BY ss2.attr_key\n"
+ + " ) AS t ON t.k2 = ss.attr_key AND t.ca2 = ss.created_at\n"
+ + " WHERE ss.type = 'SYSTEM' AND ss.active IS TRUE\n")
+public class RuntimeConfiguration {
+
+ @Id
+ private Long id;
+
+ @Column(name = "attr_key")
+ private String key;
+
+ @Column(name = "val")
+ private String value;
+
+ @Column(name = "created_at")
+ private Instant createdAt;
+}
diff --git a/persistence-modules/hibernate-annotations/src/main/resources/migrations/V1__init.xml b/persistence-modules/hibernate-annotations/src/main/resources/migrations/V1__init.xml
new file mode 100644
index 0000000000..5970821ccd
--- /dev/null
+++ b/persistence-modules/hibernate-annotations/src/main/resources/migrations/V1__init.xml
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+ splitting.enabled
+ true
+ true
+ SYSTEM
+
+
+
+
+ 2
+ splitting.enabled
+ false
+ false
+ SYSTEM
+
+
+
+
+ 3
+ redelivery.enabled
+ false
+ true
+ ORDER
+
+
+
+
\ No newline at end of file
diff --git a/persistence-modules/hibernate-annotations/src/main/resources/migrations/master.xml b/persistence-modules/hibernate-annotations/src/main/resources/migrations/master.xml
new file mode 100644
index 0000000000..ba16dc7b8b
--- /dev/null
+++ b/persistence-modules/hibernate-annotations/src/main/resources/migrations/master.xml
@@ -0,0 +1,7 @@
+
+
+
+
\ No newline at end of file
diff --git a/persistence-modules/hibernate-annotations/src/test/java/com/baeldung/hibernate/subselect/SubselectIntegrationTest.java b/persistence-modules/hibernate-annotations/src/test/java/com/baeldung/hibernate/subselect/SubselectIntegrationTest.java
new file mode 100644
index 0000000000..074468ca37
--- /dev/null
+++ b/persistence-modules/hibernate-annotations/src/test/java/com/baeldung/hibernate/subselect/SubselectIntegrationTest.java
@@ -0,0 +1,65 @@
+package com.baeldung.hibernate.subselect;
+
+import com.baeldung.hibernate.oneToMany.config.HibernateAnnotationUtil;
+import jakarta.persistence.criteria.Root;
+import liquibase.Contexts;
+import liquibase.LabelExpression;
+import liquibase.Liquibase;
+import liquibase.database.DatabaseFactory;
+import liquibase.database.jvm.JdbcConnection;
+import liquibase.exception.LiquibaseException;
+import liquibase.resource.ClassLoaderResourceAccessor;
+import org.hibernate.Session;
+import jakarta.persistence.criteria.CriteriaBuilder;
+import jakarta.persistence.criteria.CriteriaQuery;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+public class SubselectIntegrationTest {
+
+ @BeforeAll
+ static void setUp() {
+ Session currentSession = HibernateAnnotationUtil.getSessionFactory().getCurrentSession();
+ currentSession.beginTransaction();
+
+ currentSession.doWork(it -> {
+ Liquibase liquibase;
+ try {
+ liquibase = new Liquibase(
+ "migrations/master.xml",
+ new ClassLoaderResourceAccessor(),
+ DatabaseFactory.getInstance().findCorrectDatabaseImplementation(new JdbcConnection(it))
+ );
+ liquibase.update(new Contexts(), new LabelExpression(),true);
+ } catch (LiquibaseException e) {
+ throw new RuntimeException(e);
+ }
+ });
+
+ currentSession.getTransaction().commit();
+ }
+
+ @Test
+ void givenEntityMarkedWithSubselect_whenSelectingRuntimeConfigByKey_thenSelectedSuccessfully() {
+ String key = "splitting.enabled";
+ Session entityManager = HibernateAnnotationUtil.getSessionFactory().getCurrentSession();
+
+ entityManager.beginTransaction();
+
+ CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
+
+ CriteriaQuery query = criteriaBuilder.createQuery(RuntimeConfiguration.class);
+
+ Root root = query.from(RuntimeConfiguration.class);
+
+ RuntimeConfiguration configurationParameter = entityManager.createQuery(
+ query.select(root).where(criteriaBuilder.equal(root.get("key"), key))
+ ).getSingleResult();
+
+ entityManager.getTransaction().commit();
+
+ Assertions.assertThat(configurationParameter.getValue()).isEqualTo("true");
+ }
+}
+