Consider property path root in QuerydslBindings.

We now consider a qualified property path when registering and querying `QuerydslBindings` to ensure that paths matching various domain types do not accidentally get applied for a different type than they were registered for.
Previously, a binding for `Address.description` would be also applied to `User.description` as only the property path `description` was considered when looking up bindings.

Closes: #2418
Original Pull Request: #2422
This commit is contained in:
Mark Paluch
2021-07-29 11:46:31 +02:00
committed by Christoph Strobl
parent 0505fc4975
commit bb3898add3
10 changed files with 211 additions and 26 deletions

View File

@@ -31,6 +31,14 @@ import com.querydsl.core.types.Path;
*/
interface PathInformation {
/**
* The root property owner type.
*
* @return
* @since 2.5.5
*/
Class<?> getRootParentType();
/**
* The type of the leaf property.
*

View File

@@ -35,6 +35,7 @@ import com.querydsl.core.types.dsl.CollectionPathBase;
*
* @author Oliver Gierke
* @author Christoph Strobl
* @author Mark Paluch
* @since 1.13
*/
class PropertyPathInformation implements PathInformation {
@@ -71,6 +72,15 @@ class PropertyPathInformation implements PathInformation {
return new PropertyPathInformation(path);
}
/*
* (non-Javadoc)
* @see org.springframework.data.querydsl.binding.PathInformation#getRootParentType()
*/
@Override
public Class<?> getRootParentType() {
return path.getOwningType().getType();
}
/*
* (non-Javadoc)
* @see org.springframework.data.querydsl.binding.PathInformation#getLeafType()
@@ -162,12 +172,13 @@ class PropertyPathInformation implements PathInformation {
return true;
}
if (!(o instanceof PropertyPathInformation)) {
if (!(o instanceof PathInformation)) {
return false;
}
PropertyPathInformation that = (PropertyPathInformation) o;
return ObjectUtils.nullSafeEquals(path, that.path);
PathInformation that = (PathInformation) o;
return ObjectUtils.nullSafeEquals(getRootParentType(), that.getRootParentType())
&& ObjectUtils.nullSafeEquals(toDotPath(), that.toDotPath());
}
/*
@@ -176,7 +187,9 @@ class PropertyPathInformation implements PathInformation {
*/
@Override
public int hashCode() {
return ObjectUtils.nullSafeHashCode(path);
int result = ObjectUtils.nullSafeHashCode(getRootParentType());
result = 31 * result + ObjectUtils.nullSafeHashCode(toDotPath());
return result;
}
/*

View File

@@ -65,6 +65,7 @@ import com.querydsl.core.types.Path;
*/
public class QuerydslBindings {
// pathSpecs key format: <class.simpleName>.<pathInformation.toDotPath>
private final Map<String, PathAndBinding<?, ?>> pathSpecs;
private final Map<Class<?>, PathAndBinding<?, ?>> typeSpecs;
private final Set<String> allowList;
@@ -203,7 +204,7 @@ public class QuerydslBindings {
Assert.notNull(path, "PropertyPath must not be null!");
PathAndBinding<S, T> pathAndBinding = (PathAndBinding<S, T>) pathSpecs.get(path.toDotPath());
PathAndBinding<S, T> pathAndBinding = (PathAndBinding<S, T>) pathSpecs.get(createKey(path));
if (pathAndBinding != null) {
@@ -229,7 +230,7 @@ public class QuerydslBindings {
Assert.notNull(path, "PropertyPath must not be null!");
return Optional.ofNullable(pathSpecs.get(path.toDotPath())).flatMap(PathAndBinding::getPath);
return Optional.ofNullable(pathSpecs.get(createKey(path))).flatMap(PathAndBinding::getPath);
}
/**
@@ -249,6 +250,15 @@ public class QuerydslBindings {
return null;
}
// fully-qualified path lookup
String key = createKey(type, path);
if (pathSpecs.containsKey(key)) {
return pathSpecs.get(key).getPath()//
.map(QuerydslPathInformation::of)//
.orElse(null);
}
// alias lookup
if (pathSpecs.containsKey(path)) {
return pathSpecs.get(path).getPath()//
.map(QuerydslPathInformation::of)//
@@ -263,6 +273,28 @@ public class QuerydslBindings {
}
}
/**
* Returns the property path key for the given {@link Path}.
*
* @param path can be {@literal null}.
* @return
*/
private static String createKey(Optional<Path<?>> path) {
return path.map(QuerydslPathInformation::of).map(QuerydslBindings::createKey).orElse("");
}
private static String createKey(PathInformation path) {
return createKey(path.getRootParentType(), path.toDotPath());
}
private static String createKey(TypeInformation<?> type, String path) {
return createKey(type.getType(), path);
}
private static String createKey(Class<?> type, String path) {
return type.getSimpleName() + "." + path;
}
/**
* Checks if a given {@link PropertyPath} should be visible for binding values.
*
@@ -385,7 +417,7 @@ public class QuerydslBindings {
}
protected void registerBinding(PathAndBinding<P, T> binding) {
QuerydslBindings.this.pathSpecs.put(toDotPath(binding.getPath()), binding);
QuerydslBindings.this.pathSpecs.put(createKey(binding.getPath()), binding);
}
}
@@ -455,10 +487,12 @@ public class QuerydslBindings {
super.registerBinding(binding);
String dotPath = toDotPath(binding.getPath());
if (alias != null) {
QuerydslBindings.this.pathSpecs.put(alias, binding);
QuerydslBindings.this.aliases.add(alias);
QuerydslBindings.this.denyList.add(toDotPath(binding.getPath()));
QuerydslBindings.this.denyList.add(dotPath);
}
}
}

View File

@@ -29,6 +29,7 @@ import com.querydsl.core.types.Path;
* {@link PathInformation} based on a Querydsl {@link Path}.
*
* @author Oliver Gierke
* @author Mark Paluch
* @since 1.13
*/
class QuerydslPathInformation implements PathInformation {
@@ -45,7 +46,16 @@ class QuerydslPathInformation implements PathInformation {
/*
* (non-Javadoc)
* @see org.springframework.data.querydsl.binding.MappedPath#getLeafType()
* @see org.springframework.data.querydsl.binding.PathInformation#getRootParentType()
*/
@Override
public Class<?> getRootParentType() {
return path.getRoot().getType();
}
/*
* (non-Javadoc)
* @see org.springframework.data.querydsl.binding.PathInformation#getLeafType()
*/
@Override
public Class<?> getLeafType() {
@@ -54,7 +64,7 @@ class QuerydslPathInformation implements PathInformation {
/*
* (non-Javadoc)
* @see org.springframework.data.querydsl.binding.MappedPath#getLeafParentType()
* @see org.springframework.data.querydsl.binding.PathInformation#getLeafParentType()
*/
@Override
public Class<?> getLeafParentType() {
@@ -70,7 +80,7 @@ class QuerydslPathInformation implements PathInformation {
/*
* (non-Javadoc)
* @see org.springframework.data.querydsl.binding.MappedPath#getLeafProperty()
* @see org.springframework.data.querydsl.binding.PathInformation#getLeafProperty()
*/
@Override
public String getLeafProperty() {
@@ -79,7 +89,7 @@ class QuerydslPathInformation implements PathInformation {
/*
* (non-Javadoc)
* @see org.springframework.data.querydsl.binding.MappedPath#getLeafPropertyDescriptor()
* @see org.springframework.data.querydsl.binding.PathInformation#getLeafPropertyDescriptor()
*/
@Nullable
@Override
@@ -89,7 +99,7 @@ class QuerydslPathInformation implements PathInformation {
/*
* (non-Javadoc)
* @see org.springframework.data.querydsl.binding.MappedPath#toDotPath()
* @see org.springframework.data.querydsl.binding.PathInformation#toDotPath()
*/
@Override
public String toDotPath() {
@@ -115,12 +125,13 @@ class QuerydslPathInformation implements PathInformation {
return true;
}
if (!(o instanceof QuerydslPathInformation)) {
if (!(o instanceof PathInformation)) {
return false;
}
QuerydslPathInformation that = (QuerydslPathInformation) o;
return ObjectUtils.nullSafeEquals(path, that.path);
PathInformation that = (PathInformation) o;
return ObjectUtils.nullSafeEquals(getRootParentType(), that.getRootParentType())
&& ObjectUtils.nullSafeEquals(toDotPath(), that.toDotPath());
}
/*
@@ -129,7 +140,9 @@ class QuerydslPathInformation implements PathInformation {
*/
@Override
public int hashCode() {
return ObjectUtils.nullSafeHashCode(path);
int result = ObjectUtils.nullSafeHashCode(getRootParentType());
result = 31 * result + ObjectUtils.nullSafeHashCode(toDotPath());
return result;
}
/*