diff --git a/README.md b/README.md
index 9890b49..1ccd8cd 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,8 @@
# specification-with-projection
Support Projections with `JpaSpecificationExecutor.findAll(Specification,Pageable)` for Spring Data JPA
+>version 3.x.x for Spring Data JPA 3.x (Spring Boot 3.x)
+
>version 2.x.x for Spring Data JPA 2.x (Spring Boot 2.x)
>version 1.x.x Spring Data JPA 1.x
@@ -8,6 +10,14 @@ Support Projections with `JpaSpecificationExecutor.findAll(Specification,Pageabl
## How to use
* add dependency to pom
```xml
+
+
+ th.co.geniustree.springdata.jpa
+ specification-with-projections
+ 3.0.0
+
+```
+```xml
th.co.geniustree.springdata.jpa
diff --git a/pom.xml b/pom.xml
index d24b119..8889684 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,5 +1,6 @@
-
+
4.0.0
th.co.geniustree.springdata.jpa
@@ -13,14 +14,15 @@
org.springframework.boot
spring-boot-starter-parent
- 2.5.1
-
+ 3.1.5
+
UTF-8
UTF-8
- 1.8
+ 17
+ 17
@@ -73,12 +75,13 @@
org.hibernate
hibernate-jpamodelgen
+ 6.3.1.Final
provided
org.projectlombok
lombok
- 1.18.4
+ 1.18.30
provided
@@ -112,7 +115,7 @@
org.apache.maven.plugins
maven-source-plugin
- 3.0.1
+ 3.3.0
attach-sources
@@ -125,7 +128,7 @@
org.apache.maven.plugins
maven-javadoc-plugin
- 2.10.4
+ 3.6.0
attach-javadocs
@@ -138,7 +141,7 @@
org.apache.maven.plugins
maven-gpg-plugin
- 1.6
+ 3.1.0
sign-artifacts
diff --git a/src/main/java/org/springframework/data/repository/query/TupleConverter.java b/src/main/java/org/springframework/data/repository/query/TupleConverter.java
index a32a112..abd873b 100644
--- a/src/main/java/org/springframework/data/repository/query/TupleConverter.java
+++ b/src/main/java/org/springframework/data/repository/query/TupleConverter.java
@@ -4,8 +4,8 @@
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
-import javax.persistence.Tuple;
-import javax.persistence.TupleElement;
+import jakarta.persistence.Tuple;
+import jakarta.persistence.TupleElement;
import java.util.*;
import java.util.stream.Collectors;
diff --git a/src/main/java/th/co/geniustree/springdata/jpa/repository/JpaSpecificationExecutorWithProjection.java b/src/main/java/th/co/geniustree/springdata/jpa/repository/JpaSpecificationExecutorWithProjection.java
index 2e2a3e4..5adbc83 100644
--- a/src/main/java/th/co/geniustree/springdata/jpa/repository/JpaSpecificationExecutorWithProjection.java
+++ b/src/main/java/th/co/geniustree/springdata/jpa/repository/JpaSpecificationExecutorWithProjection.java
@@ -17,7 +17,7 @@
public interface JpaSpecificationExecutorWithProjection {
Optional findById(ID id, Class projectionClass);
-
+
Optional findOne(Specification spec, Class projectionClass);
Page findAll(Specification spec, Class projectionClass, Pageable pageable);
diff --git a/src/main/java/th/co/geniustree/springdata/jpa/repository/support/DefaultQueryHints.java b/src/main/java/th/co/geniustree/springdata/jpa/repository/support/DefaultQueryHints.java
index 6e9fb0a..55e6d32 100644
--- a/src/main/java/th/co/geniustree/springdata/jpa/repository/support/DefaultQueryHints.java
+++ b/src/main/java/th/co/geniustree/springdata/jpa/repository/support/DefaultQueryHints.java
@@ -25,7 +25,7 @@
import org.springframework.data.util.Optionals;
import org.springframework.util.Assert;
-import javax.persistence.EntityManager;
+import jakarta.persistence.EntityManager;
import java.util.*;
import java.util.function.BiConsumer;
diff --git a/src/main/java/th/co/geniustree/springdata/jpa/repository/support/JpaSpecificationExecutorWithProjectionImpl.java b/src/main/java/th/co/geniustree/springdata/jpa/repository/support/JpaSpecificationExecutorWithProjectionImpl.java
index 81995b7..1897b89 100644
--- a/src/main/java/th/co/geniustree/springdata/jpa/repository/support/JpaSpecificationExecutorWithProjectionImpl.java
+++ b/src/main/java/th/co/geniustree/springdata/jpa/repository/support/JpaSpecificationExecutorWithProjectionImpl.java
@@ -20,24 +20,24 @@
import org.springframework.data.repository.query.ReturnTypeWarpper;
import org.springframework.data.repository.query.ReturnedType;
import org.springframework.data.repository.query.TupleConverter;
-import org.springframework.data.repository.support.PageableExecutionUtils;
+import org.springframework.data.support.PageableExecutionUtils;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import th.co.geniustree.springdata.jpa.repository.JpaSpecificationExecutorWithProjection;
-import javax.persistence.*;
-import javax.persistence.criteria.*;
-import javax.persistence.metamodel.Attribute;
-import javax.persistence.metamodel.Bindable;
-import javax.persistence.metamodel.ManagedType;
-import javax.persistence.metamodel.PluralAttribute;
+import jakarta.persistence.*;
+import jakarta.persistence.criteria.*;
+import jakarta.persistence.metamodel.Attribute;
+import jakarta.persistence.metamodel.Bindable;
+import jakarta.persistence.metamodel.ManagedType;
+import jakarta.persistence.metamodel.PluralAttribute;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Member;
import java.util.*;
-import static javax.persistence.metamodel.Attribute.PersistentAttributeType.*;
+import static jakarta.persistence.metamodel.Attribute.PersistentAttributeType.*;
/**
@@ -68,11 +68,11 @@ public JpaSpecificationExecutorWithProjectionImpl(JpaEntityInformation entityInf
this.entityManager = entityManager;
this.entityInformation = entityInformation;
}
-
+
@Override
public Optional findById(ID id, Class projectionType) {
final ReturnedType returnedType = ReturnTypeWarpper.of(projectionType, getDomainClass(), projectionFactory);
-
+
CriteriaBuilder builder = this.entityManager.getCriteriaBuilder();
CriteriaQuery q = builder.createQuery(Tuple.class);
Root root = q.from(getDomainClass());
@@ -90,9 +90,9 @@ public Optional findById(ID id, Class projectionType) {
} else {
throw new IllegalArgumentException("only except projection");
}
-
+
final TypedQuery query = this.applyRepositoryMethodMetadata(this.entityManager.createQuery(q));
-
+
try {
final MyResultProcessor resultProcessor = new MyResultProcessor(projectionFactory,returnedType);
final R singleResult = resultProcessor.processResult(query.getSingleResult(), new TupleConverter(returnedType));
diff --git a/src/test/java/th/co/geniustree/springdata/jpa/SpecificationExecutorProjectionTest.java b/src/test/java/th/co/geniustree/springdata/jpa/SpecificationExecutorProjectionTest.java
index b78f130..54bd10c 100644
--- a/src/test/java/th/co/geniustree/springdata/jpa/SpecificationExecutorProjectionTest.java
+++ b/src/test/java/th/co/geniustree/springdata/jpa/SpecificationExecutorProjectionTest.java
@@ -4,6 +4,7 @@
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
@@ -19,6 +20,7 @@
@ExtendWith(SpringExtension.class)
@DataJpaTest
@Transactional
+@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
public class SpecificationExecutorProjectionTest {
@Autowired
private DocumentRepository documentRepository;
@@ -27,7 +29,7 @@ public class SpecificationExecutorProjectionTest {
@Test
public void findAll() {
Specification where = Specification.where(DocumentSpecs.idEq(1L));
- Page all = documentRepository.findAll(where, DocumentRepository.DocumentWithoutParent.class, PageRequest.of(0,10));
+ Page all = documentRepository.findAll(where, DocumentRepository.DocumentWithoutParent.class, PageRequest.of(0, 10));
Assertions.assertThat(all).isNotEmpty();
Assertions.assertThat(all.getContent().get(0).getDocumentType()).isEqualTo("ต้นฉบับ");
}
@@ -35,7 +37,7 @@ public void findAll() {
@Test
public void findAll2() {
Specification where = Specification.where(DocumentSpecs.idEq(1L));
- Page all = documentRepository.findAll(where, DocumentRepository.DocumentWithoutParent.class, PageRequest.of(0,10));
+ Page all = documentRepository.findAll(where, DocumentRepository.DocumentWithoutParent.class, PageRequest.of(0, 10));
Assertions.assertThat(all).isNotEmpty();
Assertions.assertThat(all.getContent().get(0).getChild().size()).isEqualTo(1);
}
@@ -43,7 +45,7 @@ public void findAll2() {
@Test
public void findAll3() {
Specification where = Specification.where(DocumentSpecs.idEq(1L));
- Page all = documentRepository.findAll(where, DocumentRepository.OnlyId.class, PageRequest.of(0,10));
+ Page all = documentRepository.findAll(where, DocumentRepository.OnlyId.class, PageRequest.of(0, 10));
Assertions.assertThat(all).isNotEmpty();
Assertions.assertThat(all.getContent().get(0).getId()).isEqualTo(1L);
}
@@ -51,7 +53,7 @@ public void findAll3() {
@Test
public void findAll4() {
Specification where = Specification.where(DocumentSpecs.idEq(24L));
- Page all = documentRepository.findAll(where, DocumentRepository.DocumentWithoutParent.class, PageRequest.of(0,10));
+ Page all = documentRepository.findAll(where, DocumentRepository.DocumentWithoutParent.class, PageRequest.of(0, 10));
Assertions.assertThat(all).isNotEmpty();
Assertions.assertThat(all.getContent().get(0).getChild()).isNull();
}
@@ -59,14 +61,15 @@ public void findAll4() {
@Test
public void findAll5() {
Specification where = Specification.where(DocumentSpecs.idEq(24L));
- Page all = documentRepository.findAll(where, DocumentRepository.OnlyParent.class, PageRequest.of(0,10));
+ Page all = documentRepository.findAll(where, DocumentRepository.OnlyParent.class, PageRequest.of(0, 10));
Assertions.assertThat(all).isNotEmpty();
Assertions.assertThat(all.getContent().get(0).getParent().getId()).isEqualTo(13L);
}
+
@Test
public void find_single_page() {
Specification where = Specification.where(DocumentSpecs.idEq(24L));
- Page all = documentRepository.findAll(where, DocumentRepository.OnlyParent.class, PageRequest.of(0,10));
+ Page all = documentRepository.findAll(where, DocumentRepository.OnlyParent.class, PageRequest.of(0, 10));
Assertions.assertThat(all).isNotEmpty();
Assertions.assertThat(all.getTotalElements()).isEqualTo(1);
Assertions.assertThat(all.getTotalPages()).isEqualTo(1);
@@ -75,7 +78,7 @@ public void find_single_page() {
@Test
public void find_all_page() {
Specification where = Specification.where(null);
- Page all = documentRepository.findAll(where, DocumentRepository.OnlyParent.class, PageRequest.of(0,10));
+ Page all = documentRepository.findAll(where, DocumentRepository.OnlyParent.class, PageRequest.of(0, 10));
Assertions.assertThat(all).isNotEmpty();
Assertions.assertThat(all.getTotalElements()).isEqualTo(24);
Assertions.assertThat(all.getTotalPages()).isEqualTo(3);
@@ -87,13 +90,13 @@ public void findOne() {
Optional one = documentRepository.findOne(where, DocumentRepository.DocumentWithoutParent.class);
Assertions.assertThat(one.get().getDocumentType()).isEqualTo("ต้นฉบับ");
}
-
+
@Test
public void findBydId() {
Optional one = documentRepository.findById(1L, DocumentRepository.DocumentWithoutParent.class);
Assertions.assertThat(one.get().getDocumentType()).isEqualTo("ต้นฉบับ");
}
-
+
@Test
public void findOneWithOpenProjection() {
Specification where = Specification.where(DocumentSpecs.idEq(1L));
@@ -104,7 +107,7 @@ public void findOneWithOpenProjection() {
@Test
public void findAllWithOpenProjection() {
Specification where = Specification.where(DocumentSpecs.idEq(1L));
- Page page = documentRepository.findAll(where, DocumentRepository.OpenProjection.class,PageRequest.of(0,10));
+ Page page = documentRepository.findAll(where, DocumentRepository.OpenProjection.class, PageRequest.of(0, 10));
Assertions.assertThat(page.getContent().get(0).getDescriptionString()).isEqualTo("descriptiontest");
}
diff --git a/src/test/java/th/co/geniustree/springdata/jpa/domain/Document.java b/src/test/java/th/co/geniustree/springdata/jpa/domain/Document.java
index e88cf40..ea7dab6 100644
--- a/src/test/java/th/co/geniustree/springdata/jpa/domain/Document.java
+++ b/src/test/java/th/co/geniustree/springdata/jpa/domain/Document.java
@@ -1,6 +1,6 @@
package th.co.geniustree.springdata.jpa.domain;
-import javax.persistence.*;
+import jakarta.persistence.*;
import java.io.Serializable;
import java.util.List;
import java.util.Objects;
diff --git a/src/test/java/th/co/geniustree/springdata/jpa/domain/FormType.java b/src/test/java/th/co/geniustree/springdata/jpa/domain/FormType.java
index e5b280f..3f099eb 100644
--- a/src/test/java/th/co/geniustree/springdata/jpa/domain/FormType.java
+++ b/src/test/java/th/co/geniustree/springdata/jpa/domain/FormType.java
@@ -1,6 +1,7 @@
package th.co.geniustree.springdata.jpa.domain;
-import javax.persistence.*;
+import jakarta.persistence.*;
+
import java.io.Serializable;
/**
diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties
index 7631a18..dc7c074 100644
--- a/src/test/resources/application.properties
+++ b/src/test/resources/application.properties
@@ -1,10 +1,10 @@
################## JPA
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.properties.hibernate.cache.use_second_level_cache=false
-spring.jpa.hibernate.use-new-id-generator-mappings=true
+spring.jpa.properties.hibernate.id.new_generator_mappings=true
spring.sql.init.mode=always
################## spring.datasource
-spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_ON_EXIT=FALSE
+spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_ON_EXIT=FALSE;MODE=LEGACY
# spring.datasource.username=sa
# spring.datasource.password=sa
spring.datasource.driver-class-name=org.h2.Driver
diff --git a/src/test/resources/import.sql b/src/test/resources/import.sql
index b2cbb7e..dd14ad2 100644
--- a/src/test/resources/import.sql
+++ b/src/test/resources/import.sql
@@ -1,9 +1,9 @@
-insert into form_type values('01', 'ก.01');
-insert into form_type values('04', 'ก.04');
-insert into form_type values('05', 'ก.05');
-insert into form_type values('06', 'ก.06');
-insert into form_type values('07', 'ก.07');
-insert into form_type values('08', 'ก.08');
+insert into form_type (id, form_desc) values('01', 'ก.01');
+insert into form_type (id, form_desc) values('04', 'ก.04');
+insert into form_type (id, form_desc) values('05', 'ก.05');
+insert into form_type (id, form_desc) values('06', 'ก.06');
+insert into form_type (id, form_desc) values('07', 'ก.07');
+insert into form_type (id, form_desc) values('08', 'ก.08');
insert into document (id, description, category, type, FLAG_HAS_SUB, FORM_TYPE_ID) values(DOCUMENT_SEQ.nextVal, 'descriptiontest', 'ก.01', 'ต้นฉบับ', 'false', '01');
insert into document (id, description, category, type, FLAG_HAS_SUB, FORM_TYPE_ID) values(DOCUMENT_SEQ.nextVal, 'description', 'ก.01', 'ต้นฉบับ', 'true', '01');