HHH-10242 - Deal with HCANN poor handling of multiple properties by matching stem name

This commit is contained in:
Steve Ebersole 2015-11-05 11:53:40 -06:00
parent 5cc5ed1c84
commit ae9ff5587e
4 changed files with 100 additions and 8 deletions

View File

@ -28,6 +28,10 @@ import org.hibernate.annotations.Target;
import org.hibernate.annotations.Type;
import org.hibernate.annotations.common.reflection.XClass;
import org.hibernate.annotations.common.reflection.XProperty;
import org.hibernate.annotations.common.reflection.java.JavaXMember;
import org.hibernate.boot.jaxb.Origin;
import org.hibernate.boot.jaxb.SourceType;
import org.hibernate.cfg.annotations.HCANNHelper;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.StringHelper;
@ -188,7 +192,14 @@ class PropertyContainer {
// HHH-10242 detect registration of the same property twice eg boolean isId() + UUID getId()
XProperty oldProperty = propertiesMap.get( property.getName() );
if ( oldProperty != null ) {
throw LOG.throwAmbiguousPropertyException( this.xClass, oldProperty.getName(), oldProperty.getType(), property.getType() );
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 );

View File

@ -0,0 +1,70 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.cfg.annotations;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import org.hibernate.AssertionFailure;
import org.hibernate.annotations.common.reflection.XProperty;
import org.hibernate.annotations.common.reflection.java.JavaXMember;
/**
* Manage the various fun-ness of dealing with HCANN...
*
* @author Steve Ebersole
*/
public class HCANNHelper {
private static Class javaXMemberClass = JavaXMember.class;
private static Method getMemberMethod;
public static String annotatedElementSignature(XProperty xProperty) {
if ( getMemberMethod == null ) {
resolveGetMemberMethod();
}
return getUnderlyingMember( xProperty ).toString();
}
public static Member getUnderlyingMember(XProperty xProperty) {
if ( getMemberMethod == null ) {
resolveGetMemberMethod();
}
try {
return (Member) getMemberMethod.invoke( xProperty );
}
catch (IllegalAccessException e) {
throw new AssertionFailure(
"Could not resolve member signature from XProperty reference",
e
);
}
catch (InvocationTargetException e) {
throw new AssertionFailure(
"Could not resolve member signature from XProperty reference",
e.getCause()
);
}
}
@SuppressWarnings("unchecked")
private static void resolveGetMemberMethod() {
try {
getMemberMethod = javaXMemberClass.getDeclaredMethod( "getMember" );
getMemberMethod.setAccessible( true );
}
catch (NoSuchMethodException e) {
throw new AssertionFailure(
"Could not resolve JavaXAnnotatedElement#toAnnotatedElement method in order to access XProperty member signature",
e
);
}
}
}

View File

@ -1753,6 +1753,9 @@ public interface CoreMessageLogger extends BasicLogger {
@Message(value = "Omitting cached file [%s] as the mapping file is newer", id = 473)
void cachedFileObsolete(File cachedFile);
@Message(value = "Ambiguous property detected %s.%s (of types %s and %s). Mark one as @Transient.", id = 474)
HibernateException throwAmbiguousPropertyException(XClass entity, String propertyName, XClass firstPropertyType, XClass secondPropertyType);
@Message(
value = "Ambiguous persistent property methods detected on %s; mark one as @Transient : [%s] and [%s]",
id = 474
)
String ambiguousPropertyMethods(String entityName, String oneMethodSig, String secondMethodSig);
}

View File

@ -19,6 +19,8 @@ import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.startsWith;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
/**
@ -50,17 +52,23 @@ public class GetAndIsVariantGetterTest {
.buildMetadata();
fail( "Expecting a failure" );
}
catch (MappingException ignore) {
// expected
catch (MappingException e) {
assertThat( e.getMessage(), startsWith( "In trying to locate getter for property [id]" ) );
}
}
@Test
@TestForIssue( jiraKey = "HHH-10172" )
public void testAnnotations() {
new MetadataSources( ssr )
.addAnnotatedClass( TheEntity.class )
.buildMetadata();
try {
new MetadataSources( ssr )
.addAnnotatedClass( TheEntity.class )
.buildMetadata();
fail( "Expecting a failure" );
}
catch (MappingException e) {
assertThat( e.getMessage(), startsWith( "HHH000474: Ambiguous persistent property methods detected on" ) );
}
}
@Entity