HHH-6537 Adding check for @MapsId annotation to AssociationAttribute.
This commit is contained in:
parent
21ea415f61
commit
89991f8610
|
@ -37,12 +37,15 @@ import org.jboss.jandex.DotName;
|
|||
import org.hibernate.FetchMode;
|
||||
import org.hibernate.annotations.NotFoundAction;
|
||||
import org.hibernate.mapping.PropertyGeneration;
|
||||
import org.hibernate.metamodel.source.annotations.AnnotationBindingContext;
|
||||
import org.hibernate.metamodel.source.MappingException;
|
||||
import org.hibernate.metamodel.source.annotations.EnumConversionHelper;
|
||||
import org.hibernate.metamodel.source.annotations.HibernateDotNames;
|
||||
import org.hibernate.metamodel.source.annotations.JPADotNames;
|
||||
import org.hibernate.metamodel.source.annotations.JandexHelper;
|
||||
import org.hibernate.metamodel.source.annotations.attribute.type.AttributeTypeResolver;
|
||||
import org.hibernate.metamodel.source.annotations.attribute.type.AttributeTypeResolverImpl;
|
||||
import org.hibernate.metamodel.source.annotations.attribute.type.CompositeAttributeTypeResolver;
|
||||
import org.hibernate.metamodel.source.annotations.entity.EntityBindingContext;
|
||||
|
||||
/**
|
||||
* Represents an association attribute.
|
||||
|
@ -60,6 +63,8 @@ public class AssociationAttribute extends MappedAttribute {
|
|||
private final boolean isLazy;
|
||||
private final boolean isOrphanRemoval;
|
||||
private final FetchMode fetchMode;
|
||||
private final boolean mapsId;
|
||||
private final String referencedIdAttributeName;
|
||||
|
||||
private boolean isInsertable = true;
|
||||
private boolean isUpdatable = true;
|
||||
|
@ -70,7 +75,7 @@ public class AssociationAttribute extends MappedAttribute {
|
|||
AttributeNature attributeNature,
|
||||
String accessType,
|
||||
Map<DotName, List<AnnotationInstance>> annotations,
|
||||
AnnotationBindingContext context) {
|
||||
EntityBindingContext context) {
|
||||
return new AssociationAttribute(
|
||||
name,
|
||||
attributeType,
|
||||
|
@ -86,7 +91,7 @@ public class AssociationAttribute extends MappedAttribute {
|
|||
AttributeNature associationType,
|
||||
String accessType,
|
||||
Map<DotName, List<AnnotationInstance>> annotations,
|
||||
AnnotationBindingContext context) {
|
||||
EntityBindingContext context) {
|
||||
super( name, javaType, accessType, annotations, context );
|
||||
this.associationNature = associationType;
|
||||
this.ignoreNotFound = ignoreNotFound();
|
||||
|
@ -105,6 +110,8 @@ public class AssociationAttribute extends MappedAttribute {
|
|||
this.cascadeTypes = determineCascadeTypes( associationAnnotation );
|
||||
|
||||
this.fetchMode = determineFetchMode();
|
||||
this.referencedIdAttributeName = determineMapsId();
|
||||
this.mapsId = referencedIdAttributeName != null;
|
||||
}
|
||||
|
||||
public boolean isIgnoreNotFound() {
|
||||
|
@ -135,6 +142,14 @@ public class AssociationAttribute extends MappedAttribute {
|
|||
return fetchMode;
|
||||
}
|
||||
|
||||
public String getReferencedIdAttributeName() {
|
||||
return referencedIdAttributeName;
|
||||
}
|
||||
|
||||
public boolean mapsId() {
|
||||
return mapsId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AttributeTypeResolver getHibernateTypeResolver() {
|
||||
if ( resolver == null ) {
|
||||
|
@ -271,10 +286,31 @@ public class AssociationAttribute extends MappedAttribute {
|
|||
"value",
|
||||
org.hibernate.annotations.FetchMode.class
|
||||
);
|
||||
mode = EnumConversionHelper.annotationFetchModeToHibernateFetchMode( annotationFetchMode );
|
||||
}
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
private String determineMapsId() {
|
||||
String referencedIdAttributeName;
|
||||
AnnotationInstance mapsIdAnnotation = JandexHelper.getSingleAnnotation( annotations(), JPADotNames.MAPS_ID );
|
||||
if ( mapsIdAnnotation == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ( !( AttributeNature.MANY_TO_ONE.equals( getAssociationNature() ) || AttributeNature.MANY_TO_ONE
|
||||
.equals( getAssociationNature() ) ) ) {
|
||||
throw new MappingException(
|
||||
"@MapsId can only be specified on a many-to-one or one-to-one associations",
|
||||
getContext().getOrigin()
|
||||
);
|
||||
}
|
||||
|
||||
referencedIdAttributeName = JandexHelper.getValue( mapsIdAnnotation, "value", String.class );
|
||||
|
||||
return referencedIdAttributeName;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -40,17 +40,17 @@ import org.hibernate.internal.util.StringHelper;
|
|||
import org.hibernate.mapping.PropertyGeneration;
|
||||
import org.hibernate.metamodel.binding.IdGenerator;
|
||||
import org.hibernate.metamodel.source.MappingException;
|
||||
import org.hibernate.metamodel.source.annotations.AnnotationBindingContext;
|
||||
import org.hibernate.metamodel.source.annotations.EnumConversionHelper;
|
||||
import org.hibernate.metamodel.source.annotations.HibernateDotNames;
|
||||
import org.hibernate.metamodel.source.annotations.JPADotNames;
|
||||
import org.hibernate.metamodel.source.annotations.JandexHelper;
|
||||
import org.hibernate.metamodel.source.annotations.EnumConversionHelper;
|
||||
import org.hibernate.metamodel.source.annotations.attribute.type.AttributeTypeResolver;
|
||||
import org.hibernate.metamodel.source.annotations.attribute.type.AttributeTypeResolverImpl;
|
||||
import org.hibernate.metamodel.source.annotations.attribute.type.CompositeAttributeTypeResolver;
|
||||
import org.hibernate.metamodel.source.annotations.attribute.type.EnumeratedTypeResolver;
|
||||
import org.hibernate.metamodel.source.annotations.attribute.type.AttributeTypeResolverImpl;
|
||||
import org.hibernate.metamodel.source.annotations.attribute.type.LobTypeResolver;
|
||||
import org.hibernate.metamodel.source.annotations.attribute.type.TemporalTypeResolver;
|
||||
import org.hibernate.metamodel.source.annotations.entity.EntityBindingContext;
|
||||
|
||||
/**
|
||||
* Represent a basic attribute (explicitly or implicitly mapped).
|
||||
|
@ -96,7 +96,7 @@ public class BasicAttribute extends MappedAttribute {
|
|||
Class<?> attributeType,
|
||||
Map<DotName, List<AnnotationInstance>> annotations,
|
||||
String accessType,
|
||||
AnnotationBindingContext context) {
|
||||
EntityBindingContext context) {
|
||||
return new BasicAttribute( name, attributeType, accessType, annotations, context );
|
||||
}
|
||||
|
||||
|
@ -104,7 +104,7 @@ public class BasicAttribute extends MappedAttribute {
|
|||
Class<?> attributeType,
|
||||
String accessType,
|
||||
Map<DotName, List<AnnotationInstance>> annotations,
|
||||
AnnotationBindingContext context) {
|
||||
EntityBindingContext context) {
|
||||
super( name, attributeType, accessType, annotations, context );
|
||||
|
||||
AnnotationInstance versionAnnotation = JandexHelper.getSingleAnnotation( annotations, JPADotNames.VERSION );
|
||||
|
|
|
@ -30,11 +30,11 @@ import org.jboss.jandex.AnnotationInstance;
|
|||
import org.jboss.jandex.DotName;
|
||||
|
||||
import org.hibernate.mapping.PropertyGeneration;
|
||||
import org.hibernate.metamodel.source.annotations.AnnotationBindingContext;
|
||||
import org.hibernate.metamodel.source.annotations.HibernateDotNames;
|
||||
import org.hibernate.metamodel.source.annotations.JPADotNames;
|
||||
import org.hibernate.metamodel.source.annotations.JandexHelper;
|
||||
import org.hibernate.metamodel.source.annotations.attribute.type.AttributeTypeResolver;
|
||||
import org.hibernate.metamodel.source.annotations.entity.EntityBindingContext;
|
||||
|
||||
/**
|
||||
* Base class for the different types of mapped attributes
|
||||
|
@ -82,9 +82,9 @@ public abstract class MappedAttribute implements Comparable<MappedAttribute> {
|
|||
/**
|
||||
* The binding context
|
||||
*/
|
||||
private final AnnotationBindingContext context;
|
||||
private final EntityBindingContext context;
|
||||
|
||||
MappedAttribute(String name, Class<?> attributeType, String accessType, Map<DotName, List<AnnotationInstance>> annotations, AnnotationBindingContext context) {
|
||||
MappedAttribute(String name, Class<?> attributeType, String accessType, Map<DotName, List<AnnotationInstance>> annotations, EntityBindingContext context) {
|
||||
this.context = context;
|
||||
this.annotations = annotations;
|
||||
this.name = name;
|
||||
|
@ -120,7 +120,7 @@ public abstract class MappedAttribute implements Comparable<MappedAttribute> {
|
|||
return accessType;
|
||||
}
|
||||
|
||||
public AnnotationBindingContext getContext() {
|
||||
public EntityBindingContext getContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
|
|
|
@ -137,7 +137,7 @@ public class ConfiguredClass {
|
|||
*/
|
||||
private final String customTuplizer;
|
||||
|
||||
private final LocalBindingContextImpl localBindingContext;
|
||||
private final EntityBindingContext localBindingContext;
|
||||
|
||||
public ConfiguredClass(
|
||||
ClassInfo classInfo,
|
||||
|
@ -155,7 +155,7 @@ public class ConfiguredClass {
|
|||
this.idAttributeMap = new TreeMap<String, BasicAttribute>();
|
||||
this.associationAttributeMap = new TreeMap<String, AssociationAttribute>();
|
||||
|
||||
this.localBindingContext = new LocalBindingContextImpl( context, this );
|
||||
this.localBindingContext = new EntityBindingContext( context, this );
|
||||
|
||||
collectAttributes();
|
||||
attributeOverrideMap = Collections.unmodifiableMap( findAttributeOverrides() );
|
||||
|
@ -177,7 +177,7 @@ public class ConfiguredClass {
|
|||
return parent;
|
||||
}
|
||||
|
||||
public LocalBindingContextImpl getLocalBindingContext() {
|
||||
public EntityBindingContext getLocalBindingContext() {
|
||||
return localBindingContext;
|
||||
}
|
||||
|
||||
|
|
|
@ -44,11 +44,11 @@ import org.hibernate.service.ServiceRegistry;
|
|||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class LocalBindingContextImpl implements LocalBindingContext, AnnotationBindingContext {
|
||||
public class EntityBindingContext implements LocalBindingContext, AnnotationBindingContext {
|
||||
private final AnnotationBindingContext contextDelegate;
|
||||
private final Origin origin;
|
||||
|
||||
public LocalBindingContextImpl(AnnotationBindingContext contextDelegate, ConfiguredClass source) {
|
||||
public EntityBindingContext(AnnotationBindingContext contextDelegate, ConfiguredClass source) {
|
||||
this.contextDelegate = contextDelegate;
|
||||
this.origin = new Origin( SourceType.ANNOTATION, source.getName() );
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
package org.hibernate.metamodel.source.annotations.entity;
|
||||
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.MapsId;
|
||||
import javax.persistence.OneToMany;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.metamodel.MetadataSources;
|
||||
import org.hibernate.metamodel.source.MappingException;
|
||||
import org.hibernate.service.ServiceRegistryBuilder;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
import static junit.framework.Assert.fail;
|
||||
|
||||
/**
|
||||
* @author Hardy Ferentschik
|
||||
*/
|
||||
public class MapsIdTest extends BaseAnnotationBindingTestCase {
|
||||
@Entity
|
||||
public class Employee {
|
||||
@Id
|
||||
long empId;
|
||||
String name;
|
||||
}
|
||||
|
||||
@Embeddable
|
||||
public class DependentId {
|
||||
String name;
|
||||
long empid; // corresponds to PK type of Employee
|
||||
}
|
||||
|
||||
@Entity
|
||||
public class Dependent {
|
||||
@Id
|
||||
// should be @EmbeddedId, but embedded id are not working atm
|
||||
DependentId id;
|
||||
|
||||
@MapsId("empid")
|
||||
@OneToMany
|
||||
Employee emp; // maps the empid attribute of embedded id @ManyToOne Employee emp;
|
||||
}
|
||||
|
||||
@Test
|
||||
@Resources(annotatedClasses = DependentId.class)
|
||||
public void testMapsIsOnOneToManyThrowsException() {
|
||||
try {
|
||||
sources = new MetadataSources( new ServiceRegistryBuilder().buildServiceRegistry() );
|
||||
sources.addAnnotatedClass( DependentId.class );
|
||||
sources.addAnnotatedClass( Dependent.class );
|
||||
sources.addAnnotatedClass( Employee.class );
|
||||
sources.buildMetadata();
|
||||
fail();
|
||||
}
|
||||
catch ( MappingException e ) {
|
||||
assertTrue(
|
||||
e.getMessage()
|
||||
.startsWith( "@MapsId can only be specified on a many-to-one or one-to-one associations" )
|
||||
);
|
||||
assertEquals(
|
||||
"Wrong error origin",
|
||||
"org.hibernate.metamodel.source.annotations.entity.MapsIdTest$Dependent",
|
||||
e.getOrigin().getName()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue