diff --git a/hibernate-core/src/main/java/org/hibernate/internal/CoreMessageLogger.java b/hibernate-core/src/main/java/org/hibernate/internal/CoreMessageLogger.java index 27ee100055..56b451b0f2 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/CoreMessageLogger.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/CoreMessageLogger.java @@ -1570,7 +1570,7 @@ public interface CoreMessageLogger extends BasicLogger { @LogMessage(level = INFO) @Message(value = "Max NaturalId query time: %sms", id = 441) void naturalIdMaxQueryTime(long naturalIdQueryExecutionMaxTime); - + @LogMessage(level = INFO) @Message(value = "NaturalId queries executed to database: %s", id = 442) void naturalIdQueriesExecuted(long naturalIdQueriesExecutionCount); @@ -1596,18 +1596,33 @@ public interface CoreMessageLogger extends BasicLogger { ) void tooManyInExpressions(String dialectName, int limit, String paramName, int size); - - // moved from hibernate-entitymanager ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - @LogMessage( level = ERROR ) - @Message( value = "Illegal argument on static metamodel field injection : %s#%s; expected type : %s; encountered type : %s", id = 15007 ) + @Message( value = "Illegal argument on static metamodel field injection : %s#%s; expected type : %s; encountered type : %s", id = 448 ) void illegalArgumentOnStaticMetamodelFieldInjection( String metamodelClassName, String attributeName, String attributeJavaType, String metamodelFieldJavaType ); @LogMessage( level = ERROR ) - @Message( value = "Unable to locate static metamodel field : %s#%s", id = 15011 ) + @Message( value = "Unable to locate static metamodel field : %s#%s", id = 449 ) void unableToLocateStaticMetamodelField( String metamodelClassName, String attributeName ); + + @Message(value = "The access type of class %s is AccessType.FIELD. To override the access for an attribute " + + "@Access has to be placed on the property (getter)", id = 450) + String accessTypeOverrideShouldBeAnnotatedOnProperty( String className ); + + @Message(value = "The access type of class %s is AccessType.FIELD. To override the access for an attribute " + + "@Access has to be placed on the property (getter) with an access type of AccessType.PROPERTY. " + + "Using AccessType.FIELD on the property has no effect", id = 451) + String accessTypeOverrideShouldBeProperty( String className ); + + @Message(value = "The access type of class %s is AccessType.PROPERTY. To override the access for a field " + + "@Access has to be placed on the field ", id = 452) + String accessTypeOverrideShouldBeAnnotatedOnField( String className ); + + @Message(value = "The access type of class %s is AccessType.PROPERTY. To override the access for a field " + + "@Access has to be placed on the field with an access type of AccessType.FIELD. " + + "Using AccessType.PROPERTY on the field has no effect", id = 453) + String accessTypeOverrideShouldBeField( String className ); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/ConfiguredClass.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/ConfiguredClass.java index 2dfcf91999..33f1a847a0 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/ConfiguredClass.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/ConfiguredClass.java @@ -27,7 +27,6 @@ import java.lang.reflect.Field; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.EnumMap; @@ -37,23 +36,14 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; -import javax.persistence.AccessType; -import com.fasterxml.classmate.ResolvedTypeWithMembers; -import com.fasterxml.classmate.members.HierarchicType; -import com.fasterxml.classmate.members.ResolvedMember; -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationTarget; -import org.jboss.jandex.ClassInfo; -import org.jboss.jandex.DotName; -import org.jboss.jandex.FieldInfo; -import org.jboss.jandex.MethodInfo; -import org.jboss.logging.Logger; +import javax.persistence.AccessType; import org.hibernate.AnnotationException; import org.hibernate.AssertionFailure; import org.hibernate.EntityMode; import org.hibernate.HibernateException; +import org.hibernate.internal.CoreMessageLogger; import org.hibernate.metamodel.internal.source.annotations.AnnotationBindingContext; import org.hibernate.metamodel.internal.source.annotations.attribute.AssociationAttribute; import org.hibernate.metamodel.internal.source.annotations.attribute.AttributeOverride; @@ -66,6 +56,17 @@ import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper; import org.hibernate.metamodel.internal.source.annotations.util.ReflectionHelper; import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; import org.hibernate.metamodel.spi.source.MappingException; +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationTarget; +import org.jboss.jandex.ClassInfo; +import org.jboss.jandex.DotName; +import org.jboss.jandex.FieldInfo; +import org.jboss.jandex.MethodInfo; +import org.jboss.logging.Logger; + +import com.fasterxml.classmate.ResolvedTypeWithMembers; +import com.fasterxml.classmate.members.HierarchicType; +import com.fasterxml.classmate.members.ResolvedMember; /** * Base class for a configured entity, mapped super class or embeddable @@ -73,7 +74,7 @@ import org.hibernate.metamodel.spi.source.MappingException; * @author Hardy Ferentschik */ public class ConfiguredClass { - public static final Logger LOG = Logger.getLogger( ConfiguredClass.class.getName() ); + private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, AssertionFailure.class.getName()); /** * The parent of this configured class or {@code null} in case this configured class is the root of a hierarchy. @@ -233,8 +234,13 @@ public class ConfiguredClass { AccessType accessType = defaultAccessType; AnnotationInstance accessAnnotation = JandexHelper.getSingleAnnotation( classInfo, JPADotNames.ACCESS, ClassInfo.class ); - if ( accessAnnotation != null && accessAnnotation.target().getClass().equals( ClassInfo.class ) ) { + if ( accessAnnotation != null ) { accessType = JandexHelper.getEnumValue( accessAnnotation, "value", AccessType.class ); + } else { + accessAnnotation = JandexHelper.getSingleAnnotation( classInfo, HibernateDotNames.ACCESS_TYPE, ClassInfo.class ); + if ( accessAnnotation != null ) { + accessType = AccessType.valueOf( accessAnnotation.value().asString().toUpperCase() ); + } } return accessType; @@ -321,8 +327,14 @@ public class ConfiguredClass { Set explicitAccessPropertyNames = new HashSet(); List accessAnnotations = classInfo.annotations().get( JPADotNames.ACCESS ); + List hibernateAccessAnnotations = classInfo.annotations().get( HibernateDotNames.ACCESS_TYPE ); if ( accessAnnotations == null ) { - return explicitAccessPropertyNames; + accessAnnotations = hibernateAccessAnnotations; + if ( accessAnnotations == null ) { + return explicitAccessPropertyNames; + } + } else if ( hibernateAccessAnnotations != null ) { + accessAnnotations.addAll( hibernateAccessAnnotations ); } // iterate over all @Access annotations defined on the current class @@ -334,18 +346,19 @@ public class ConfiguredClass { continue; } - AccessType accessType = JandexHelper.getEnumValue( accessAnnotation, "value", AccessType.class ); - - if ( !isExplicitAttributeAccessAnnotationPlacedCorrectly( annotationTarget, accessType ) ) { - continue; + AccessType accessType; + if ( JPADotNames.ACCESS.equals( accessAnnotation.name() ) ) { + accessType = JandexHelper.getEnumValue( accessAnnotation, "value", AccessType.class ); + checkExplicitJpaAttributeAccessAnnotationPlacedCorrectly( annotationTarget, accessType ); + } else { + accessType = AccessType.valueOf( accessAnnotation.value().asString().toUpperCase() ); } // the placement is correct, get the member Member member; if ( annotationTarget instanceof MethodInfo ) { - Method m; try { - m = clazz.getMethod( ( ( MethodInfo ) annotationTarget ).name() ); + member = clazz.getMethod( ( ( MethodInfo ) annotationTarget ).name() ); } catch ( NoSuchMethodException e ) { throw new HibernateException( @@ -354,13 +367,10 @@ public class ConfiguredClass { + " of class " + clazz.getName() ); } - member = m; - accessType = AccessType.PROPERTY; } else { - Field f; try { - f = clazz.getField( ( ( FieldInfo ) annotationTarget ).name() ); + member = clazz.getField( ( ( FieldInfo ) annotationTarget ).name() ); } catch ( NoSuchFieldException e ) { throw new HibernateException( @@ -369,8 +379,6 @@ public class ConfiguredClass { + " of class " + clazz.getName() ); } - member = f; - accessType = AccessType.FIELD; } if ( ReflectionHelper.isProperty( member ) ) { createMappedAttribute( member, resolvedMembers, accessType ); @@ -380,26 +388,20 @@ public class ConfiguredClass { return explicitAccessPropertyNames; } - private boolean isExplicitAttributeAccessAnnotationPlacedCorrectly(AnnotationTarget annotationTarget, AccessType accessType) { + private void checkExplicitJpaAttributeAccessAnnotationPlacedCorrectly(AnnotationTarget annotationTarget, AccessType accessType) { // when the access type of the class is FIELD // overriding access annotations must be placed on properties AND have the access type PROPERTY if ( AccessType.FIELD.equals( classAccessType ) ) { if ( !MethodInfo.class.isInstance( annotationTarget ) ) { - LOG.tracef( - "The access type of class %s is AccessType.FIELD. To override the access for an attribute " + - "@Access has to be placed on the property (getter)", classInfo.name().toString() - ); - return false; + String msg = LOG.accessTypeOverrideShouldBeAnnotatedOnProperty( classInfo.name().toString() ); + LOG.trace( msg ); + throw new AnnotationException( msg ); } if ( !AccessType.PROPERTY.equals( accessType ) ) { - LOG.tracef( - "The access type of class %s is AccessType.FIELD. To override the access for an attribute " + - "@Access has to be placed on the property (getter) with an access type of AccessType.PROPERTY. " + - "Using AccessType.FIELD on the property has no effect", - classInfo.name().toString() - ); - return false; + String msg = LOG.accessTypeOverrideShouldBeProperty( classInfo.name().toString() ); + LOG.trace( msg ); + throw new AnnotationException( msg ); } } @@ -407,24 +409,17 @@ public class ConfiguredClass { // overriding access annotations must be placed on fields and have the access type FIELD if ( AccessType.PROPERTY.equals( classAccessType ) ) { if ( !FieldInfo.class.isInstance( annotationTarget ) ) { - LOG.tracef( - "The access type of class %s is AccessType.PROPERTY. To override the access for a field " + - "@Access has to be placed on the field ", classInfo.name().toString() - ); - return false; + String msg = LOG.accessTypeOverrideShouldBeAnnotatedOnField( classInfo.name().toString() ); + LOG.trace( msg ); + throw new AnnotationException( msg ); } if ( !AccessType.FIELD.equals( accessType ) ) { - LOG.tracef( - "The access type of class %s is AccessType.PROPERTY. To override the access for a field " + - "@Access has to be placed on the field with an access type of AccessType.FIELD. " + - "Using AccessType.PROPERTY on the field has no effect", - classInfo.name().toString() - ); - return false; + String msg = LOG.accessTypeOverrideShouldBeField( classInfo.name().toString() ); + LOG.trace( msg ); + throw new AnnotationException( msg ); } } - return true; } private void createMappedAttribute(Member member, ResolvedTypeWithMembers resolvedType, AccessType accessType) { @@ -476,6 +471,7 @@ public class ConfiguredClass { ); idAttributeMap.put( attributeName, attribute ); } + //$FALL-THROUGH$ case EMBEDDED: { final AnnotationInstance targetAnnotation = JandexHelper.getSingleAnnotation( getClassInfo(), @@ -520,7 +516,7 @@ public class ConfiguredClass { associationAttributeMap.put( attributeName, attribute ); break; } - + case MANY_TO_ANY: {} } } @@ -722,29 +718,6 @@ public class ConfiguredClass { return prefix; } - private List findAssociationOverrides() { - List associationOverrideList = new ArrayList(); - - AnnotationInstance associationOverrideAnnotation = JandexHelper.getSingleAnnotation( - classInfo, - JPADotNames.ASSOCIATION_OVERRIDE - ); - if ( associationOverrideAnnotation != null ) { - associationOverrideList.add( associationOverrideAnnotation ); - } - - AnnotationInstance associationOverridesAnnotation = JandexHelper.getSingleAnnotation( - classInfo, - JPADotNames.ASSOCIATION_OVERRIDES - ); - if ( associationOverrideAnnotation != null ) { - AnnotationInstance[] attributeOverride = associationOverridesAnnotation.value().asNestedArray(); - Collections.addAll( associationOverrideList, attributeOverride ); - } - - return associationOverrideList; - } - private String determineCustomTuplizer() { final AnnotationInstance tuplizersAnnotation = JandexHelper.getSingleAnnotation( classInfo, HibernateDotNames.TUPLIZERS diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/access/AccessTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/access/AccessTest.java index b411ffd4c5..b760352a4b 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/access/AccessTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/access/AccessTest.java @@ -38,9 +38,10 @@ import static org.junit.Assert.assertNull; /** * @author Emmanuel Bernard */ -@FailureExpectedWithNewMetamodel public class AccessTest extends BaseCoreFunctionalTestCase { + @Test + @FailureExpectedWithNewMetamodel public void testSuperclassOverriding() throws Exception { Furniture fur = new Furniture(); fur.setColor( "Black" ); @@ -61,6 +62,7 @@ public class AccessTest extends BaseCoreFunctionalTestCase { } @Test + @FailureExpectedWithNewMetamodel public void testSuperclassNonOverriding() throws Exception { Furniture fur = new Furniture(); fur.setGod( "Buddha" ); @@ -76,7 +78,9 @@ public class AccessTest extends BaseCoreFunctionalTestCase { tx.commit(); s.close(); } - @Test + + @Test + @FailureExpectedWithNewMetamodel public void testPropertyOverriding() throws Exception { Furniture fur = new Furniture(); fur.weight = 3; @@ -92,7 +96,9 @@ public class AccessTest extends BaseCoreFunctionalTestCase { tx.commit(); s.close(); } + @Test + @FailureExpectedWithNewMetamodel public void testNonOverridenSubclass() throws Exception { Chair chair = new Chair(); chair.setPillow( "Blue" ); @@ -108,7 +114,9 @@ public class AccessTest extends BaseCoreFunctionalTestCase { tx.commit(); s.close(); } + @Test + @FailureExpectedWithNewMetamodel public void testOverridenSubclass() throws Exception { BigBed bed = new BigBed(); bed.size = 5; @@ -126,6 +134,7 @@ public class AccessTest extends BaseCoreFunctionalTestCase { tx.commit(); s.close(); } + @Test public void testFieldsOverriding() throws Exception { Gardenshed gs = new Gardenshed(); @@ -143,6 +152,7 @@ public class AccessTest extends BaseCoreFunctionalTestCase { tx.commit(); s.close(); } + @Override protected Class[] getAnnotatedClasses() { return new Class[] { diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/keymanytoone/EagerKeyManyToOneTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/keymanytoone/EagerKeyManyToOneTest.java index e2ef6c390a..a0df4c51cc 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/keymanytoone/EagerKeyManyToOneTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/keymanytoone/EagerKeyManyToOneTest.java @@ -50,7 +50,6 @@ public class EagerKeyManyToOneTest extends BaseCoreFunctionalTestCase { @Test @TestForIssue( jiraKey = "HHH-4147" ) - @FailureExpectedWithNewMetamodel public void testLoadEntityWithEagerFetchingToKeyManyToOneReferenceBackToSelf() { // based on the core testsuite test of same name in org.hibernate.test.keymanytoone.bidir.component.EagerKeyManyToOneTest // meant to test against regression relating to http://opensource.atlassian.com/projects/hibernate/browse/HHH-2277