QuerydslPredicateArgumentResolver now properly handles predicate lookups that result in null values. The semantics of a handler method parameter of type of Querydsl's Predicate have been tightened to always see a non-null Predicate by default. Users that want to handle the absence of predicates explicitly can opt into seeing null by annotating the parameter with @Nullable or use Optional<Predicate>.
QuerydslPredicateBuilder now consistently returns null in case the original parameter map is entirely empty or consists of only keys with empty value arrays as empty form submissions do. This partially reverts the work of DATACMNS-1168, which moved into the direction of returning a default Predicate value for empty maps in the first place. That however prevents us from producing empty Optionals.
Related tickets: DATACMNS-1168.
We now explicitly rejects null values for the Sort parameters in the constructor of PageRequest to avoid the creation of invalid instances if the IDE validation of nullability constraints is not in use.
Replace AtTest(expected = …) and ExpectedException with the corresponding AssertJ assertThatExceptionOfType(…) and assertThatIllegalArgumentException().isThrownBy(…).
We now use StringUtils.hasLength(…) in the check whether to drop request elements from binding instead of ….hasText(…) as the latter drops blank strings so that's impossible to search for properties that contain a blank.
We now follow a more consistent naming scheme for the methods in repository that are driven by the following guidelines:
* Methods referring to an identifier now all end on …ById(…).
* Methods taking or returning a collection are named …All(…)
That results in the following renames:
* findOne(…) -> findById(…)
* save(Iterable) -> saveAll(Iterable)
* findAll(Iterable<ID>) -> findAllById(…)
* delete(ID) -> deleteById(ID)
* delete(Iterable<T>) -> deleteAll(Iterable<T>)
* exists() -> existsById(…)
As a side-effect of that, we can now drop the Serializable requirement for identifiers.
Updated CRUD method detection to use the new naming scheme and moved the code to Java 8 streams and Optional. Adapted RepositoryInvoker API to reflect method name changes as well.
Make use of lambdas and method references though out the codebase. Remove no longer required generic type parameters.
Additionally remove unused imports and replace single element list initialization with dedicated singletonList.
Use Assertion overloads taking Supplier for dynamic assertion error messages.
We now support downcasts (e.g. user.as(QSpecialUser.class).…) expressions in Querydsl web binding. We do so by skipping the introduced intermediate step in the path when calculating the dot path.
Refactored the internals of the binding to now work based on a PathInformation implementation for which either a Querydsl Path or a Spring Data PropertyPath can be used. This allows us to reuse the paths of predefined bindings.
A bit of Lombok cleanup in internal implementations.
Improved the dot-path translation of existing Querydsl Path instances by not relying on the toString() representation of the metadata but manually traversing the elements up to the root. Extracted the translation method into QueryDslUtils.
Furthermore, we now automatically insert an CollectionPathBase.any() step for Path instances of that type when reifying the paths from request attributes.
If a single path is now handed to QuerydslBindings.bind(…), a specialized AliasingPathBinder is returned which allows defining an alias the binding will be exposed under.
By default that alias will cause the original binding being black-listed and thus become unavailable for binding. This can be overridden by explicitly white-listing the properties to be bindable.
Switched to new Querydsl 4 artifacts and adapted to changed package names and API changes.
Cleaned up some JavaDoc and APIs in QuerydslBindingsFactory and QuerydslBinderCustomizer.
If standard Querydsl StringPaths are used without any reference to a query class tree, we previously dropped the first segment of the path expression.
Moved to a completely different algorithm to determine the path by just using the Path's toString() representation and the root removed if necessary.
QuerydslBindingsFactory creates a completely build up and customized QuerydslBindings instance for a given QuerydslBinderCustomizer type and domain type.
This basically involves creating or obtaining an instance of the customizer with the following algorithm:
1. If an explicit customizer type is given and no BeanFactory is configured, we'll simply instantiate the configured type. This allows simple customizer implementations with a no-arg constructor.
2. If a BeanFactory is configured and a customizer type configured, we're trying to locate a bean of that type in the BeanFactory, falling back to creating an instance of the customizer through the BeanFactory if no existing bean definition can be found. This allows unique customizer bean definitions or complex prototype scoped customizer beans created on the fly.
3. If no customizer type is configured, we check whether the the repository of the domain type implements QuerydslBinderCustomizer and use it if so.
The extraction of that functionality allows that algorithm being used by Spring Data REST, although only step 3 is currently used there as no explicit customizer can currently be configured with Spring Data REST.
We now default to a FormattingConversionService to make sure comma-separated values are transformed into arrays correctly. Also, we now build up dedicated TypeDescriptor instances for the property or field about to be bound to potentially pick up formatting annotations on those.
We now convert comma separated values for an array property by splitting values and converting each of them. This allows to convert address.location=40.740337,-73.995146 to
class Address {
Double[] location;
}
Introduced dedicated querydsl.bindings package to contain all non-web projects to make sure domain types and repositories don't have to depend on types in a web package.
Updated Sonargraph architecture description accordingly.
Original pull request: #132.
Javadoc on MultiValueBinding. Hide QuerydslBindings.bind(…), ….include(…) and ….exclude(…) methods that take String arguments to reduce the probability of no query class being present.
Refined the value handling for empty request values which are represented as String[] containing an empty String. We now massage those into an empty Collection for MultiValueBindings and a null value for SingleValueInvocations.
We currently skip property values that match this pattern entirely but are prepared to allow a configuration flip switch to handle those scenarios in the future. We currently stick to skipping those values to prevent the bindings from having to deal with null values.
We now also allow the bindings to return null to indicate they don't want to get applied in the resulting predicate at all.
Switched to interface based customization to make it easier to use customizations with Spring Data REST. Added Querydsl-specific adapter of RepositoryInvoker to allow Spring Data REST to hook in the execution of the predicate obtained from request parameters.
Original pull request: #132.
QuerydslBindings now uses a builder style pattern to define custom bindings. This allows to define the same binding for multiple properties of the same type in one configuration call.
Introduced MultiValueBinding to be able to register a binding for multiple source values (i.e. if multiple values are provided for the same parameter). The previously named QuerydslBinding is now a SingleValueBinding which gets adapted to by extracting the first element of the values provided considered as collection.
Slightly refined the generics signature in QuerydslBinding for better type derivation in Lambdas. Removed the need for QuerydslBindingContext by moving a few properties around. The ConversionService instance is now piped into the QuerydslPredicateBuilder directly.
Added a bit of sample data to the Users test domain type to be able to execute the generated Predicates in tests to validate their correctness.
Original pull request: #132.
Adding @QuerydslPredicate to a parameter within SpringMVC Controller when having registered the QueryDslPredicateArgumentResolver allows to generate a Querydsl Predicate based on the request parameters.
Parameters will be converted into their corresponding property types before using the as predicate value. Given more than one attribute will connect those using 'and'. Collections of values will force usage of 'in' while single values on collection like properties result in 'contains'.
The base type for building the Querydsl Path is extracted from the methods return type. In case of non domain type return values it can optionally be specified via @QueydslPredicate(root = …). Specific Predicate conversions can be registered via '@QuerydslSpecification'.
This allows to sneak in specific property path handlings more easily.
new QueryDslPredicateSpecification() {
{
define(new StringPath("address.city"), (path, value) -> path.like(value.toString()));
}
};
Renamed resolver, accessor etc. to express operation of binding properties to a resolved path and introduced explicit binding context which allows reuse of predicate builder within the ArgumentResolver.
Added registration of QuerydslPredicateArgumentResolver directly in SpringDataWebConfiguration reusing the provided ConversionService.
Added Javadoc and changed visibility of non public API and types.
Original pull request: #132.
Simplified implementation of Path conversion. Inlined helper domain types to not to pollute the packages with types that are only used within that very one test class.
Original pull request: #111.
Added basic infrastructure for repositories on top of key-value data stores. For more details see the original pull request.
Original pull request: #95.
Previously we only allowed to sort by QueryDsl path expressions. With this change we now also support ordering by operator expressions, e.g. yearMonth() on a date property.
Original pull request: #94.
Previously we did only support ordering by a string or property path through Sort. In order to be able to express more type safe ordering expressions we introduce QSort as a subclass of Sort that is able to wrap QueryDSL OrderSpecifiers. To be able to separate the concerns of sorting via QueryDSL expressions better we introduce the AbstractPageRequest base class and QPageRequest as a special implementation that accepts a QSort or OrderSpecifiers for ordering.
Original pull request: #59.