|
@@ -30,15 +30,11 @@ import java.util.*;
|
|
|
* A helper class to keep the {@code XProperty}s of a class ordered by access type.
|
|
|
*
|
|
|
* @author Hardy Ferentschik
|
|
|
- *
|
|
|
+ * <p>
|
|
|
* 修改treeMap 为LinkedHashMap 使字段生成顺序与实体定义顺序一致
|
|
|
*/
|
|
|
@SuppressWarnings("unused")
|
|
|
class PropertyContainer {
|
|
|
-//
|
|
|
-// static {
|
|
|
-// System.setProperty("jboss.i18n.generate-proxies", "true");
|
|
|
-// }
|
|
|
|
|
|
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, org.hibernate.cfg.PropertyContainer.class.getName());
|
|
|
|
|
@@ -60,7 +56,7 @@ class PropertyContainer {
|
|
|
this.xClass = clazz;
|
|
|
this.entityAtStake = entityAtStake;
|
|
|
|
|
|
- if ( defaultClassLevelAccessType == org.hibernate.cfg.AccessType.DEFAULT ) {
|
|
|
+ if (defaultClassLevelAccessType == org.hibernate.cfg.AccessType.DEFAULT) {
|
|
|
// this is effectively what the old code did when AccessType.DEFAULT was passed in
|
|
|
// to getProperties(AccessType) from AnnotationBinder and InheritanceState
|
|
|
defaultClassLevelAccessType = org.hibernate.cfg.AccessType.PROPERTY;
|
|
@@ -76,13 +72,13 @@ class PropertyContainer {
|
|
|
|
|
|
this.persistentAttributeMap = new LinkedHashMap<>();
|
|
|
|
|
|
- final List<XProperty> fields = xClass.getDeclaredProperties( org.hibernate.cfg.AccessType.FIELD.getType() );
|
|
|
+ final List<XProperty> fields = xClass.getDeclaredProperties(org.hibernate.cfg.AccessType.FIELD.getType());
|
|
|
|
|
|
- final List<XProperty> getters = xClass.getDeclaredProperties( org.hibernate.cfg.AccessType.PROPERTY.getType() );
|
|
|
+ final List<XProperty> getters = xClass.getDeclaredProperties(org.hibernate.cfg.AccessType.PROPERTY.getType());
|
|
|
|
|
|
- preFilter( fields, getters );
|
|
|
+ preFilter(fields, getters);
|
|
|
|
|
|
- final Map<String,XProperty> persistentAttributesFromGetters = new HashMap<>();
|
|
|
+ final Map<String, XProperty> persistentAttributesFromGetters = new HashMap<>();
|
|
|
|
|
|
collectPersistentAttributesUsingLocalAccessType(
|
|
|
persistentAttributeMap,
|
|
@@ -100,17 +96,17 @@ class PropertyContainer {
|
|
|
|
|
|
private void preFilter(List<XProperty> fields, List<XProperty> getters) {
|
|
|
Iterator<XProperty> propertyIterator = fields.iterator();
|
|
|
- while ( propertyIterator.hasNext() ) {
|
|
|
+ while (propertyIterator.hasNext()) {
|
|
|
final XProperty property = propertyIterator.next();
|
|
|
- if ( mustBeSkipped( property ) ) {
|
|
|
+ if (mustBeSkipped(property)) {
|
|
|
propertyIterator.remove();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
propertyIterator = getters.iterator();
|
|
|
- while ( propertyIterator.hasNext() ) {
|
|
|
+ while (propertyIterator.hasNext()) {
|
|
|
final XProperty property = propertyIterator.next();
|
|
|
- if ( mustBeSkipped( property ) ) {
|
|
|
+ if (mustBeSkipped(property)) {
|
|
|
propertyIterator.remove();
|
|
|
}
|
|
|
}
|
|
@@ -118,31 +114,31 @@ class PropertyContainer {
|
|
|
|
|
|
private void collectPersistentAttributesUsingLocalAccessType(
|
|
|
LinkedHashMap<String, XProperty> persistentAttributeMap,
|
|
|
- Map<String,XProperty> persistentAttributesFromGetters,
|
|
|
+ Map<String, XProperty> persistentAttributesFromGetters,
|
|
|
List<XProperty> fields,
|
|
|
List<XProperty> getters) {
|
|
|
|
|
|
// Check fields...
|
|
|
Iterator<XProperty> propertyIterator = fields.iterator();
|
|
|
- while ( propertyIterator.hasNext() ) {
|
|
|
+ while (propertyIterator.hasNext()) {
|
|
|
final XProperty xProperty = propertyIterator.next();
|
|
|
- final Access localAccessAnnotation = xProperty.getAnnotation( Access.class );
|
|
|
- if ( localAccessAnnotation == null
|
|
|
- || localAccessAnnotation.value() != javax.persistence.AccessType.FIELD ) {
|
|
|
+ final Access localAccessAnnotation = xProperty.getAnnotation(Access.class);
|
|
|
+ if (localAccessAnnotation == null
|
|
|
+ || localAccessAnnotation.value() != javax.persistence.AccessType.FIELD) {
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
propertyIterator.remove();
|
|
|
- persistentAttributeMap.put( xProperty.getName(), xProperty );
|
|
|
+ persistentAttributeMap.put(xProperty.getName(), xProperty);
|
|
|
}
|
|
|
|
|
|
// Check getters...
|
|
|
propertyIterator = getters.iterator();
|
|
|
- while ( propertyIterator.hasNext() ) {
|
|
|
+ while (propertyIterator.hasNext()) {
|
|
|
final XProperty xProperty = propertyIterator.next();
|
|
|
- final Access localAccessAnnotation = xProperty.getAnnotation( Access.class );
|
|
|
- if ( localAccessAnnotation == null
|
|
|
- || localAccessAnnotation.value() != javax.persistence.AccessType.PROPERTY ) {
|
|
|
+ final Access localAccessAnnotation = xProperty.getAnnotation(Access.class);
|
|
|
+ if (localAccessAnnotation == null
|
|
|
+ || localAccessAnnotation.value() != javax.persistence.AccessType.PROPERTY) {
|
|
|
continue;
|
|
|
}
|
|
|
|
|
@@ -151,60 +147,59 @@ class PropertyContainer {
|
|
|
final String name = xProperty.getName();
|
|
|
|
|
|
// HHH-10242 detect registration of the same property getter twice - eg boolean isId() + UUID getId()
|
|
|
- final XProperty previous = persistentAttributesFromGetters.get( name );
|
|
|
- if ( previous != null ) {
|
|
|
+ final XProperty previous = persistentAttributesFromGetters.get(name);
|
|
|
+ if (previous != null) {
|
|
|
throw new org.hibernate.boot.MappingException(
|
|
|
LOG.ambiguousPropertyMethods(
|
|
|
xClass.getName(),
|
|
|
- HCANNHelper.annotatedElementSignature( previous ),
|
|
|
- HCANNHelper.annotatedElementSignature( xProperty )
|
|
|
+ HCANNHelper.annotatedElementSignature(previous),
|
|
|
+ HCANNHelper.annotatedElementSignature(xProperty)
|
|
|
),
|
|
|
- new Origin( SourceType.ANNOTATION, xClass.getName() )
|
|
|
+ new Origin(SourceType.ANNOTATION, xClass.getName())
|
|
|
);
|
|
|
}
|
|
|
|
|
|
- persistentAttributeMap.put( name, xProperty );
|
|
|
- persistentAttributesFromGetters.put( name, xProperty );
|
|
|
+ persistentAttributeMap.put(name, xProperty);
|
|
|
+ persistentAttributesFromGetters.put(name, xProperty);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private void collectPersistentAttributesUsingClassLevelAccessType(
|
|
|
LinkedHashMap<String, XProperty> persistentAttributeMap,
|
|
|
- Map<String,XProperty> persistentAttributesFromGetters,
|
|
|
+ Map<String, XProperty> persistentAttributesFromGetters,
|
|
|
List<XProperty> fields,
|
|
|
List<XProperty> getters) {
|
|
|
- if ( classLevelAccessType == org.hibernate.cfg.AccessType.FIELD ) {
|
|
|
- for ( XProperty field : fields ) {
|
|
|
- if ( persistentAttributeMap.containsKey( field.getName() ) ) {
|
|
|
+ if (classLevelAccessType == org.hibernate.cfg.AccessType.FIELD) {
|
|
|
+ for (XProperty field : fields) {
|
|
|
+ if (persistentAttributeMap.containsKey(field.getName())) {
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
- persistentAttributeMap.put( field.getName(), field );
|
|
|
+ persistentAttributeMap.put(field.getName(), field);
|
|
|
}
|
|
|
- }
|
|
|
- else {
|
|
|
- for ( XProperty getter : getters ) {
|
|
|
+ } else {
|
|
|
+ for (XProperty getter : getters) {
|
|
|
final String name = getter.getName();
|
|
|
|
|
|
// HHH-10242 detect registration of the same property getter twice - eg boolean isId() + UUID getId()
|
|
|
- final XProperty previous = persistentAttributesFromGetters.get( name );
|
|
|
- if ( previous != null ) {
|
|
|
+ final XProperty previous = persistentAttributesFromGetters.get(name);
|
|
|
+ if (previous != null) {
|
|
|
throw new org.hibernate.boot.MappingException(
|
|
|
LOG.ambiguousPropertyMethods(
|
|
|
xClass.getName(),
|
|
|
- HCANNHelper.annotatedElementSignature( previous ),
|
|
|
- HCANNHelper.annotatedElementSignature( getter )
|
|
|
+ HCANNHelper.annotatedElementSignature(previous),
|
|
|
+ HCANNHelper.annotatedElementSignature(getter)
|
|
|
),
|
|
|
- new Origin( SourceType.ANNOTATION, xClass.getName() )
|
|
|
+ new Origin(SourceType.ANNOTATION, xClass.getName())
|
|
|
);
|
|
|
}
|
|
|
|
|
|
- if ( persistentAttributeMap.containsKey( name ) ) {
|
|
|
+ if (persistentAttributeMap.containsKey(name)) {
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
- persistentAttributeMap.put( getter.getName(), getter );
|
|
|
- persistentAttributesFromGetters.put( name, getter );
|
|
|
+ persistentAttributeMap.put(getter.getName(), getter);
|
|
|
+ persistentAttributesFromGetters.put(name, getter);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -223,96 +218,19 @@ class PropertyContainer {
|
|
|
|
|
|
public Collection<XProperty> getProperties() {
|
|
|
assertTypesAreResolvable();
|
|
|
- return Collections.unmodifiableCollection( persistentAttributeMap.values() );
|
|
|
+ return Collections.unmodifiableCollection(persistentAttributeMap.values());
|
|
|
}
|
|
|
|
|
|
private void assertTypesAreResolvable() {
|
|
|
- for ( XProperty xProperty : persistentAttributeMap.values() ) {
|
|
|
- if ( !xProperty.isTypeResolved() && !discoverTypeWithoutReflection( xProperty ) ) {
|
|
|
- String msg = "Property " + StringHelper.qualify( xClass.getName(), xProperty.getName() ) +
|
|
|
+ for (XProperty xProperty : persistentAttributeMap.values()) {
|
|
|
+ if (!xProperty.isTypeResolved() && !discoverTypeWithoutReflection(xProperty)) {
|
|
|
+ String msg = "Property " + StringHelper.qualify(xClass.getName(), xProperty.getName()) +
|
|
|
" has an unbound type and no explicit target entity. Resolve this Generic usage issue" +
|
|
|
" or set an explicit target attribute (eg @OneToMany(target=) or use an explicit @Type";
|
|
|
- throw new AnnotationException( msg );
|
|
|
+ throw new AnnotationException(msg);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-//
|
|
|
-// private void considerExplicitFieldAndPropertyAccess() {
|
|
|
-// for ( XProperty property : fieldAccessMap.values() ) {
|
|
|
-// Access access = property.getAnnotation( Access.class );
|
|
|
-// if ( access == null ) {
|
|
|
-// continue;
|
|
|
-// }
|
|
|
-//
|
|
|
-// // see "2.3.2 Explicit Access Type" of JPA 2 spec
|
|
|
-// // the access type for this property is explicitly set to AccessType.FIELD, hence we have to
|
|
|
-// // use field access for this property even if the default access type for the class is AccessType.PROPERTY
|
|
|
-// AccessType accessType = AccessType.getAccessStrategy( access.value() );
|
|
|
-// if (accessType == AccessType.FIELD) {
|
|
|
-// propertyAccessMap.put(property.getName(), property);
|
|
|
-// }
|
|
|
-// else {
|
|
|
-// LOG.debug( "Placing @Access(AccessType.FIELD) on a field does not have any effect." );
|
|
|
-// }
|
|
|
-// }
|
|
|
-//
|
|
|
-// for ( XProperty property : propertyAccessMap.values() ) {
|
|
|
-// Access access = property.getAnnotation( Access.class );
|
|
|
-// if ( access == null ) {
|
|
|
-// continue;
|
|
|
-// }
|
|
|
-//
|
|
|
-// AccessType accessType = AccessType.getAccessStrategy( access.value() );
|
|
|
-//
|
|
|
-// // see "2.3.2 Explicit Access Type" of JPA 2 spec
|
|
|
-// // the access type for this property is explicitly set to AccessType.PROPERTY, hence we have to
|
|
|
-// // return use method access even if the default class access type is AccessType.FIELD
|
|
|
-// if (accessType == AccessType.PROPERTY) {
|
|
|
-// fieldAccessMap.put(property.getName(), property);
|
|
|
-// }
|
|
|
-// else {
|
|
|
-// LOG.debug( "Placing @Access(AccessType.PROPERTY) on a field does not have any effect." );
|
|
|
-// }
|
|
|
-// }
|
|
|
-// }
|
|
|
-
|
|
|
-// /**
|
|
|
-// * Retrieves all properties from the {@code xClass} with the specified access type. This method does not take
|
|
|
-// * any jpa access rules/annotations into account yet.
|
|
|
-// *
|
|
|
-// * @param access The access type - {@code AccessType.FIELD} or {@code AccessType.Property}
|
|
|
-// *
|
|
|
-// * @return A maps of the properties with the given access type keyed against their property name
|
|
|
-// */
|
|
|
-// private TreeMap<String, XProperty> initProperties(AccessType access) {
|
|
|
-// if ( !( AccessType.PROPERTY.equals( access ) || AccessType.FIELD.equals( access ) ) ) {
|
|
|
-// throw new IllegalArgumentException( "Access type has to be AccessType.FIELD or AccessType.Property" );
|
|
|
-// }
|
|
|
-//
|
|
|
-// //order so that property are used in the same order when binding native query
|
|
|
-// TreeMap<String, XProperty> propertiesMap = new TreeMap<String, XProperty>();
|
|
|
-// List<XProperty> properties = xClass.getDeclaredProperties( access.getType() );
|
|
|
-// for ( XProperty property : properties ) {
|
|
|
-// if ( mustBeSkipped( property ) ) {
|
|
|
-// continue;
|
|
|
-// }
|
|
|
-// // HHH-10242 detect registration of the same property twice eg boolean isId() + UUID getId()
|
|
|
-// XProperty oldProperty = propertiesMap.get( property.getName() );
|
|
|
-// if ( oldProperty != null ) {
|
|
|
-// throw new org.hibernate.boot.MappingException(
|
|
|
-// LOG.ambiguousPropertyMethods(
|
|
|
-// xClass.getName(),
|
|
|
-// HCANNHelper.annotatedElementSignature( oldProperty ),
|
|
|
-// HCANNHelper.annotatedElementSignature( property )
|
|
|
-// ),
|
|
|
-// new Origin( SourceType.ANNOTATION, xClass.getName() )
|
|
|
-// );
|
|
|
-// }
|
|
|
-//
|
|
|
-// propertiesMap.put( property.getName(), property );
|
|
|
-// }
|
|
|
-// return propertiesMap;
|
|
|
-// }
|
|
|
|
|
|
@SuppressWarnings("deprecation")
|
|
|
private org.hibernate.cfg.AccessType determineLocalClassDefinedAccessStrategy() {
|
|
@@ -321,75 +239,64 @@ class PropertyContainer {
|
|
|
org.hibernate.cfg.AccessType hibernateDefinedAccessType = org.hibernate.cfg.AccessType.DEFAULT;
|
|
|
org.hibernate.cfg.AccessType jpaDefinedAccessType = org.hibernate.cfg.AccessType.DEFAULT;
|
|
|
|
|
|
- org.hibernate.annotations.AccessType accessType = xClass.getAnnotation( org.hibernate.annotations.AccessType.class );
|
|
|
- if ( accessType != null ) {
|
|
|
- hibernateDefinedAccessType = org.hibernate.cfg.AccessType.getAccessStrategy( accessType.value() );
|
|
|
+ org.hibernate.annotations.AccessType accessType = xClass.getAnnotation(org.hibernate.annotations.AccessType.class);
|
|
|
+ if (accessType != null) {
|
|
|
+ hibernateDefinedAccessType = org.hibernate.cfg.AccessType.getAccessStrategy(accessType.value());
|
|
|
}
|
|
|
|
|
|
- Access access = xClass.getAnnotation( Access.class );
|
|
|
- if ( access != null ) {
|
|
|
- jpaDefinedAccessType = org.hibernate.cfg.AccessType.getAccessStrategy( access.value() );
|
|
|
+ Access access = xClass.getAnnotation(Access.class);
|
|
|
+ if (access != null) {
|
|
|
+ jpaDefinedAccessType = org.hibernate.cfg.AccessType.getAccessStrategy(access.value());
|
|
|
}
|
|
|
|
|
|
- if ( hibernateDefinedAccessType != org.hibernate.cfg.AccessType.DEFAULT
|
|
|
+ if (hibernateDefinedAccessType != org.hibernate.cfg.AccessType.DEFAULT
|
|
|
&& jpaDefinedAccessType != org.hibernate.cfg.AccessType.DEFAULT
|
|
|
- && hibernateDefinedAccessType != jpaDefinedAccessType ) {
|
|
|
+ && hibernateDefinedAccessType != jpaDefinedAccessType) {
|
|
|
throw new MappingException(
|
|
|
"@AccessType and @Access specified with contradicting values. Use of @Access only is recommended. "
|
|
|
);
|
|
|
}
|
|
|
|
|
|
- if ( hibernateDefinedAccessType != org.hibernate.cfg.AccessType.DEFAULT ) {
|
|
|
+ if (hibernateDefinedAccessType != org.hibernate.cfg.AccessType.DEFAULT) {
|
|
|
classDefinedAccessType = hibernateDefinedAccessType;
|
|
|
- }
|
|
|
- else {
|
|
|
+ } else {
|
|
|
classDefinedAccessType = jpaDefinedAccessType;
|
|
|
}
|
|
|
return classDefinedAccessType;
|
|
|
}
|
|
|
|
|
|
private static boolean discoverTypeWithoutReflection(XProperty p) {
|
|
|
- if ( p.isAnnotationPresent( OneToOne.class ) && !p.getAnnotation( OneToOne.class )
|
|
|
+ if (p.isAnnotationPresent(OneToOne.class) && !p.getAnnotation(OneToOne.class)
|
|
|
.targetEntity()
|
|
|
- .equals( void.class ) ) {
|
|
|
+ .equals(void.class)) {
|
|
|
return true;
|
|
|
- }
|
|
|
- else if ( p.isAnnotationPresent( OneToMany.class ) && !p.getAnnotation( OneToMany.class )
|
|
|
+ } else if (p.isAnnotationPresent(OneToMany.class) && !p.getAnnotation(OneToMany.class)
|
|
|
.targetEntity()
|
|
|
- .equals( void.class ) ) {
|
|
|
+ .equals(void.class)) {
|
|
|
return true;
|
|
|
- }
|
|
|
- else if ( p.isAnnotationPresent( ManyToOne.class ) && !p.getAnnotation( ManyToOne.class )
|
|
|
+ } else if (p.isAnnotationPresent(ManyToOne.class) && !p.getAnnotation(ManyToOne.class)
|
|
|
.targetEntity()
|
|
|
- .equals( void.class ) ) {
|
|
|
+ .equals(void.class)) {
|
|
|
return true;
|
|
|
- }
|
|
|
- else if ( p.isAnnotationPresent( ManyToMany.class ) && !p.getAnnotation( ManyToMany.class )
|
|
|
+ } else if (p.isAnnotationPresent(ManyToMany.class) && !p.getAnnotation(ManyToMany.class)
|
|
|
.targetEntity()
|
|
|
- .equals( void.class ) ) {
|
|
|
+ .equals(void.class)) {
|
|
|
return true;
|
|
|
- }
|
|
|
- else if ( p.isAnnotationPresent( org.hibernate.annotations.Any.class ) ) {
|
|
|
+ } else if (p.isAnnotationPresent(org.hibernate.annotations.Any.class)) {
|
|
|
return true;
|
|
|
- }
|
|
|
- else if ( p.isAnnotationPresent( ManyToAny.class ) ) {
|
|
|
- if ( !p.isCollection() && !p.isArray() ) {
|
|
|
- throw new AnnotationException( "@ManyToAny used on a non collection non array property: " + p.getName() );
|
|
|
+ } else if (p.isAnnotationPresent(ManyToAny.class)) {
|
|
|
+ if (!p.isCollection() && !p.isArray()) {
|
|
|
+ throw new AnnotationException("@ManyToAny used on a non collection non array property: " + p.getName());
|
|
|
}
|
|
|
return true;
|
|
|
- }
|
|
|
- else if ( p.isAnnotationPresent( Type.class ) ) {
|
|
|
- return true;
|
|
|
- }
|
|
|
- else if ( p.isAnnotationPresent( Target.class ) ) {
|
|
|
+ } else if (p.isAnnotationPresent(Type.class)) {
|
|
|
return true;
|
|
|
- }
|
|
|
- return false;
|
|
|
+ } else return p.isAnnotationPresent(Target.class);
|
|
|
}
|
|
|
|
|
|
private static boolean mustBeSkipped(XProperty property) {
|
|
|
- return property.isAnnotationPresent( Transient.class )
|
|
|
- || "net.sf.cglib.transform.impl.InterceptFieldCallback".equals( property.getType().getName() )
|
|
|
- || "org.hibernate.bytecode.internal.javassist.FieldHandler".equals( property.getType().getName() );
|
|
|
+ return property.isAnnotationPresent(Transient.class)
|
|
|
+ || "net.sf.cglib.transform.impl.InterceptFieldCallback".equals(property.getType().getName())
|
|
|
+ || "org.hibernate.bytecode.internal.javassist.FieldHandler".equals(property.getType().getName());
|
|
|
}
|
|
|
}
|