The new method allows to look up identifiers and immediately fail in the case of absence. Introduced the method as default method but also a new base type TargetAwareIdentifierAccessor to throw an exception with more context, i.e. the actual target bean we try to look up the identifier on.
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.
Preserve underscores in variable names (eg. String foo_bar) when resolving the actual type information for the property via PropertyPath by quoting (Pattern#quote) the property name.
We now consider property annotations as merged annotations when initially scanning for annotations in a property declaration. Composed annotations such as declared outside our code are captured correctly because they use an own type that is not queried by users of PersistentProperty. Own, revised annotations, using @AliasFor providing an alias for annotation values require merged annotation processing.
Previously, annotations were cached as-is without resolving @AliasFor. This caused a later lookup via findAnnotation(…) to return the cached annotation without aliasing. Because the annotation was cached, no further lookup via AnnotatedElementUtils.findMergedAnnotation(…) was attempted.
@Retention(RetentionPolicy.RUNTIME)
@Target(value = { FIELD, METHOD })
public @interface RevisedAnnnotationWithAliasFor {
@AliasFor("value")
String name() default "";
@AliasFor("name")
String value() default "";
}
public class Person {
@RevisedAnnnotationWithAliasFor(value = "spring")
String firstname;
}
PersistentProperty firstname = …
property.findAnnotation(…) returned previously @RevisedAnnnotationWithAliasFor(value = "spring", name = "")
now we return @RevisedAnnnotationWithAliasFor(value = "spring", name = "spring")
We now prefer an explicit Method.getParameterCount() over accessing the parameter types array and its length to avoid the overhead of cloning the array.
Original pull request: #187.
Previously a null value was added to the list of associations if it was handed to BasicaPersistentEntity.addAssociation(…). We now drop those null values and log a warning as it usually indicates a MappingContext implementation identifying a property as association but subsequently failing to look it up.
Previously, ClassGeneratingPropertyAccessorFactory uses boxed types for primitive type setters. This threw NoSuchMethodExceptions and caused ExceptionInInitializerError as the generated class could not be initialized. We now use the appropriate argument type to look up setters.
Also, we now only generate accessor usage if the property is configured to use property access in the first place.
Original pull request: #178.
We now explicitly report the given object's type and the one expected in case of a mismatch when BasicPersistentEntity.getPropertyAccessor(…) is invoked.
Simplified test case. Formatting in ClassGeneratingPropertyAccessorFactory.
Related tickets: DATACMNS-809.
Original pull request: #161.
Related pull request: #160.
Reproduce issue accessing persistent properties from interface-based entities using the ClassGeneratingPropertyAccessorFactory.
Related tickets: DATACMNS-809.
Original pull request: #161.
Related pull request: #160.
Removed DefaultPersistentPropertyAccessorFactory as it only delegates to the class generating one. Tweaked AbstractMappingContext to actually use the latter in the first place. Introduced BeanWrapperPropertyAccessorFactory to implement the default behavior of using a BeanWrapper and initialize BasicPersistentEntity to avoid a null clause in getPersistentPropertyAccessor(…).
Removed getPersistentPropertyAccessorFactory and rather rely on ReflectionTestUtils in tests to avoid additional API being exposed.
Original pull request: #159.
PersistentPropertyAccessorFactory can be set on a BasicPersistentEntity. This is done by AbstractMappingContext once the entity is verified. This change reduces the count of PersistentPropertyAccessorFactory instances and performs the isSupported check only once, when initializing the entity.
Original pull request: #159.
Made as many methods in ClassGeneratingPropertyAccessorFactory static as possible. Some code formatting. Some warning suppressions where needed.
Original pull request: #159.
We now support generated PersistentPropertyAccessors when using Java 7 and if property/association name hashCodes are unique within a PersistentEntity.
Generated PersistentPropertyAccessors provide optimized access to properties. They use either MethodHandles or direct property/field access, depending on the visibility/final modifiers of the entity type and its members. A generated PersistentPropertyAccessor is injected into the originating class loader of the entity class to enable optimizations for package-default/protected member access.
Original pull request: #159.
We now resolve composed annotation values using @AliasFor within AnnotationBasedPersistentProperty and BasicPersistentEntity. Nevertheless it is up to the individual store implementation to make use of this.
Original pull request: #156.
A failure to resolve a property path into a PersistentPropertyPath now causes an InvalidPropertyPath exception being thrown. It captures the context of the failure like the resolved path, the offending segment. Added getPersistentPropertyPath(InvalidPropertyPath) that resolves the resolvable part for further use downstream.
Added null-checking assertions to AbstractMappingContext.getPersistentPropertyPath(…) variants. Improved DefaultPersistentPropertyPath to be able to append properties while building and to allow representing an empty path.
We now use Spring's PropertyMatches to build up the exception message and include a list of potentially meant properties.
Removed unused config file for tests along the way.
Original pull request: #125.
When traversing nested property paths, AbstractMappingContext.getPersistentPropertyPath(…) previously used the raw actual property type. If the property path contains a reference to a generically typed property, this causes the deeper paths not being resolved correctly.
We now explicitly use the TypeInformation of the property to retain generics information while traversing the path.
AnnotationBasedPersistentProperty now also caches the absence of properties that are expressed through accessors only. Previously the absence of a field caused us to skip the registration of the absence in the cache.
Extend AuditableBeanWrapper to allow access to the last modification date of a target object. Made AuditableBeanWrapperFactory an interface and renamed what’s been previously known under this name as DefaultAuditableBeanWrapperFactory.
The components previously relying on a MappingContext to lookup a PersistentEntity now use PersistentEntities to be able to back a collection of MappingContexts behind that and also avoid unmanaged types to be added to the MappingContext.
We now also register the JSR-310 and ThreeTen back-port converters with the ConversionService to be able to get and set auditing dates as these types.
Made ObjectInstantiator interface public as otherwise the generated class to implement it cannot access it and thus the usage of the ByteCodeGeneratingEntityInstantiator fails completely.
PreferredConstructor.isEnclosingClassParameter(…) now eagerly returns if the parameter itself is not an enclosing one and thus avoids a collection lookup and equals check. Moved equals check for the type to the very end of the equals check to increase the chances that other inequality guards kick in earlier.
AbstractMappingContext now leaves the non-null-check for getPersistentEntity(…) to the factory method of ClassTypeInformation.
We now pre-calculate the hash codes for TypeInformation implementations as far as possible as the instances are used as cache keys quite a lot. The same applies to AbstractPersistentProperty.
BasicPersistentEntity now uses an ArrayList we sort during the verify() phase to mimic the previous behavior wich was implemented using a TreeSet as ArrayLists are way more performant when iterating over all elements which doWithProperties(…) is doing which is used quite a lot.
BeanWrapper now avoids the getter lookup if field access is used.
SimpleTypeHolder now uses a CopyOnWriteArrySet to leniently add types detected to be simple to the set of simple types to avoid ongoing checks against the inheritance hierarchy.
Added basic infrastructure for repositories on top of key-value data stores. For more details see the original pull request.
Original pull request: #95.
PersistentEntity now exposes an getIdentifierAccessor(…)-method that allows obtaining the identifier of an entity without using a PersistentProperty instance. This allows advanced scenarios (like multi-property identifiers). Also we can use store specific means to optimize id lookups to e.g. avoid proxy initialization for lazy loading proxies.
BasicpersistentEntity now allows subtypes to be handed into the PersistentPropertyAccessor lookup to support inheritance hierarchies as well as interface based PersistentEntity scenarios.
To be able to customize the lookup of bean properties by persistent store we now expose a getPropertyAccessor(Object entity) method on PersistentEntity. It returns a PersistentPropertyAccessor which is basically an interface with a simplified API of BeanWrapper.
Reduced the plain BeanWrapper to not perform any type conversion to be able to drop the ConversionService dependency. To compensate for that we introduced a ConvertingPropertyAccessor that takes a ConversionService and delegates to a standard PersistentPropertyAccessor and applies conversions if necessary.
Refactored client APIs to use the PersistentPropertyAccessor instead of referring to BeanWrapper directly. Deprecated BeanWrapper.create(…) for removal in RC1.
The type detection for entity candidates of PersistentProperty instances now consistently handles collection types even if they're used als collection or map values.
Annotations used on both fields and accessors are now only rejected if they're Spring Data annotations (i.e. from the org.springframework.data namespace) and the configurations of these annotations differ.
PropertyPath now exposes the complete property named the resolution failed for in case it can't resolve a source String. It will expose the part of the Path from the deepest successful resolution result.
Changed the resolution algorithm to use a List instead of a Stack and a fresh instance of the former so that the nested recursion steps keep track of the correct resolution depths.
This commit introduces @ReadOnlyProperty to mark properties as not to be persisted. That trait is exposed via the newly added PersistentProperty.isWritable() which supersedes shallBePersisted(). Currently all non-transient property that are not annotated with @ReadOnlyProperty are considered writable.
Original pull request: #88.
Changed the algorithm for nested PersistentEntity detection to only use PersistentProperty.getPersistentEntityTypes(…) and make sure we return unwrap Maps and Collections inside the method correctly.
Added a MappingAuditableBeanWrapperFactory to be able to use themapping metamodel to lookup annotations on persistent properties. This propagates into AuditingHandler and IsNewAwareAuditingHandler getting new constructors taking a MappingContext to set themselves up correctly. This will probably need store specific updates in the setup of the auditing infrastructure for namespace implementations and annotation based JavaConfig.
Introduced ….getPersistentProperty(Class<? extends Annotation> annotationType) on PersistentEntity to be able to access properties with a given annotation.
Updated SonarGraph architecture description and moved auditing related config classes into auditing.config package.
Introduced @AccessType annotation to allow user to control the way property values are accessed. The default is field access. Improved the property detection mechanism to also inspect all PropertyDescriptors not backed by a field and add them if property access is defined for the property or type. We also keep property accessors for interfaces as they strongly indicate property access to be used (as they cannot be field backed by definition).
The BeanWrapper doesn't take a useFieldAccess attribute anymore as the access type is solely derived from the given PersistentProperty now. AnnotationBasedPersistentProperty now also rejects properties with the very same annotation both on the field and on an accessor.
Removed the rejecting check for collections and maps and solely rely on the evaluation of the actual type for the ….isEntity() decision in AbstractPersistentProperty. This will cause collection and map properties also being inspected for persistent types as soon as the owner type gets added to the mapping context.
Previously we directly threw a MappingException in MappingContext.getPersistentEntity(TypeInformation) when the MappingContext was in strict mode and we were given a TypeInformation for which we didn't have a PersistentEntity already.
We now first check whether we should actually create a PersistentEntity for the given TypeInformation if no PersistentEntity is available, before throwing a MappingException - if we should not then we simply return null (e.g. for simple types like Integer or Double).
Original pull requests: #66, #71.