Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating multiple aliases for the same QueryDSL path in Spring Data

I have a generic Spring Data repository interface that extends QuerydslBinderCustomizer, allowing me to customize the query execution. I am trying to extend the basic equality testing built into the default repository implementation, so that I can perform other query operations using Spring Data REST. For example:

GET /api/persons?name=Joe%20Smith  // This works by default
GET /api/persons?nameEndsWith=Smith  // This requires custom parameter binding.

The problem I am having is that every alias of an entity path I create seems to override the preceding alias bindings.

@NoRepositoryBean
public interface BaseRepository<T, ID extends Serializable>
    extends PagingAndSortingRepository<T, ID>, QueryDslPredicateExecutor<T>, QuerydslBinderCustomizer { 

    @Override
    @SuppressWarnings("unchecked")
    default void customize(QuerydslBindings bindings, EntityPath entityPath){

        Class<T> model = entityPath.getType();
        Path<T> root = entityPath.getRoot();
        for (Field field: model.getDeclaredFields()){
            if (field.isSynthetic()) continue;
            Class<?> fieldType = field.getType();
            if (fieldType.isAssignableFrom(String.class)){
                // This binding works by itself, but not after the next one is added
                bindings.bind(Expressions.stringPath(root, field.getName()))
                        .as(field.getName()  + "EndsWith")
                        .first((path, value) -> {
                            return path.endsWith(value);
                        });
                // This binding overrides the previous one
                bindings.bind(Expressions.stringPath(root, field.getName()))
                        .as(field.getName()  + "StartsWith")
                        .first((path, value) -> {
                            return path.startsWith(value);
                        });
            }
        }
    }
}

Is it possible to create more than one alias for the same field? Can this be accomplished in a generic way?

like image 611
woemler Avatar asked Jan 15 '17 23:01

woemler


1 Answers

You can create a transient property bound to QueryDSL this way:

@Transient
@QueryType(PropertyType.SIMPLE)
public String getNameEndsWith() {
    // Whatever code, even return null
}

If you are using the QueryDSL annotation processor, you will see the "nameEndsWith" in the metadata Qxxx class, so you can bind it like any persisted property, but without persisting it.

like image 193
apetrelli Avatar answered Nov 02 '22 19:11

apetrelli