HHH-7549 binding Indexed collection

This commit is contained in:
Strong Liu 2012-09-12 17:49:01 +08:00
parent b939be3157
commit ea2b9a899f
10 changed files with 89 additions and 33 deletions

View File

@ -112,8 +112,8 @@ public class ListBinder extends CollectionBinder {
PropertyHolder valueHolder = PropertyHolderBuilder.buildPropertyHolder( PropertyHolder valueHolder = PropertyHolderBuilder.buildPropertyHolder(
this.collection, this.collection,
StringHelper.qualify( this.collection.getRole(), "key" ), StringHelper.qualify( this.collection.getRole(), "key" ),
(XClass) null, null,
(XProperty) null, propertyHolder, mappings null, propertyHolder, mappings
); );
List list = (List) this.collection; List list = (List) this.collection;
if ( !list.isOneToMany() ) indexColumn.forceNotNull(); if ( !list.isOneToMany() ) indexColumn.forceNotNull();

View File

@ -1,8 +1,16 @@
package org.hibernate.metamodel.internal.source.annotations; package org.hibernate.metamodel.internal.source.annotations;
import java.util.ArrayList;
import java.util.List; 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.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.binding.PluralAttributeIndexBinding;
import org.hibernate.metamodel.spi.source.ExplicitHibernateTypeSource; import org.hibernate.metamodel.spi.source.ExplicitHibernateTypeSource;
import org.hibernate.metamodel.spi.source.PluralAttributeIndexSource; import org.hibernate.metamodel.spi.source.PluralAttributeIndexSource;
@ -14,15 +22,31 @@ import org.hibernate.metamodel.spi.source.RelationalValueSource;
public class PluralAttributeIndexSourceImpl implements PluralAttributeIndexSource { public class PluralAttributeIndexSourceImpl implements PluralAttributeIndexSource {
private final PluralAssociationAttribute attribute; private final PluralAssociationAttribute attribute;
private final IndexedPluralAttributeSourceImpl indexedPluralAttributeSource; private final IndexedPluralAttributeSourceImpl indexedPluralAttributeSource;
private final int base;
private final List<RelationalValueSource> relationalValueSources = new ArrayList<RelationalValueSource>( 1 );
public PluralAttributeIndexSourceImpl(IndexedPluralAttributeSourceImpl indexedPluralAttributeSource, PluralAssociationAttribute attribute) { public PluralAttributeIndexSourceImpl(IndexedPluralAttributeSourceImpl indexedPluralAttributeSource, PluralAssociationAttribute attribute) {
this.attribute = attribute; this.attribute = attribute;
this.indexedPluralAttributeSource = indexedPluralAttributeSource; 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 @Override
public PluralAttributeIndexBinding.Nature getNature() { public PluralAttributeIndexBinding.Nature getNature() {
switch ( indexedPluralAttributeSource.getElementSource().getNature() ){ switch ( indexedPluralAttributeSource.getElementSource().getNature() ) {
case BASIC: case BASIC:
return PluralAttributeIndexBinding.Nature.BASIC; return PluralAttributeIndexBinding.Nature.BASIC;
case COMPONENT: case COMPONENT:
@ -37,17 +61,27 @@ public class PluralAttributeIndexSourceImpl implements PluralAttributeIndexSourc
@Override @Override
public int base() { public int base() {
return 0; return base;
} }
@Override @Override
public ExplicitHibernateTypeSource explicitHibernateTypeSource() { public ExplicitHibernateTypeSource explicitHibernateTypeSource() {
return new ExplicitHibernateTypeSource() {
@Override
public String getName() {
return "integer";
}
@Override
public Map<String, String> getParameters() {
return null; return null;
} }
};
}
@Override @Override
public List<RelationalValueSource> relationalValueSources() { public List<RelationalValueSource> relationalValueSources() {
return null; return relationalValueSources;
} }
@Override @Override

View File

@ -53,7 +53,7 @@ public class PluralAttributeKeySourceImpl implements PluralAttributeKeySource {
@Override @Override
public List<RelationalValueSource> getValueSources() { public List<RelationalValueSource> getValueSources() {
List<RelationalValueSource> valueSources = new ArrayList<RelationalValueSource>(); List<RelationalValueSource> valueSources = new ArrayList<RelationalValueSource>();
if ( !attribute.getColumnValues().isEmpty() ) { if ( !attribute.getJoinColumnValues().isEmpty() ) {
for ( Column columnValues : attribute.getColumnValues() ) { for ( Column columnValues : attribute.getColumnValues() ) {
valueSources.add( new ColumnSourceImpl( attribute, null, columnValues ) ); valueSources.add( new ColumnSourceImpl( attribute, null, columnValues ) );
} }

View File

@ -352,7 +352,7 @@ public class AssociationAttribute extends MappedAttribute {
if ( !( Nature.MANY_TO_ONE.equals( getNature() ) || Nature.MANY_TO_ONE if ( !( Nature.MANY_TO_ONE.equals( getNature() ) || Nature.MANY_TO_ONE
.equals( getNature() ) ) ) { .equals( getNature() ) ) ) {
throw new MappingException( 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() getContext().getOrigin()
); );
} }

View File

@ -200,7 +200,7 @@ public class BasicAttribute extends MappedAttribute {
if ( isId() || isVersioned() ) { if ( isId() || isVersioned() ) {
throw new AnnotationException( throw new AnnotationException(
"@OptimisticLock.exclude=true incompatible with @Id, @EmbeddedId and @Version: " "@OptimisticLock.exclude=true incompatible with @Id, @EmbeddedId and @Version: "
+ getName() + getRole()
); );
} }
} }
@ -211,7 +211,7 @@ public class BasicAttribute extends MappedAttribute {
public String toString() { public String toString() {
final StringBuilder sb = new StringBuilder(); final StringBuilder sb = new StringBuilder();
sb.append( "SimpleAttribute" ); sb.append( "SimpleAttribute" );
sb.append( "{name=" ).append( getName() ); sb.append( "{name=" ).append( getRole() );
return sb.toString(); return sb.toString();
} }
@ -295,7 +295,7 @@ public class BasicAttribute extends MappedAttribute {
} }
if ( alreadyProcessedForColumn ) { 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 ? readWrite[0] = annotationInstance.value( "read" ) == null ?
@ -322,7 +322,7 @@ public class BasicAttribute extends MappedAttribute {
if ( StringHelper.isNotEmpty( name ) ) { if ( StringHelper.isNotEmpty( name ) ) {
generator = locateIdentifierGeneratorDefinition( name ); generator = locateIdentifierGeneratorDefinition( name );
if ( generator == null ) { 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 { else {

View File

@ -25,8 +25,10 @@ package org.hibernate.metamodel.internal.source.annotations.attribute;
import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.AnnotationValue; import org.jboss.jandex.AnnotationValue;
import org.jboss.jandex.DotName;
import org.hibernate.AssertionFailure; import org.hibernate.AssertionFailure;
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.JPADotNames;
/** /**
@ -52,11 +54,16 @@ public class Column {
private String referencedColumnName; // from @JoinColumn private String referencedColumnName; // from @JoinColumn
public Column(AnnotationInstance columnAnnotation) { public Column(AnnotationInstance columnAnnotation) {
if ( columnAnnotation != null && if(columnAnnotation!=null){
!( JPADotNames.COLUMN.equals( columnAnnotation.name() ) || JPADotNames.JOIN_COLUMN.equals( DotName name = columnAnnotation.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" ); throw new AssertionFailure( "A @Column or @JoinColumn annotation needs to be passed to the constructor" );
}
} }
applyColumnValues( columnAnnotation ); applyColumnValues( columnAnnotation );
} }

View File

@ -99,6 +99,11 @@ public abstract class MappedAttribute implements Comparable<MappedAttribute> {
*/ */
private final String checkCondition; private final String checkCondition;
/**
* FQN of the attribute.
*/
private final String role;
/** /**
* The binding context * The binding context
*/ */
@ -125,6 +130,7 @@ public abstract class MappedAttribute implements Comparable<MappedAttribute> {
this.isOptimisticLockable = checkOptimisticLockAnnotation(); this.isOptimisticLockable = checkOptimisticLockAnnotation();
this.checkCondition = checkCheckAnnotation(); this.checkCondition = checkCheckAnnotation();
this.naturalIdMutability = checkNaturalId(); this.naturalIdMutability = checkNaturalId();
this.role = context.getOrigin().getName() + "#" + name;
checkColumnAnnotations( annotations ); checkColumnAnnotations( annotations );
} }
@ -132,6 +138,10 @@ public abstract class MappedAttribute implements Comparable<MappedAttribute> {
return name; return name;
} }
public String getRole(){
return role;
}
public final Class<?> getAttributeType() { public final Class<?> getAttributeType() {
return attributeType; return attributeType;
} }
@ -185,7 +195,7 @@ public abstract class MappedAttribute implements Comparable<MappedAttribute> {
public String toString() { public String toString() {
final StringBuilder sb = new StringBuilder(); final StringBuilder sb = new StringBuilder();
sb.append( "MappedAttribute" ); sb.append( "MappedAttribute" );
sb.append( "{name='" ).append( context.getOrigin().getName() ).append( "#" ).append( name ).append( '\'' ); sb.append( "{name='" ).append( getRole() ).append( '\'' );
sb.append( '}' ); sb.append( '}' );
return sb.toString(); return sb.toString();
} }
@ -237,8 +247,7 @@ public abstract class MappedAttribute implements Comparable<MappedAttribute> {
if ( columnAnnotation != null ) { if ( columnAnnotation != null ) {
if ( getNature() == Nature.MANY_TO_ONE || getNature() == Nature.ONE_TO_ONE ) { if ( getNature() == Nature.MANY_TO_ONE || getNature() == Nature.ONE_TO_ONE ) {
throw getContext().makeMappingException( throw getContext().makeMappingException(
"@Column(s) not allowed on a " + getNature() + " property: " + getContext().getOrigin() "@Column(s) not allowed on a " + getNature() + " property: " + getRole()
.getName() + "." + name
); );
} }
columnValues.add( new Column( columnAnnotation ) ); columnValues.add( new Column( columnAnnotation ) );
@ -252,8 +261,7 @@ public abstract class MappedAttribute implements Comparable<MappedAttribute> {
if ( columnsAnnotation != null ) { if ( columnsAnnotation != null ) {
if ( getNature() == Nature.MANY_TO_ONE || getNature() == Nature.ONE_TO_ONE ) { if ( getNature() == Nature.MANY_TO_ONE || getNature() == Nature.ONE_TO_ONE ) {
throw getContext().makeMappingException( throw getContext().makeMappingException(
"@Column(s) not allowed on a " + getNature() + " property: " + getContext().getOrigin() "@Column(s) not allowed on a " + getNature() + " property: " + getRole()
.getName() + "." + name
); );
} }
List<AnnotationInstance> columnsList = Arrays.asList( List<AnnotationInstance> columnsList = Arrays.asList(

View File

@ -217,7 +217,7 @@ public class PluralAssociationAttribute extends AssociationAttribute {
String comparatorName = JandexHelper.getValue( sortAnnotation, "comparator", String.class ); String comparatorName = JandexHelper.getValue( sortAnnotation, "comparator", String.class );
if ( StringHelper.isEmpty( comparatorName ) ) { if ( StringHelper.isEmpty( comparatorName ) ) {
throw new MappingException( 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() getContext().getOrigin()
); );
} }
@ -230,6 +230,9 @@ public class PluralAssociationAttribute extends AssociationAttribute {
AnnotationInstance orderColumnAnnotation = JandexHelper.getSingleAnnotation( annotations, JPADotNames.ORDER_COLUMN ); AnnotationInstance orderColumnAnnotation = JandexHelper.getSingleAnnotation( annotations, JPADotNames.ORDER_COLUMN );
AnnotationInstance indexColumnAnnotation = JandexHelper.getSingleAnnotation( annotations, HibernateDotNames.INDEX_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; this.isIndexed = orderColumnAnnotation != null || indexColumnAnnotation != null;
} }
@ -323,7 +326,7 @@ public class PluralAssociationAttribute extends AssociationAttribute {
if ( jpaWhereAnnotation != null && hibernateWhereAnnotation != null ) { if ( jpaWhereAnnotation != null && hibernateWhereAnnotation != null ) {
throw new AnnotationException( throw new AnnotationException(
"Cannot use sql order by clause (@org.hibernate.annotations.OrderBy) " + "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()
); );
} }

View File

@ -33,7 +33,9 @@ import javax.persistence.JoinTable;
import org.junit.Test; import org.junit.Test;
import org.hibernate.annotations.IndexColumn;
import org.hibernate.jaxb.spi.SourceType; 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.EntityBinding;
import org.hibernate.metamodel.spi.binding.ListBinding; import org.hibernate.metamodel.spi.binding.ListBinding;
import org.hibernate.metamodel.spi.relational.Column; import org.hibernate.metamodel.spi.relational.Column;
@ -140,8 +142,8 @@ public class ElementCollectionBindingTest extends BaseAnnotationBindingTestCase
@Resources(annotatedClasses = TestEntity3.class) @Resources(annotatedClasses = TestEntity3.class)
public void testDefaultJoinTableName() { public void testDefaultJoinTableName() {
EntityBinding entityBinding = getEntityBinding( TestEntity3.class ); EntityBinding entityBinding = getEntityBinding( TestEntity3.class );
ListBinding listBinding = ( ListBinding ) entityBinding.locateAttributeBinding( "strings" ); BagBinding bagBinding = ( BagBinding ) entityBinding.locateAttributeBinding( "strings" );
TableSpecification tableSpec = listBinding.getPluralAttributeKeyBinding().getCollectionTable(); TableSpecification tableSpec = bagBinding.getPluralAttributeKeyBinding().getCollectionTable();
assertEquals( assertEquals(
"Wrong default collection table name", "Wrong default collection table name",
"ElementCollectionBindingTest$TestEntity3_strings", "ElementCollectionBindingTest$TestEntity3_strings",
@ -171,8 +173,8 @@ public class ElementCollectionBindingTest extends BaseAnnotationBindingTestCase
@Resources(annotatedClasses = TestEntity4.class) @Resources(annotatedClasses = TestEntity4.class)
public void testExplicitJoinTableName() { public void testExplicitJoinTableName() {
EntityBinding entityBinding = getEntityBinding( TestEntity4.class ); EntityBinding entityBinding = getEntityBinding( TestEntity4.class );
ListBinding listBinding = ( ListBinding ) entityBinding.locateAttributeBinding( "strings" ); BagBinding bagBinding = ( BagBinding ) entityBinding.locateAttributeBinding( "strings" );
TableSpecification tableSpec = listBinding.getPluralAttributeKeyBinding().getCollectionTable(); TableSpecification tableSpec = bagBinding.getPluralAttributeKeyBinding().getCollectionTable();
assertEquals( assertEquals(
"Wrong default collection table name", "Wrong default collection table name",
"STRING_COLLECTION", "STRING_COLLECTION",
@ -203,8 +205,8 @@ public class ElementCollectionBindingTest extends BaseAnnotationBindingTestCase
@Resources(annotatedClasses = TestEntity5.class) @Resources(annotatedClasses = TestEntity5.class)
public void testJoinColumnAsPartOfCollectionTable() { public void testJoinColumnAsPartOfCollectionTable() {
EntityBinding entityBinding = getEntityBinding( TestEntity5.class ); EntityBinding entityBinding = getEntityBinding( TestEntity5.class );
ListBinding listBinding = ( ListBinding ) entityBinding.locateAttributeBinding( "strings" ); BagBinding bagBinding = ( BagBinding ) entityBinding.locateAttributeBinding( "strings" );
TableSpecification tableSpec = listBinding.getPluralAttributeKeyBinding().getCollectionTable(); TableSpecification tableSpec = bagBinding.getPluralAttributeKeyBinding().getCollectionTable();
Column column = tableSpec.locateColumn( "FOO" ); Column column = tableSpec.locateColumn( "FOO" );
assertNotNull( "The join column should be named FOO", column ); assertNotNull( "The join column should be named FOO", column );
} }
@ -231,8 +233,8 @@ public class ElementCollectionBindingTest extends BaseAnnotationBindingTestCase
@Resources(annotatedClasses = TestEntity6.class) @Resources(annotatedClasses = TestEntity6.class)
public void testElementCollectionWithJoinColumn() { public void testElementCollectionWithJoinColumn() {
EntityBinding entityBinding = getEntityBinding( TestEntity6.class ); EntityBinding entityBinding = getEntityBinding( TestEntity6.class );
ListBinding listBinding = ( ListBinding ) entityBinding.locateAttributeBinding( "strings" ); BagBinding bagBinding = ( BagBinding ) entityBinding.locateAttributeBinding( "strings" );
TableSpecification tableSpec = listBinding.getPluralAttributeKeyBinding().getCollectionTable(); TableSpecification tableSpec = bagBinding.getPluralAttributeKeyBinding().getCollectionTable();
Column column = tableSpec.locateColumn( "FOO" ); Column column = tableSpec.locateColumn( "FOO" );
assertNotNull( "The join column should be named FOO", column ); assertNotNull( "The join column should be named FOO", column );
} }

View File

@ -13,6 +13,7 @@ import javax.persistence.Id;
import javax.persistence.JoinColumn; import javax.persistence.JoinColumn;
import javax.persistence.OneToMany; import javax.persistence.OneToMany;
import org.hibernate.annotations.IndexColumn;
import org.hibernate.annotations.LazyCollection; import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption; import org.hibernate.annotations.LazyCollectionOption;
/** /**
@ -68,6 +69,7 @@ public class EntityWithUnidirectionalOneToMany {
@OneToMany(fetch = FetchType.EAGER) @OneToMany(fetch = FetchType.EAGER)
@JoinColumn(name = "theListOwner", nullable = false) @JoinColumn(name = "theListOwner", nullable = false)
@IndexColumn( name = "list_index")
public List<ReferencedEntity> getTheList() { public List<ReferencedEntity> getTheList() {
return theList; return theList;
} }