HHH-7571 Minimal implementation of @ElementCollection details to pass AnnotationBasicCollectionBindingTests

This commit is contained in:
Hardy Ferentschik 2012-09-05 14:59:35 +02:00
parent fd6cacd6f4
commit d14d18e40b
14 changed files with 247 additions and 109 deletions

View File

@ -28,8 +28,12 @@ package org.hibernate.jaxb.spi.hbm;
*/
public interface TableInformationSource {
public String getSchema();
public String getCatalog();
public String getTable();
public String getSubselect();
public String getSubselectAttribute();
}

View File

@ -2173,8 +2173,7 @@ public class Binder {
}
private PluralAttributeElementBinding.Nature pluralAttributeElementNature(PluralAttributeSource attributeSource) {
return PluralAttributeElementBinding.Nature
.valueOf( attributeSource.getElementSource().getNature().name() );
return PluralAttributeElementBinding.Nature.valueOf( attributeSource.getElementSource().getNature().name() );
}
private PluralAttributeIndexBinding.Nature pluralAttributeIndexNature(PluralAttributeSource attributeSource) {

View File

@ -0,0 +1,70 @@
package org.hibernate.metamodel.internal.source.annotations;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.metamodel.internal.source.annotations.attribute.AssociationAttribute;
import org.hibernate.metamodel.internal.source.annotations.attribute.Column;
import org.hibernate.metamodel.internal.source.annotations.attribute.MappedAttribute;
import org.hibernate.metamodel.spi.source.BasicPluralAttributeElementSource;
import org.hibernate.metamodel.spi.source.ExplicitHibernateTypeSource;
import org.hibernate.metamodel.spi.source.RelationalValueSource;
/**
* @author Hardy Ferentschik
*/
public class BasicPluralAttributeElementSourceImpl implements BasicPluralAttributeElementSource {
private final AssociationAttribute associationAttribute;
public BasicPluralAttributeElementSourceImpl(AssociationAttribute associationAttribute) {
this.associationAttribute = associationAttribute;
}
@Override
public ExplicitHibernateTypeSource getExplicitHibernateTypeSource() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public Nature getNature() {
if ( MappedAttribute.Nature.ELEMENT_COLLECTION_BASIC.equals( associationAttribute.getNature() ) ) {
return Nature.BASIC;
}
else if ( MappedAttribute.Nature.ELEMENT_COLLECTION_EMBEDDABLE.equals( associationAttribute.getNature() ) ) {
return Nature.COMPONENT;
}
else {
throw new AssertionError(
"Wrong attribute nature for a element collection attribute: " + associationAttribute.getNature()
);
}
}
@Override
public List<RelationalValueSource> relationalValueSources() {
List<RelationalValueSource> valueSources = new ArrayList<RelationalValueSource>( );
if ( !associationAttribute.getColumnValues().isEmpty() ) {
for ( Column columnValues : associationAttribute.getColumnValues() ) {
valueSources.add( new ColumnSourceImpl( associationAttribute, null, columnValues ) );
}
}
return valueSources;
}
@Override
public boolean areValuesIncludedInInsertByDefault() {
return true;
}
@Override
public boolean areValuesIncludedInUpdateByDefault() {
return true;
}
@Override
public boolean areValuesNullableByDefault() {
return true;
}
}

View File

@ -242,6 +242,12 @@ public class EntitySourceImpl implements EntitySource {
:new PluralAttributeSourceImpl( ( PluralAssociationAttribute ) associationAttribute );
attributeList.add( source );
break;
case ELEMENT_COLLECTION_BASIC:
case ELEMENT_COLLECTION_EMBEDDABLE: {
source = new PluralAttributeSourceImpl( ( PluralAssociationAttribute ) associationAttribute );
attributeList.add( source );
break;
}
default: {
throw new NotYetImplementedException();
}

View File

@ -0,0 +1,28 @@
package org.hibernate.metamodel.internal.source.annotations;
import org.hibernate.engine.spi.CascadeStyle;
import org.hibernate.metamodel.internal.source.annotations.attribute.PluralAssociationAttribute;
import org.hibernate.metamodel.internal.source.annotations.util.EnumConversionHelper;
import org.hibernate.metamodel.spi.source.ManyToAnyPluralAttributeElementSource;
/**
* @author Hardy Ferentschik
*/
public class ManyToAnyPluralAttributeElementSourceImpl implements ManyToAnyPluralAttributeElementSource {
private final PluralAssociationAttribute attribute;
public ManyToAnyPluralAttributeElementSourceImpl(PluralAssociationAttribute attribute) {
this.attribute = attribute;
}
@Override
public Iterable<CascadeStyle> getCascadeStyles() {
return EnumConversionHelper.cascadeTypeToCascadeStyleSet( attribute.getCascadeTypes(), attribute.getContext() );
}
@Override
public Nature getNature() {
return Nature.MANY_TO_ANY;
}
}

View File

@ -0,0 +1,62 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.metamodel.internal.source.annotations;
import org.hibernate.engine.spi.CascadeStyle;
import org.hibernate.metamodel.internal.source.annotations.attribute.PluralAssociationAttribute;
import org.hibernate.metamodel.internal.source.annotations.util.EnumConversionHelper;
import org.hibernate.metamodel.spi.source.OneToManyPluralAttributeElementSource;
/**
* @author Hardy Ferentschik
*/
public class OneToManyAttributeElementSourceImpl implements OneToManyPluralAttributeElementSource {
private final PluralAssociationAttribute attribute;
public OneToManyAttributeElementSourceImpl(PluralAssociationAttribute attribute) {
this.attribute = attribute;
}
@Override
public String getReferencedEntityName() {
return attribute.getReferencedEntityType();
}
@Override
public boolean isNotFoundAnException() {
return !attribute.isIgnoreNotFound();
}
@Override
public Iterable<CascadeStyle> getCascadeStyles() {
return EnumConversionHelper.cascadeTypeToCascadeStyleSet( attribute.getCascadeTypes(), attribute.getContext() );
}
@Override
public Nature getNature() {
return Nature.ONE_TO_MANY;
}
}

View File

@ -115,16 +115,15 @@ public class PluralAttributeKeySourceImpl implements PluralAttributeKeySource {
public JoinColumnResolutionDelegateImpl(PluralAssociationAttribute attribute) {
this.attribute = attribute;
}
@Override
public List<Value> getJoinColumns(JoinColumnResolutionContext context) {
List<Column> joinClumnValues = attribute.getJoinColumnValues();
if ( joinClumnValues.isEmpty() ) {
List<Column> joinColumnValues = attribute.getJoinColumnValues();
if ( joinColumnValues.isEmpty() ) {
return null;
}
List<Value> result = new ArrayList<Value>( joinClumnValues.size() );
List<Value> result = new ArrayList<Value>( joinColumnValues.size() );
for ( Column column : attribute.getJoinColumnValues() ) {
result.add( context.resolveColumn( column.getReferencedColumnName(), null, null, null ) );
}

View File

@ -27,26 +27,22 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.persistence.CascadeType;
import org.hibernate.FetchMode;
import org.hibernate.engine.FetchStyle;
import org.hibernate.engine.FetchTiming;
import org.hibernate.engine.spi.CascadeStyle;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.metamodel.internal.source.annotations.attribute.PluralAssociationAttribute;
import org.hibernate.metamodel.internal.source.annotations.util.EnumConversionHelper;
import org.hibernate.metamodel.spi.binding.Caching;
import org.hibernate.metamodel.spi.binding.CustomSQL;
import org.hibernate.metamodel.spi.source.ExplicitHibernateTypeSource;
import org.hibernate.metamodel.spi.source.ManyToAnyPluralAttributeElementSource;
import org.hibernate.metamodel.spi.source.MetaAttributeSource;
import org.hibernate.metamodel.spi.source.OneToManyPluralAttributeElementSource;
import org.hibernate.metamodel.spi.source.Orderable;
import org.hibernate.metamodel.spi.source.PluralAttributeElementSource;
import org.hibernate.metamodel.spi.source.PluralAttributeKeySource;
import org.hibernate.metamodel.spi.source.PluralAttributeSource;
import org.hibernate.metamodel.spi.source.Sortable;
import org.hibernate.metamodel.spi.source.TableSource;
import org.hibernate.metamodel.spi.source.TableSpecificationSource;
/**
@ -78,21 +74,6 @@ public class PluralAttributeSourceImpl implements PluralAttributeSource, Orderab
};
}
private Nature resolveAttributeNature() {
if ( Map.class.isAssignableFrom( attribute.getAttributeType() ) ) {
return PluralAttributeSource.Nature.MAP;
}
else if ( List.class.isAssignableFrom( attribute.getAttributeType() ) ) {
return PluralAttributeSource.Nature.LIST;
}
else if ( Set.class.isAssignableFrom( attribute.getAttributeType() ) ) {
return PluralAttributeSource.Nature.SET;
}
else {
return PluralAttributeSource.Nature.BAG;
}
}
@Override
public Nature getNature() {
return nature;
@ -103,7 +84,7 @@ public class PluralAttributeSourceImpl implements PluralAttributeSource, Orderab
return elementSource;
}
private PluralAttributeElementSource determineElementSource (){
private PluralAttributeElementSource determineElementSource() {
switch ( attribute.getNature() ) {
case MANY_TO_MANY:
return new ManyToManyPluralAttributeElementSourceImpl( attribute );
@ -111,6 +92,10 @@ public class PluralAttributeSourceImpl implements PluralAttributeSource, Orderab
return new ManyToAnyPluralAttributeElementSourceImpl( attribute );
case ONE_TO_MANY:
return new OneToManyPluralAttributeElementSourceImpl( attribute );
case ELEMENT_COLLECTION_BASIC:
case ELEMENT_COLLECTION_EMBEDDABLE: {
return new BasicPluralAttributeElementSourceImpl( attribute );
}
}
throw new AssertionError( "unexpected attribute nature" );
}
@ -122,8 +107,24 @@ public class PluralAttributeSourceImpl implements PluralAttributeSource, Orderab
@Override
public TableSpecificationSource getCollectionTableSpecificationSource() {
// todo see org.hibernate.metamodel.internal.Binder#bindOneToManyCollectionKey
return null;
// todo - see org.hibernate.metamodel.internal.Binder#bindOneToManyCollectionKey
// todo - needs to cater for @CollectionTable and @JoinTable
return new TableSource() {
@Override
public String getExplicitSchemaName() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public String getExplicitCatalogName() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public String getExplicitTableName() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
};
}
@Override
@ -252,55 +253,19 @@ public class PluralAttributeSourceImpl implements PluralAttributeSource, Orderab
public FetchStyle getFetchStyle() {
return attribute.getFetchStyle();
}
public Iterable<CascadeStyle> interpretCascadeStyles(Set<CascadeType> cascadeTypes) {
return EnumConversionHelper.cascadeTypeToCascadeStyleSet( cascadeTypes, attribute.getContext() );
}
private class OneToManyPluralAttributeElementSourceImpl implements OneToManyPluralAttributeElementSource {
private final PluralAssociationAttribute attribute;
private OneToManyPluralAttributeElementSourceImpl(PluralAssociationAttribute attribute) {
this.attribute = attribute;
private Nature resolveAttributeNature() {
if ( Map.class.isAssignableFrom( attribute.getAttributeType() ) ) {
return PluralAttributeSource.Nature.MAP;
}
@Override
public String getReferencedEntityName() {
return attribute.getReferencedEntityType();
else if ( List.class.isAssignableFrom( attribute.getAttributeType() ) ) {
return PluralAttributeSource.Nature.LIST;
}
@Override
public boolean isNotFoundAnException() {
return !attribute.isIgnoreNotFound();
else if ( Set.class.isAssignableFrom( attribute.getAttributeType() ) ) {
return PluralAttributeSource.Nature.SET;
}
@Override
public Iterable<CascadeStyle> getCascadeStyles() {
return interpretCascadeStyles( attribute.getCascadeTypes() );
}
@Override
public Nature getNature() {
return Nature.ONE_TO_MANY;
}
}
private class ManyToAnyPluralAttributeElementSourceImpl implements ManyToAnyPluralAttributeElementSource {
private final PluralAssociationAttribute attribute;
private ManyToAnyPluralAttributeElementSourceImpl(PluralAssociationAttribute attribute) {
this.attribute = attribute;
}
@Override
public Iterable<CascadeStyle> getCascadeStyles() {
return interpretCascadeStyles( attribute.getCascadeTypes() );
}
@Override
public Nature getNature() {
return Nature.MANY_TO_ANY;
else {
return PluralAttributeSource.Nature.BAG;
}
}
}

View File

@ -75,9 +75,9 @@ public abstract class MappedAttribute implements Comparable<MappedAttribute> {
* Defines the column values (relational values) for this property. A mapped property can refer to multiple
* column values in case of components or join columns etc
*/
private List<Column> columnValues = new ArrayList<Column>( );
private List<Column> columnValues = new ArrayList<Column>();
private List<Column> joinColumnValues = new ArrayList<Column>( );
private List<Column> joinColumnValues = new ArrayList<Column>();
/**
* Is this property an id property (or part thereof).
@ -86,7 +86,7 @@ public abstract class MappedAttribute implements Comparable<MappedAttribute> {
/**
* Is this property a natural id property and what's the mutability it is.
*/
*/
private SingularAttributeBinding.NaturalIdMutability naturalIdMutability;
/**
@ -154,7 +154,7 @@ public abstract class MappedAttribute implements Comparable<MappedAttribute> {
return columnValues;
}
public List<Column> getJoinColumnValues(){
public List<Column> getJoinColumnValues() {
return joinColumnValues;
}
@ -229,7 +229,8 @@ public abstract class MappedAttribute implements Comparable<MappedAttribute> {
if ( naturalIdAnnotation == null ) {
return SingularAttributeBinding.NaturalIdMutability.NOT_NATURAL_ID;
}
final boolean mutable = naturalIdAnnotation.value("mutable") == null ? false : naturalIdAnnotation.value( "mutable" ).asBoolean();
final boolean mutable = naturalIdAnnotation.value( "mutable" ) == null ? false :
naturalIdAnnotation.value("mutable").asBoolean();
return mutable ? SingularAttributeBinding.NaturalIdMutability.MUTABLE : SingularAttributeBinding.NaturalIdMutability.IMMUTABLE;
}
@ -240,8 +241,11 @@ public abstract class MappedAttribute implements Comparable<MappedAttribute> {
JPADotNames.COLUMN
);
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 );
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
);
}
columnValues.add( new Column( columnAnnotation ) );
}
@ -261,8 +265,11 @@ public abstract class MappedAttribute implements Comparable<MappedAttribute> {
HibernateDotNames.COLUMNS
);
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 );
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
);
}
List<AnnotationInstance> columnsList = Arrays.asList(
JandexHelper.getValue( columnsAnnotation, "value", AnnotationInstance[].class )
@ -295,10 +302,9 @@ public abstract class MappedAttribute implements Comparable<MappedAttribute> {
}
return checkCondition;
}
/**
* An enum defining the type of a mapped attribute.
*
* @author Hardy Ferentschik
*/
public static enum Nature {
BASIC( JPADotNames.BASIC ),
@ -321,12 +327,6 @@ public abstract class MappedAttribute implements Comparable<MappedAttribute> {
public DotName getAnnotationDotName() {
return annotationDotName;
}
@Override
public String toString() {
return "Nature{" +annotationDotName.toString()+
'}';
}
}
}

View File

@ -54,7 +54,6 @@ import org.hibernate.AnnotationException;
import org.hibernate.AssertionFailure;
import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
import org.hibernate.cfg.NotYetImplementedException;
import org.hibernate.metamodel.internal.source.annotations.AnnotationBindingContext;
import org.hibernate.metamodel.internal.source.annotations.attribute.AssociationAttribute;
import org.hibernate.metamodel.internal.source.annotations.attribute.AttributeOverride;
@ -461,10 +460,6 @@ public class ConfiguredClass {
}
break;
}
case ELEMENT_COLLECTION_BASIC:
case ELEMENT_COLLECTION_EMBEDDABLE: {
throw new NotYetImplementedException( "Element collections must still be implemented." );
}
case EMBEDDED_ID: {
final BasicAttribute attribute = BasicAttribute.createSimpleAttribute(
attributeName,
@ -490,7 +485,6 @@ public class ConfiguredClass {
resolveEmbeddable( attributeName, attributeType, annotations );
break;
}
// OneToOne, OneToMany, ManyToOne, ManyToMany
case ONE_TO_ONE:
case MANY_TO_ONE: {
final AssociationAttribute attribute = AssociationAttribute.createAssociationAttribute(
@ -504,6 +498,8 @@ public class ConfiguredClass {
associationAttributeMap.put( attributeName, attribute );
break;
}
case ELEMENT_COLLECTION_BASIC:
case ELEMENT_COLLECTION_EMBEDDABLE:
case ONE_TO_MANY:
case MANY_TO_MANY: {
AssociationAttribute attribute = PluralAssociationAttribute.createPluralAssociationAttribute(
@ -609,12 +605,13 @@ public class ConfiguredClass {
JPADotNames.ELEMENT_COLLECTION
);
if ( elementCollection != null ) {
// class info can be null for types like string, etc where there are no annotations
ClassInfo classInfo = getLocalBindingContext().getIndex().getClassByName(
DotName.createSimple(
referencedCollectionType.getName()
)
);
if ( classInfo.annotations().get( JPADotNames.EMBEDDABLE ) != null ) {
if ( classInfo != null && classInfo.annotations().get( JPADotNames.EMBEDDABLE ) != null ) {
discoveredAttributeTypes.put( MappedAttribute.Nature.ELEMENT_COLLECTION_EMBEDDABLE, elementCollection );
}
else {

View File

@ -54,12 +54,10 @@ public class OneToManyBindingTest extends BaseAnnotationBindingTestCase {
EntityBinding teamBinding = getEntityBinding( Team.class );
assertNotNull( teamBinding );
attributeBinding = teamBinding.locateAttributeBinding( "players" );
attributeBinding = teamBinding.locateAttributeBinding( "players" );
assertTrue( attributeBinding.isAssociation() );
typeDescriptor = attributeBinding.getHibernateTypeDescriptor();
PluralAttributeBinding pluralAttributeBinding = PluralAttributeBinding.class.cast( attributeBinding );
}
}

View File

@ -92,7 +92,7 @@ public abstract class AbstractBasicCollectionBindingTests extends BaseUnitTestCa
// TODO: this will fail until HHH-7121 is fixed
//assertTrue( entityBinding.getPrimaryTable().locateColumn( "`name`" ).isUnique() );
checkResult(
assertBasicCollectionBinding(
entityBinding,
metadata.getCollection( EntityWithBasicCollections.class.getName() + ".theBag" ),
BagType.class,
@ -105,7 +105,7 @@ public abstract class AbstractBasicCollectionBindingTests extends BaseUnitTestCa
true
);
checkResult(
assertBasicCollectionBinding(
entityBinding,
metadata.getCollection( EntityWithBasicCollections.class.getName() + ".theSet" ),
SetType.class,
@ -118,13 +118,13 @@ public abstract class AbstractBasicCollectionBindingTests extends BaseUnitTestCa
true
);
checkResult(
assertBasicCollectionBinding(
entityBinding,
metadata.getCollection( EntityWithBasicCollections.class.getName() + ".thePropertyRefSet" ),
SetType.class,
Set.class,
Integer.class,
(SingularAttributeBinding ) entityBinding.locateAttributeBinding( "name" ),
( SingularAttributeBinding ) entityBinding.locateAttributeBinding( "name" ),
Identifier.toIdentifier( "EntityWithBasicCollections_thePropertyRefSet" ),
Identifier.toIdentifier( "pid" ),
FetchTiming.DELAYED,
@ -132,7 +132,7 @@ public abstract class AbstractBasicCollectionBindingTests extends BaseUnitTestCa
);
}
private <X extends CollectionType> void checkResult(
private <X extends CollectionType> void assertBasicCollectionBinding(
EntityBinding collectionOwnerBinding,
PluralAttributeBinding collectionBinding,
Class<X> expectedCollectionTypeClass,

View File

@ -26,7 +26,6 @@ package org.hibernate.metamodel.spi.binding.basiccollections;
import org.junit.Test;
import org.hibernate.metamodel.MetadataSources;
import org.hibernate.testing.FailureExpectedWithNewMetamodel;
/**
* @author Hardy Ferentschik
@ -37,7 +36,6 @@ public class AnnotationBasicCollectionBindingTests extends AbstractBasicCollecti
}
@Test
@FailureExpectedWithNewMetamodel
public void testBasicCollections() {
super.testBasicCollections();
}

View File

@ -30,9 +30,15 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;
/**
* @author Gail Badner
@ -64,6 +70,7 @@ public class EntityWithBasicCollections {
this.id = id;
}
@Column(unique = true)
public String getName() {
return name;
}
@ -72,7 +79,8 @@ public class EntityWithBasicCollections {
this.name = name;
}
@ElementCollection
@ElementCollection(fetch = FetchType.EAGER)
@JoinColumn(name = "owner_id")
public Collection<String> getTheBag() {
return theBag;
}
@ -82,6 +90,8 @@ public class EntityWithBasicCollections {
}
@ElementCollection
@LazyCollection(value = LazyCollectionOption.EXTRA)
@JoinColumn(name = "pid")
public Set<String> getTheSet() {
return theSet;
}
@ -91,6 +101,8 @@ public class EntityWithBasicCollections {
}
@ElementCollection
@JoinColumn(name = "pid", referencedColumnName = "name")
@Column(name="property_ref_set_stuff", nullable = false)
public Set<Integer> getThePropertyRefSet() {
return thePropertyRefSet;
}