diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/ListBinder.java b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/ListBinder.java index 6915f6dbf8..4ee8d3d3a5 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/ListBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/ListBinder.java @@ -112,8 +112,8 @@ public class ListBinder extends CollectionBinder { PropertyHolder valueHolder = PropertyHolderBuilder.buildPropertyHolder( this.collection, StringHelper.qualify( this.collection.getRole(), "key" ), - (XClass) null, - (XProperty) null, propertyHolder, mappings + null, + null, propertyHolder, mappings ); List list = (List) this.collection; if ( !list.isOneToMany() ) indexColumn.forceNotNull(); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/PluralAttributeIndexSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/PluralAttributeIndexSourceImpl.java index fb60516fd8..281d55c063 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/PluralAttributeIndexSourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/PluralAttributeIndexSourceImpl.java @@ -1,8 +1,16 @@ package org.hibernate.metamodel.internal.source.annotations; +import java.util.ArrayList; import java.util.List; +import java.util.Map; +import org.jboss.jandex.AnnotationInstance; + +import org.hibernate.metamodel.internal.source.annotations.attribute.Column; import org.hibernate.metamodel.internal.source.annotations.attribute.PluralAssociationAttribute; +import org.hibernate.metamodel.internal.source.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames; +import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper; import org.hibernate.metamodel.spi.binding.PluralAttributeIndexBinding; import org.hibernate.metamodel.spi.source.ExplicitHibernateTypeSource; import org.hibernate.metamodel.spi.source.PluralAttributeIndexSource; @@ -14,15 +22,31 @@ import org.hibernate.metamodel.spi.source.RelationalValueSource; public class PluralAttributeIndexSourceImpl implements PluralAttributeIndexSource { private final PluralAssociationAttribute attribute; private final IndexedPluralAttributeSourceImpl indexedPluralAttributeSource; - + private final int base; + private final List relationalValueSources = new ArrayList( 1 ); public PluralAttributeIndexSourceImpl(IndexedPluralAttributeSourceImpl indexedPluralAttributeSource, PluralAssociationAttribute attribute) { this.attribute = attribute; this.indexedPluralAttributeSource = indexedPluralAttributeSource; + AnnotationInstance columnAnnotation = JandexHelper.getSingleAnnotation( + attribute.annotations(), + HibernateDotNames.INDEX_COLUMN + ); + if(columnAnnotation == null){ + columnAnnotation = JandexHelper.getSingleAnnotation( + attribute.annotations(), + JPADotNames.ORDER_COLUMN + ); + } + this.base = columnAnnotation.value( "base" ) != null ? columnAnnotation.value( "base" ) + .asInt() : 0; + Column indexColumn = new Column( columnAnnotation ); + relationalValueSources.add( new ColumnValuesSourceImpl( indexColumn ) ); + } @Override public PluralAttributeIndexBinding.Nature getNature() { - switch ( indexedPluralAttributeSource.getElementSource().getNature() ){ + switch ( indexedPluralAttributeSource.getElementSource().getNature() ) { case BASIC: return PluralAttributeIndexBinding.Nature.BASIC; case COMPONENT: @@ -37,17 +61,27 @@ public class PluralAttributeIndexSourceImpl implements PluralAttributeIndexSourc @Override public int base() { - return 0; + return base; } @Override public ExplicitHibernateTypeSource explicitHibernateTypeSource() { - return null; + return new ExplicitHibernateTypeSource() { + @Override + public String getName() { + return "integer"; + } + + @Override + public Map getParameters() { + return null; + } + }; } @Override public List relationalValueSources() { - return null; + return relationalValueSources; } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/PluralAttributeKeySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/PluralAttributeKeySourceImpl.java index cf06c21f10..15c631cbbe 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/PluralAttributeKeySourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/PluralAttributeKeySourceImpl.java @@ -53,7 +53,7 @@ public class PluralAttributeKeySourceImpl implements PluralAttributeKeySource { @Override public List getValueSources() { List valueSources = new ArrayList(); - if ( !attribute.getColumnValues().isEmpty() ) { + if ( !attribute.getJoinColumnValues().isEmpty() ) { for ( Column columnValues : attribute.getColumnValues() ) { valueSources.add( new ColumnSourceImpl( attribute, null, columnValues ) ); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/AssociationAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/AssociationAttribute.java index c9825454e9..aef6f5e80b 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/AssociationAttribute.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/AssociationAttribute.java @@ -352,7 +352,7 @@ public class AssociationAttribute extends MappedAttribute { if ( !( Nature.MANY_TO_ONE.equals( getNature() ) || Nature.MANY_TO_ONE .equals( getNature() ) ) ) { throw new MappingException( - "@MapsId can only be specified on a many-to-one or one-to-one associations", + "@MapsId can only be specified on a many-to-one or one-to-one associations, property: "+ getRole(), getContext().getOrigin() ); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/BasicAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/BasicAttribute.java index f48c8bd7f2..5ce0791ddf 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/BasicAttribute.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/BasicAttribute.java @@ -200,7 +200,7 @@ public class BasicAttribute extends MappedAttribute { if ( isId() || isVersioned() ) { throw new AnnotationException( "@OptimisticLock.exclude=true incompatible with @Id, @EmbeddedId and @Version: " - + getName() + + getRole() ); } } @@ -211,7 +211,7 @@ public class BasicAttribute extends MappedAttribute { public String toString() { final StringBuilder sb = new StringBuilder(); sb.append( "SimpleAttribute" ); - sb.append( "{name=" ).append( getName() ); + sb.append( "{name=" ).append( getRole() ); return sb.toString(); } @@ -295,7 +295,7 @@ public class BasicAttribute extends MappedAttribute { } if ( alreadyProcessedForColumn ) { - throw new AnnotationException( "Multiple definition of read/write conditions for column " + getName() ); + throw new AnnotationException( "Multiple definition of read/write conditions for column " + getRole() ); } readWrite[0] = annotationInstance.value( "read" ) == null ? @@ -322,7 +322,7 @@ public class BasicAttribute extends MappedAttribute { if ( StringHelper.isNotEmpty( name ) ) { generator = locateIdentifierGeneratorDefinition( name ); if ( generator == null ) { - throw new MappingException( String.format( "Unable to find named generator %s", name ), null ); + throw new MappingException( String.format( "Unable to find named generator %s", getRole() ), getContext().getOrigin() ); } } else { diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/Column.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/Column.java index ef17dc14b5..4416626671 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/Column.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/Column.java @@ -25,8 +25,10 @@ package org.hibernate.metamodel.internal.source.annotations.attribute; import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.AnnotationValue; +import org.jboss.jandex.DotName; import org.hibernate.AssertionFailure; +import org.hibernate.metamodel.internal.source.annotations.util.HibernateDotNames; import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames; /** @@ -52,11 +54,16 @@ public class Column { private String referencedColumnName; // from @JoinColumn public Column(AnnotationInstance columnAnnotation) { - if ( columnAnnotation != null && - !( JPADotNames.COLUMN.equals( columnAnnotation.name() ) || JPADotNames.JOIN_COLUMN.equals( - columnAnnotation.name() - ) ) ) { - throw new AssertionFailure( "A @Column or @JoinColumn annotation needs to be passed to the constructor" ); + if(columnAnnotation!=null){ + DotName name = columnAnnotation.name(); + if(!(JPADotNames.COLUMN.equals( name ) + || JPADotNames.JOIN_COLUMN.equals( name ) + || JPADotNames.ORDER_COLUMN.equals( name ) + || HibernateDotNames.INDEX_COLUMN.equals( name ) + )){ + throw new AssertionFailure( "A @Column or @JoinColumn annotation needs to be passed to the constructor" ); + + } } applyColumnValues( columnAnnotation ); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/MappedAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/MappedAttribute.java index 7607e8bfa8..b5d485ff72 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/MappedAttribute.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/MappedAttribute.java @@ -99,6 +99,11 @@ public abstract class MappedAttribute implements Comparable { */ private final String checkCondition; + /** + * FQN of the attribute. + */ + private final String role; + /** * The binding context */ @@ -125,6 +130,7 @@ public abstract class MappedAttribute implements Comparable { this.isOptimisticLockable = checkOptimisticLockAnnotation(); this.checkCondition = checkCheckAnnotation(); this.naturalIdMutability = checkNaturalId(); + this.role = context.getOrigin().getName() + "#" + name; checkColumnAnnotations( annotations ); } @@ -132,6 +138,10 @@ public abstract class MappedAttribute implements Comparable { return name; } + public String getRole(){ + return role; + } + public final Class getAttributeType() { return attributeType; } @@ -185,7 +195,7 @@ public abstract class MappedAttribute implements Comparable { public String toString() { final StringBuilder sb = new StringBuilder(); sb.append( "MappedAttribute" ); - sb.append( "{name='" ).append( context.getOrigin().getName() ).append( "#" ).append( name ).append( '\'' ); + sb.append( "{name='" ).append( getRole() ).append( '\'' ); sb.append( '}' ); return sb.toString(); } @@ -237,8 +247,7 @@ public abstract class MappedAttribute implements Comparable { if ( columnAnnotation != null ) { if ( getNature() == Nature.MANY_TO_ONE || getNature() == Nature.ONE_TO_ONE ) { throw getContext().makeMappingException( - "@Column(s) not allowed on a " + getNature() + " property: " + getContext().getOrigin() - .getName() + "." + name + "@Column(s) not allowed on a " + getNature() + " property: " + getRole() ); } columnValues.add( new Column( columnAnnotation ) ); @@ -252,8 +261,7 @@ public abstract class MappedAttribute implements Comparable { if ( columnsAnnotation != null ) { if ( getNature() == Nature.MANY_TO_ONE || getNature() == Nature.ONE_TO_ONE ) { throw getContext().makeMappingException( - "@Column(s) not allowed on a " + getNature() + " property: " + getContext().getOrigin() - .getName() + "." + name + "@Column(s) not allowed on a " + getNature() + " property: " + getRole() ); } List columnsList = Arrays.asList( diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/PluralAssociationAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/PluralAssociationAttribute.java index 4263bac628..84a4ee2dd5 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/PluralAssociationAttribute.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/PluralAssociationAttribute.java @@ -217,7 +217,7 @@ public class PluralAssociationAttribute extends AssociationAttribute { String comparatorName = JandexHelper.getValue( sortAnnotation, "comparator", String.class ); if ( StringHelper.isEmpty( comparatorName ) ) { throw new MappingException( - "Comparator class must be provided when using SortType.COMPARATOR.", + "Comparator class must be provided when using SortType.COMPARATOR on property: "+ getRole(), getContext().getOrigin() ); } @@ -230,6 +230,9 @@ public class PluralAssociationAttribute extends AssociationAttribute { AnnotationInstance orderColumnAnnotation = JandexHelper.getSingleAnnotation( annotations, JPADotNames.ORDER_COLUMN ); AnnotationInstance indexColumnAnnotation = JandexHelper.getSingleAnnotation( annotations, HibernateDotNames.INDEX_COLUMN ); + if(orderColumnAnnotation!=null && indexColumnAnnotation!=null){ + throw new MappingException( "@OrderColumn and @IndexColumn can't be used together on property: " + getRole() ,getContext().getOrigin() ); + } this.isIndexed = orderColumnAnnotation != null || indexColumnAnnotation != null; } @@ -323,7 +326,7 @@ public class PluralAssociationAttribute extends AssociationAttribute { if ( jpaWhereAnnotation != null && hibernateWhereAnnotation != null ) { throw new AnnotationException( "Cannot use sql order by clause (@org.hibernate.annotations.OrderBy) " + - "in conjunction with JPA order by clause (@java.persistence.OrderBy) on " + getName() + "in conjunction with JPA order by clause (@java.persistence.OrderBy) on " + getRole() ); } diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/ElementCollectionBindingTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/ElementCollectionBindingTest.java index 2a67ddd504..7a1d1bb4a3 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/ElementCollectionBindingTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/ElementCollectionBindingTest.java @@ -33,7 +33,9 @@ import javax.persistence.JoinTable; import org.junit.Test; +import org.hibernate.annotations.IndexColumn; import org.hibernate.jaxb.spi.SourceType; +import org.hibernate.metamodel.spi.binding.BagBinding; import org.hibernate.metamodel.spi.binding.EntityBinding; import org.hibernate.metamodel.spi.binding.ListBinding; import org.hibernate.metamodel.spi.relational.Column; @@ -140,8 +142,8 @@ public class ElementCollectionBindingTest extends BaseAnnotationBindingTestCase @Resources(annotatedClasses = TestEntity3.class) public void testDefaultJoinTableName() { EntityBinding entityBinding = getEntityBinding( TestEntity3.class ); - ListBinding listBinding = ( ListBinding ) entityBinding.locateAttributeBinding( "strings" ); - TableSpecification tableSpec = listBinding.getPluralAttributeKeyBinding().getCollectionTable(); + BagBinding bagBinding = ( BagBinding ) entityBinding.locateAttributeBinding( "strings" ); + TableSpecification tableSpec = bagBinding.getPluralAttributeKeyBinding().getCollectionTable(); assertEquals( "Wrong default collection table name", "ElementCollectionBindingTest$TestEntity3_strings", @@ -171,8 +173,8 @@ public class ElementCollectionBindingTest extends BaseAnnotationBindingTestCase @Resources(annotatedClasses = TestEntity4.class) public void testExplicitJoinTableName() { EntityBinding entityBinding = getEntityBinding( TestEntity4.class ); - ListBinding listBinding = ( ListBinding ) entityBinding.locateAttributeBinding( "strings" ); - TableSpecification tableSpec = listBinding.getPluralAttributeKeyBinding().getCollectionTable(); + BagBinding bagBinding = ( BagBinding ) entityBinding.locateAttributeBinding( "strings" ); + TableSpecification tableSpec = bagBinding.getPluralAttributeKeyBinding().getCollectionTable(); assertEquals( "Wrong default collection table name", "STRING_COLLECTION", @@ -203,8 +205,8 @@ public class ElementCollectionBindingTest extends BaseAnnotationBindingTestCase @Resources(annotatedClasses = TestEntity5.class) public void testJoinColumnAsPartOfCollectionTable() { EntityBinding entityBinding = getEntityBinding( TestEntity5.class ); - ListBinding listBinding = ( ListBinding ) entityBinding.locateAttributeBinding( "strings" ); - TableSpecification tableSpec = listBinding.getPluralAttributeKeyBinding().getCollectionTable(); + BagBinding bagBinding = ( BagBinding ) entityBinding.locateAttributeBinding( "strings" ); + TableSpecification tableSpec = bagBinding.getPluralAttributeKeyBinding().getCollectionTable(); Column column = tableSpec.locateColumn( "FOO" ); assertNotNull( "The join column should be named FOO", column ); } @@ -231,8 +233,8 @@ public class ElementCollectionBindingTest extends BaseAnnotationBindingTestCase @Resources(annotatedClasses = TestEntity6.class) public void testElementCollectionWithJoinColumn() { EntityBinding entityBinding = getEntityBinding( TestEntity6.class ); - ListBinding listBinding = ( ListBinding ) entityBinding.locateAttributeBinding( "strings" ); - TableSpecification tableSpec = listBinding.getPluralAttributeKeyBinding().getCollectionTable(); + BagBinding bagBinding = ( BagBinding ) entityBinding.locateAttributeBinding( "strings" ); + TableSpecification tableSpec = bagBinding.getPluralAttributeKeyBinding().getCollectionTable(); Column column = tableSpec.locateColumn( "FOO" ); assertNotNull( "The join column should be named FOO", column ); } diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/onetomany/EntityWithUnidirectionalOneToMany.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/onetomany/EntityWithUnidirectionalOneToMany.java index b479863e81..d9fec93ee1 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/onetomany/EntityWithUnidirectionalOneToMany.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/onetomany/EntityWithUnidirectionalOneToMany.java @@ -13,6 +13,7 @@ import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.OneToMany; +import org.hibernate.annotations.IndexColumn; import org.hibernate.annotations.LazyCollection; import org.hibernate.annotations.LazyCollectionOption; /** @@ -68,6 +69,7 @@ public class EntityWithUnidirectionalOneToMany { @OneToMany(fetch = FetchType.EAGER) @JoinColumn(name = "theListOwner", nullable = false) + @IndexColumn( name = "list_index") public List getTheList() { return theList; }