PersistentEntity now exposes an ….isNew(…) method that exposes the same detection algorithm previously exposed through MappingContextIsNewStrategyFactory (Persistable in favor of the version property in favor of an identifier lookup). MappingContextIsNewStrategyFactory has been refactored to return an ad-hoc strategy to delegate to the newly introduced method.
The core message to implementing modules is that they should now prefer PersistentEntityInformation within their RepositoryFactorySupport implementation and move all customizations made in the store-specific EntityInformation implementation in PersistentEntity.
We now expose what type or PersistentEntity an association points to by trying to match the association's type to identifier types to entities. In case multiple matches are found, we require the user to explicitly declare the target type via @Reference.
Introduced PersistentEntities.of(…) for convenience.
We now have a refined replica of the EvaluationContextProvider API and SPIs in the org.springframework.data.spel package. It has seen a bit of a Java 8 overhaul by removing the SPI support class in favor of turning most methods in EvaluationContextExtension into default ones.
The already existing API has been renamed to QueryMethodEvaluationContextProvider to indicate it's working with additional semantics specific to query methods (i.e. the Parameters metadata). The internals have been refactored to use the new API but still detect implementations of the old EvaluationContextExtension interface. The implementations get wrapped into an adapting proxy to satisfy the new API so that the actual inspection and usage of the extension is now already done using the new APIs.
The repository configuration has slightly change so that the creation of the EvaluationContextProvider is now taking place within RepositoryFactoryBeanSupport's implementation of BeanFactoryAware.
AbstractMappingContext is now ApplicationContextAware and holds an ExtensionAwareEvaluationContextProvider using the configured ApplicationContext. That EvaluationContextProvider is forwarded to all MutablePersistentEntity instances. BasicPersistentEntity now exposes getEvaluationContext(…) to subclasses to easily create an EvaluationContext using the extension aware infrastructure.
Removed DefaultEvaluationContextProvider in favor of a simple constant in QueryMethodEvaluationContextProvider.
Related tickets: DATACMNS-1258, DATACMNS-1108.
We now consider all types in the java.time package as simple types to prevent deep reflective access. We are already excluding java.lang types for the same reason.
Original pull request: #286.
MappingContext now exposes a method to detect all property paths pointing to properties matching a given predicate.
Extracted PersistentPropertyPath creation into a dedicated factory class so that it can be tested individually. DefaultPersistentPropertyPath now exposes a ….containsPropertyOfType(…) to detect whether we've already processed a particular type in the path. Also applied a bit of Java 8 and Lombok polish.
InvalidPersistentPropertyPath now collects suggested alternatives to create a better exception message. PersistentEntities now allows to map over a MappingContext and PersistentEntity that a given type is corresponding to. Streamable now exposes an ….isEmpty(). Removed references to equivalent methods implemented in subtypes.
We now explicitly check for an enum type in SimpleTypeHolder.isSimpleType(…) and resort to true immediately. Before that an enum implementing an interface could have seen a false for the actual enum type in case the interface type had been checked first and (correctly) produced a false. In the check for the actual enum type, depending on the iteration order through the cached values we could've hit the cached false for the interface or the cached true value for Enum.
Use ConcurrentHashMap in AnnotationBasedPersistentProperty for thread-safe annotation caching. Reintroduce eager cache check to prevent lambda instances on positive cache hits.
Previously, a call to AbstractMappingContext.getPersistentEntity(PersistentProperty) would've added potentially leniently added the type of the given PersistentProperty, no matter whether it's actually considered to be an entity in the first place. We now defensively check for whether the given property is to be considered an entity (taking potentially registered converters into account) before the potentially entity-creating by-type lookup.
More fixes of imports. Removed obsolete generics in constructor expressions. Removed a couple of compiler warnings in test cases. Removed assumption for test case to only run on JDK 9.
Original pull request: #259.
Make sure to use concurrent collection implementations for properties holding mutable state. Especially the ones making use of computeIfAbsent(…).
Usage of ConcurrentReferenceHashMap allows us to move on without additional changes as it allows to store null values, whereas ConcurrentHashMap would require us to store explicit NullValue placeholders for such cases, potentially causing trouble in downstream store specific projects.
JMH Benchmarks done with the Spring Data MongoDB mapping layer showed a potential performance loss of up to 5%. However a comparison between ConcurrentReferenceHashMap and ConcurrentHashMap did not show any significant difference in performance.
Original pull request: #259.
AbstractMappingContext.hasPersistentEntityFor(…) now also properly consideres the empty Optional as non-presence as that is held to allow to distinguish between a type completely unkown to the context, or already known but not considered a persistent entity.
Related pull request: #258.
In AbstractPersistentProperty, we now resolve the potentially generic return and parameter types of getters and setters. To achieve that Property has now been made aware of the actual owning type.
Throw MappingInstantiationException from KotlinClassGeneratingEntityInstantiator if instantiation fails to align behavior with ClassGeneratingEntityInstantiator. Report Kotlin constructor instead of Java constructor if available.
Original pull request: #255.
Previously, the publication of the event that indicated a PersistentEntity having been added to it took place before the write lock over the entities had been released. We now keep the lock smaller and publish the addition event *after* the lock has been released.
We now only inspect regular Kotlin classes with inspection to adapt Kotlin-specific behavior. Multipart-, synthetic and unknown classes are not supported. In such cases we fall back to the JVM reflection mechanism.
Non-regular classes are typically synthetic stubs, lambdas and SAM conversion which do not represent typical domain objects but rather technical bridge code.
Original pull request: #245.
We now fall back to default preferred constructor discovery if a Kotlin class has no primary constructor and no preferred constructor is resolved. Previously, primary constructor resolution yielded no result (returned null) which caused the subsequent Java constructor lookup to fail.
Original pull request: #244.
The new name currently delegates to old version, so classes only implementing the old method still work. Old name is deprecated.
Original pull request: #243.
Add Nullable annotation to ParsingUtils, Sort.Order and PropertyValueProvider.
Add getRequiredAnnotation(…) to PersistentEntity and PersistentProperty to provide methods returning required, non-null annotations.
Moved PreferredConstructorDiscoverers into PreferredConstructorDiscoverer to hide more API. Renamed ClassGeneratingKotlinEntityInstantiator to KotlinClassGeneratingEntityInstantiator.
Use org.springframework.util.Assert instead of com.mysema.commons.lang.Assert.
Original pull request: #233.
We now discover Kotlin constructors and apply parameter defaulting to allow construction of immutable value objects. Constructor discovery uses primary constructors by default and considers PersistenceConstructor annotations.
KotlinClassGeneratingEntityInstantiator can instantiate Kotlin classes with default parameters by resolving the synthetic constructor. Null values translate to parameter defaults.
class Person(val firstname: String = "Walter") {
}
class Address(val street: String, val city: String) {
@PersistenceConstructor
constructor(street: String = "Unknown", city: String = "Unknown", country: String) : this(street, city)
}
Original pull request: #233.
We're now favoring the generic TypeInformation over trying to resolve the property type via field or PropertyDescriptor as only the former does proper generic type resolution.
We now use CGLibs ReflectUtils.defineClass(…) to inject classes into the entity's class loader instead of our own code. ReflectUtils itself discovers whether the class loader is encapsulated and falls back to Unsafe for class definition. We no longer require our own code so the evil class was removed.
Original pull request: #234.
Marked all packages with Spring Frameworks @NonNullApi. Added Spring's @Nullable to methods, parameters and fields that take or produce null values. Adapted using code to make sure the IDE can evaluate the null flow properly. Fixed Javadoc in places where an invalid null handling policy was advertised. Strengthened null requirements for types that expose null-instances.
Removed null handling from converters for JodaTime and ThreeTenBP. Introduced factory methods Page.empty() and Page.empty(Pageable). Introduced default methods getRequiredGetter(), …Setter() and …Field() on PersistentProperty to allow non-nullable lookups of members. The same for TypeInformation.getrequiredActualType(), …SuperTypeInformation().
Tweaked PersistentPropertyCreator.addPropertiesForRemainingDescriptors() to filter unsuitable PropertyDescriptors before actually trying to create a Property instance from them as the new stronger nullability requirements would cause exceptions downstream.
Lazy.get() now expects a non-null return value. Clients being able to cope with null need to call ….orElse(…).
Original pull request: #232.
As the calculation of a PersistentPropertyPath instances is rather expensive and they're heavily used in downstream mapping operations (e.g. query and fields mapping in MongoDB) we now cache the instances created per base type and property path.
Deprecated the additional method in favor if a lookup via MappingContext.getPersistentPropertyPath(PropertyPath) using the resolvable PropertyPath exposed by InvalidPersistentPropertyPath.
Move MappingException from o.s.d.mapping.model to o.s.d.mapping package and use it for getRequired* methods in MappingContext instead of throwing IllegalArgumentException. Further on we’ve consolidated usage of IllegalArgumentException and IllegalStateException. Along that IllegalMappingException was removed in favor or MappingException.
BasicPersistentEntity now looks up all properties by annotation instead of just returning the first one found. We’ve kept the original methods behavior and updated the comment as well as introduced getPersistentProperties returning all matching properties.
Refactored type alias detection invocation in BasicPersistentEntity into separate method and avoid the factory method Alias.ofOptional(…) so that it can be removed.