Skip to content

Commit 5883376

Browse files
authored
Update spring and hibernate versions and apply appropriate fixes (#171)
1 parent e7f1fb4 commit 5883376

File tree

9 files changed

+63
-34
lines changed

9 files changed

+63
-34
lines changed

pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@
2323
<java.version>17</java.version>
2424
<maven.compiler.target>17</maven.compiler.target>
2525
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
26-
<spring-boot.version>3.0.0</spring-boot.version>
27-
<spring-data-releasetrain.version>2022.0.0</spring-data-releasetrain.version>
26+
<spring-boot.version>3.4.1</spring-boot.version>
27+
<spring-data-releasetrain.version>2024.1.1</spring-data-releasetrain.version>
2828
<querydsl.version>4.1.4</querydsl.version>
2929
<rsql-parser.version>2.3.2</rsql-parser.version>
3030
<lombok.version>1.18.24</lombok.version>

rsql-common/pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@
3434
</dependency>
3535
<dependency>
3636
<groupId>io.hypersistence</groupId>
37-
<artifactId>hypersistence-utils-hibernate-62</artifactId>
38-
<version>3.5.1</version>
37+
<artifactId>hypersistence-utils-hibernate-63</artifactId>
38+
<version>3.9.0</version>
3939
<scope>test</scope>
4040
</dependency>
4141
<dependency>

rsql-common/src/main/java/io/github/perplexhub/rsql/RSQLVisitorBase.java

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package io.github.perplexhub.rsql;
22

33
import java.lang.reflect.*;
4+
import java.sql.Timestamp;
45
import java.time.*;
56
import java.time.format.DateTimeParseException;
67
import java.util.*;
@@ -13,6 +14,7 @@
1314
import jakarta.persistence.metamodel.PluralAttribute;
1415

1516
import lombok.Getter;
17+
import org.hibernate.metamodel.model.domain.ManagedDomainType;
1618
import org.springframework.core.convert.ConversionFailedException;
1719
import org.springframework.core.convert.support.ConfigurableConversionService;
1820
import org.springframework.orm.jpa.vendor.Database;
@@ -52,6 +54,15 @@ public static Database getDatabase(EntityManager entityManager) {
5254
return entityManagerDatabase.get(entityManager);
5355
}
5456

57+
public static <T> Attribute<? super T, ?> getAttribute(String property, ManagedType<T> classMetadata) {
58+
// W/A found here: https://hibernate.atlassian.net/browse/HHH-18569
59+
// breaking change on hibernate side: https://github.com/hibernate/hibernate-orm/pull/6924#discussion_r1250474422
60+
if (classMetadata instanceof ManagedDomainType managedDomainType) {
61+
return managedDomainType.findSubTypesAttribute(property);
62+
}
63+
return classMetadata.getAttribute(property);
64+
}
65+
5566
protected abstract Map<String, String> getPropertyPathMapper();
5667

5768
public Map<Class<?>, Map<String, String>> getPropertyRemapping() {
@@ -71,6 +82,9 @@ protected Object convert(String source, Class targetType) {
7182
object = UUID.fromString(source);
7283
} else if (targetType.equals(Date.class) || targetType.equals(java.sql.Date.class)) {
7384
object = java.sql.Date.valueOf(LocalDate.parse(source));
85+
} else if (targetType.equals(Timestamp.class)) {
86+
Date date = java.sql.Date.valueOf(LocalDate.parse(source));
87+
return new Timestamp(date.getTime());
7488
} else if (targetType.equals(LocalDate.class)) {
7589
object = LocalDate.parse(source);
7690
} else if (targetType.equals(LocalDateTime.class)) {
@@ -158,10 +172,10 @@ protected String mapProperty(String selector, Class<?> entityClass) {
158172

159173
protected <T> Class<?> findPropertyType(String property, ManagedType<T> classMetadata) {
160174
Class<?> propertyType = null;
161-
if (classMetadata.getAttribute(property).isCollection()) {
162-
propertyType = ((PluralAttribute) classMetadata.getAttribute(property)).getBindableJavaType();
175+
if (getAttribute(property, classMetadata).isCollection()) {
176+
propertyType = ((PluralAttribute) getAttribute(property, classMetadata)).getBindableJavaType();
163177
} else {
164-
propertyType = classMetadata.getAttribute(property).getJavaType();
178+
propertyType = getAttribute(property, classMetadata).getJavaType();
165179
}
166180
return propertyType;
167181
}
@@ -217,7 +231,7 @@ protected <T> ManagedType<T> getManagedElementCollectionType(String mappedProper
217231

218232
protected <T> boolean hasPropertyName(String property, ManagedType<T> classMetadata) {
219233
try {
220-
return classMetadata.getAttribute(property) != null;
234+
return getAttribute(property, classMetadata) != null;
221235
} catch (IllegalArgumentException e) {
222236
return false;
223237
}
@@ -238,30 +252,30 @@ protected static Class getElementCollectionGenericType(Class type, Attribute att
238252
}
239253

240254
protected <T> boolean isEmbeddedType(String property, ManagedType<T> classMetadata) {
241-
return classMetadata.getAttribute(property).getPersistentAttributeType() == PersistentAttributeType.EMBEDDED;
255+
return getAttribute(property, classMetadata).getPersistentAttributeType() == PersistentAttributeType.EMBEDDED;
242256
}
243257

244258
protected <T> boolean isElementCollectionType(String property, ManagedType<T> classMetadata) {
245-
return classMetadata.getAttribute(property).getPersistentAttributeType() == PersistentAttributeType.ELEMENT_COLLECTION;
259+
return getAttribute(property, classMetadata).getPersistentAttributeType() == PersistentAttributeType.ELEMENT_COLLECTION;
246260
}
247261

248262
protected <T> boolean isAssociationType(String property, ManagedType<T> classMetadata) {
249-
return classMetadata.getAttribute(property).isAssociation();
263+
return getAttribute(property, classMetadata).isAssociation();
250264
}
251265

252266
protected <T> boolean isOneToOneAssociationType(String property, ManagedType<T> classMetadata) {
253-
return classMetadata.getAttribute(property).isAssociation()
254-
&& PersistentAttributeType.ONE_TO_ONE == classMetadata.getAttribute(property).getPersistentAttributeType();
267+
return getAttribute(property, classMetadata).isAssociation()
268+
&& PersistentAttributeType.ONE_TO_ONE == getAttribute(property, classMetadata).getPersistentAttributeType();
255269
}
256270

257271
protected <T> boolean isOneToManyAssociationType(String property, ManagedType<T> classMetadata) {
258-
return classMetadata.getAttribute(property).isAssociation()
259-
&& PersistentAttributeType.ONE_TO_MANY == classMetadata.getAttribute(property).getPersistentAttributeType();
272+
return getAttribute(property, classMetadata).isAssociation()
273+
&& PersistentAttributeType.ONE_TO_MANY == getAttribute(property, classMetadata).getPersistentAttributeType();
260274
}
261275

262276
protected <T> boolean isManyToManyAssociationType(String property, ManagedType<T> classMetadata) {
263-
return classMetadata.getAttribute(property).isAssociation()
264-
&& PersistentAttributeType.MANY_TO_MANY == classMetadata.getAttribute(property).getPersistentAttributeType();
277+
return getAttribute(property, classMetadata).isAssociation()
278+
&& PersistentAttributeType.MANY_TO_MANY == getAttribute(property, classMetadata).getPersistentAttributeType();
265279
}
266280

267281
static {

rsql-jpa/pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@
5454
</dependency>
5555
<dependency>
5656
<groupId>io.hypersistence</groupId>
57-
<artifactId>hypersistence-utils-hibernate-60</artifactId>
58-
<version>3.5.2</version>
57+
<artifactId>hypersistence-utils-hibernate-63</artifactId>
58+
<version>3.9.0</version>
5959
<scope>test</scope>
6060
</dependency>
6161
<dependency>

rsql-jpa/src/main/java/io/github/perplexhub/rsql/RSQLJPAPredicateConverter.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import cz.jirutka.rsql.parser.ast.OrNode;
2323
import lombok.Getter;
2424
import lombok.extern.slf4j.Slf4j;
25+
import org.hibernate.query.criteria.JpaExpression;
2526

2627
@Slf4j
2728
@SuppressWarnings({ "rawtypes", "unchecked" })
@@ -83,7 +84,6 @@ private RSQLJPAContext findPropertyPathInternal(String propertyPath, Path startR
8384
Attribute<?, ?> attribute = null;
8485
String resolvedPropertyPath = firstTry? mapPropertyPath(propertyPath) : propertyPath;
8586
String[] properties = mapPropertyPath(resolvedPropertyPath).split("\\.");
86-
8787
for (int i = 0, propertiesLength = properties.length; i < propertiesLength; i++) {
8888
String property = properties[i];
8989
String mappedProperty = mapProperty(property, classMetadata.getJavaType());
@@ -140,14 +140,14 @@ private RSQLJPAContext findPropertyPathInternal(String propertyPath, Path startR
140140
}
141141
} else if (isElementCollectionType(mappedProperty, classMetadata)) {
142142
String previousClass = classMetadata.getJavaType().getName();
143-
attribute = classMetadata.getAttribute(property);
143+
attribute = RSQLVisitorBase.getAttribute(property, classMetadata);
144144
classMetadata = getManagedElementCollectionType(mappedProperty, classMetadata);
145145
String keyJoin = getKeyJoin(root, mappedProperty);
146146
log.debug("Create a element collection join between [{}] and [{}] using key [{}]", previousClass, classMetadata.getJavaType().getName(), keyJoin);
147147
root = join(keyJoin, root, mappedProperty);
148148
} else if (JsonbSupport.isJsonType(mappedProperty, classMetadata)) {
149149
root = root.get(mappedProperty);
150-
attribute = classMetadata.getAttribute(mappedProperty);
150+
attribute = RSQLVisitorBase.getAttribute(mappedProperty, classMetadata);
151151
break;
152152
} else {
153153
log.debug("Create property path for type [{}] property [{}]", classMetadata.getJavaType().getName(), mappedProperty);
@@ -158,7 +158,7 @@ private RSQLJPAContext findPropertyPathInternal(String propertyPath, Path startR
158158
type = embeddedType;
159159
classMetadata = getManagedType(embeddedType);
160160
} else {
161-
attribute = classMetadata.getAttribute(property);
161+
attribute = RSQLVisitorBase.getAttribute(property, classMetadata);
162162
}
163163
}
164164
}
@@ -246,7 +246,13 @@ private ResolvedExpression resolveExpression(ComparisonNode node, From root, Sel
246246
ComparisonNode jsonbNode = node.withSelector(jsonbPath);
247247
return JsonbSupport.jsonbPathExistsExpression(builder, jsonbNode, path);
248248
} else {
249-
return ResolvedExpression.ofPath(path.as(String.class), String.class);
249+
final Expression expression;
250+
if (path instanceof JpaExpression jpaExpression) {
251+
expression = jpaExpression.cast(String.class);
252+
} else {
253+
expression = path.as(String.class);
254+
}
255+
return ResolvedExpression.ofPath(expression, String.class);
250256
}
251257
} else {
252258
if (attribute != null

rsql-jpa/src/main/java/io/github/perplexhub/rsql/SortUtils.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import jakarta.persistence.criteria.Order;
1414
import jakarta.persistence.criteria.Root;
1515

16+
import org.hibernate.query.criteria.JpaExpression;
1617
import org.springframework.lang.Nullable;
1718
import org.springframework.util.StringUtils;
1819

@@ -63,16 +64,16 @@ private static Order sortToJpaOrder(final String[] parts, final SortSupport sort
6364
sortSupport.getJoinHints(), sortSupport.getProcedureWhiteList(),
6465
sortSupport.getProcedureBlackList());
6566

67+
final boolean ic = parts.length > 2 && "ic".equalsIgnoreCase(parts[2]);
6668
Expression<?> propertyExpression = selector.getExpression((string, builder) ->{
6769
final RSQLJPAContext rsqljpaContext = converter.findPropertyPath(string, root);
6870
final boolean isJson = JsonbSupport.isJsonType(rsqljpaContext.getAttribute());
6971
return isJson
70-
? sortExpressionOfJson(rsqljpaContext, string, sortSupport.getPropertyPathMapper(), builder)
72+
? sortExpressionOfJson(rsqljpaContext, string, sortSupport.getPropertyPathMapper(), builder, ic)
7173
: rsqljpaContext.getPath();
7274
});
7375

74-
if (parts.length > 2 && "ic".equalsIgnoreCase(parts[2])
75-
&& String.class.isAssignableFrom(propertyExpression.getJavaType())) {
76+
if (ic && String.class.isAssignableFrom(propertyExpression.getJavaType())) {
7677
propertyExpression = cb.lower(propertyExpression.as(String.class));
7778
}
7879

@@ -92,7 +93,8 @@ private static Order sortToJpaOrder(final String[] parts, final SortSupport sort
9293
private static Expression<?> sortExpressionOfJson(RSQLJPAContext context,
9394
String property,
9495
Map<String, String> mapping,
95-
CriteriaBuilder builder) {
96+
CriteriaBuilder builder,
97+
boolean ic) {
9698
String path = PathUtils.expectBestMapping(property, mapping);
9799
String jsonbSelector = JsonbSupport.jsonPathOfSelector(context.getAttribute(), path);
98100
if(jsonbSelector.contains(".")) {
@@ -102,7 +104,11 @@ private static Expression<?> sortExpressionOfJson(RSQLJPAContext context,
102104
.skip(1) // skip root
103105
.map(builder::literal)
104106
.forEach(args::add);
105-
return builder.function("jsonb_extract_path", String.class, args.toArray(Expression[]::new));
107+
Expression<?> expression = builder.function("jsonb_extract_path", Object.class, args.toArray(Expression[]::new));
108+
if (ic && expression instanceof JpaExpression<?> jpaExpression) {
109+
expression = jpaExpression.cast(String.class);
110+
}
111+
return expression;
106112
} else {
107113
return context.getPath().as(String.class);
108114
}

rsql-jpa/src/main/java/io/github/perplexhub/rsql/jsonb/JsonbSupport.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ && isJsonColumn(attribute)
9191
* @return true if the attribute is a jsonb attribute
9292
*/
9393
public static boolean isJsonType(String mappedProperty, ManagedType<?> classMetadata) {
94-
return Optional.ofNullable(classMetadata.getAttribute(mappedProperty))
94+
return Optional.ofNullable(RSQLVisitorBase.getAttribute(mappedProperty, classMetadata))
9595
.map(JsonbSupport::isJsonType)
9696
.orElse(false);
9797
}

rsql-jpa/src/test/java/io/github/perplexhub/rsql/RSQLJPASupportTest.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99
import static org.junit.jupiter.api.Assertions.assertEquals;
1010
import static org.junit.jupiter.api.Assertions.assertThrows;
1111

12+
import java.sql.Timestamp;
1213
import java.text.ParseException;
1314
import java.text.SimpleDateFormat;
15+
import java.time.LocalDate;
1416
import java.time.OffsetDateTime;
1517
import java.time.ZoneOffset;
1618
import java.util.*;
@@ -764,9 +766,9 @@ final void testBetweenDate() {
764766
@Test
765767
final void testBetweenDateTime() {
766768
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
767-
RSQLJPASupport.addConverter(Date.class, s -> {
769+
RSQLJPASupport.addConverter(Timestamp.class, s -> {
768770
try {
769-
return sdf.parse(s);
771+
return new Timestamp(sdf.parse(s).getTime());
770772
} catch (ParseException e) {
771773
return null;
772774
}

rsql-querydsl-spring-boot-starter/src/test/java/io/github/perplexhub/rsql/Application.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package io.github.perplexhub.rsql;
22

3+
import java.sql.Timestamp;
34
import java.text.SimpleDateFormat;
45
import java.util.Date;
56

@@ -23,9 +24,9 @@ public static void main(String[] args) throws Exception {
2324
@Bean
2425
public Object rsqlConfiguration(RSQLCommonSupport rsqlCommonSupport) {
2526
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
26-
RSQLCommonSupport.addConverter(Date.class, s -> {
27+
RSQLCommonSupport.addConverter(Timestamp.class, s -> {
2728
try {
28-
return sdf.parse(s);
29+
return new Timestamp(sdf.parse(s).getTime());
2930
} catch (Exception e) {
3031
return null;
3132
}

0 commit comments

Comments
 (0)