HHH-10242 - Deal with HCANN poor handling of multiple properties by matching stem name
This commit is contained in:
parent
5cc5ed1c84
commit
ae9ff5587e
|
@ -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 );
|
||||
|
|
|
@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue