HHH-7909: Non-basic map keys and index backrefs

This commit is contained in:
Gail Badner 2013-01-10 09:37:41 -08:00
parent 029badbba6
commit bf5fabd64a
16 changed files with 415 additions and 70 deletions

View File

@ -25,19 +25,39 @@ package org.hibernate.engine.spi;
/**
* @author Steve Ebersole
* @author Gail Badner
*/
public class SyntheticAttributeHelper {
public static final String SYNTHETIC_COMPOSITE_ID_ATTRIBUTE_NAME = "_identifierMapper";
private static final String BACKREF_ATTRIBUTE_NAME_PREFIX = "_";
private static final String BACKREF_ATTRIBUTE_NAME_SUFFIX = "BackRef";
private static final String INDEX_BACKREF_ATTRIBUTE_NAME_SUFFIX = "IndexBackRef";
public static String createBackRefAttributeName(String pluralAttributeRole) {
return createSyntheticAttributeName(
pluralAttributeRole,
BACKREF_ATTRIBUTE_NAME_PREFIX,
BACKREF_ATTRIBUTE_NAME_SUFFIX
);
}
public static String createIndexBackRefAttributeName(String pluralAttributeRole) {
return createSyntheticAttributeName(
pluralAttributeRole,
BACKREF_ATTRIBUTE_NAME_PREFIX,
INDEX_BACKREF_ATTRIBUTE_NAME_SUFFIX
);
}
private static String createSyntheticAttributeName(String attributeRole, String prefix, String suffix) {
return new StringBuilder(
BACKREF_ATTRIBUTE_NAME_PREFIX.length() + pluralAttributeRole.length() + BACKREF_ATTRIBUTE_NAME_SUFFIX.length() )
.append( BACKREF_ATTRIBUTE_NAME_PREFIX )
.append( pluralAttributeRole )
.append( BACKREF_ATTRIBUTE_NAME_SUFFIX )
prefix.length() + attributeRole.length() + suffix.length() )
.append( prefix )
.append( attributeRole )
.append( suffix )
.toString();
}
}

View File

@ -51,6 +51,7 @@ import org.hibernate.metamodel.spi.binding.CompositeAttributeBinding;
import org.hibernate.metamodel.spi.binding.AttributeBinding;
import org.hibernate.metamodel.spi.binding.CompositeAttributeBindingContainer;
import org.hibernate.metamodel.spi.binding.CompositePluralAttributeElementBinding;
import org.hibernate.metamodel.spi.binding.CompositePluralAttributeIndexBinding;
import org.hibernate.metamodel.spi.binding.IndexedPluralAttributeBinding;
import org.hibernate.metamodel.spi.binding.MapBinding;
import org.hibernate.metamodel.spi.binding.PluralAttributeBinding;
@ -337,15 +338,13 @@ public class AttributeBuilder {
return getEntityAttributeMetaModelType( attributeTypeDescriptor );
}
case EMBEDDABLE: {
// TODO: Need to implement CompositePluralAttributeIndexBinding
// final MapBinding mapBinding = (MapBinding) attributeBinding;
// final CompositePluralAttributeIndexBinding pluralAttributeIndexBinding =
// (CompositePluralAttributeIndexBinding) mapBinding.getPluralAttributeIndexBinding();
// return getEmbeddableAttributeMetaModelType(
// attributeTypeDescriptor,
// pluralAttributeIndexBinding.getCompositeAttributeBindingContainer();
//);
throw new NotYetImplementedException( "Composite map indexes are not implemented yet." );
final MapBinding mapBinding = (MapBinding) attributeBinding;
final CompositePluralAttributeIndexBinding pluralAttributeIndexBinding =
(CompositePluralAttributeIndexBinding) mapBinding.getPluralAttributeIndexBinding();
return getEmbeddableAttributeMetaModelType(
attributeTypeDescriptor,
pluralAttributeIndexBinding.getCompositeAttributeBindingContainer()
);
}
default: {
throw new AssertionFailure( "Unknown type : " + attributeTypeDescriptor.getValueClassification() );

View File

@ -31,6 +31,7 @@ import javax.persistence.metamodel.PluralAttribute;
import org.hibernate.annotations.common.AssertionFailure;
import org.hibernate.jpa.metamodel.internal.AbstractManagedType;
import org.hibernate.metamodel.spi.binding.IndexedPluralAttributeBinding;
import org.hibernate.metamodel.spi.binding.PluralAttributeBinding;
/**
@ -111,7 +112,7 @@ public class PluralAttributeMetadataImpl<X,Y,E>
this.keyAttributeTypeDescriptor = new AttributeTypeDescriptor() {
@Override
public org.hibernate.type.Type getHibernateType() {
return getAttributeBinding().getPluralAttributeKeyBinding()
return ( (IndexedPluralAttributeBinding) getAttributeBinding() ).getPluralAttributeIndexBinding()
.getHibernateTypeDescriptor()
.getResolvedTypeMapping();
}

View File

@ -72,6 +72,7 @@ import org.hibernate.metamodel.spi.binding.Cascadeable;
import org.hibernate.metamodel.spi.binding.CompositeAttributeBinding;
import org.hibernate.metamodel.spi.binding.CompositeAttributeBindingContainer;
import org.hibernate.metamodel.spi.binding.CompositePluralAttributeElementBinding;
import org.hibernate.metamodel.spi.binding.CompositePluralAttributeIndexBinding;
import org.hibernate.metamodel.spi.binding.EntityBinding;
import org.hibernate.metamodel.spi.binding.EntityDiscriminator;
import org.hibernate.metamodel.spi.binding.EntityIdentifier;
@ -99,6 +100,7 @@ import org.hibernate.metamodel.spi.binding.SingularNonAssociationAttributeBindin
import org.hibernate.metamodel.spi.domain.Aggregate;
import org.hibernate.metamodel.spi.domain.Attribute;
import org.hibernate.metamodel.spi.domain.Entity;
import org.hibernate.metamodel.spi.domain.IndexedPluralAttribute;
import org.hibernate.metamodel.spi.domain.PluralAttribute;
import org.hibernate.metamodel.spi.domain.SingularAttribute;
import org.hibernate.metamodel.spi.relational.Column;
@ -119,6 +121,7 @@ import org.hibernate.metamodel.spi.source.BasicPluralAttributeIndexSource;
import org.hibernate.metamodel.spi.source.ColumnSource;
import org.hibernate.metamodel.spi.source.ComponentAttributeSource;
import org.hibernate.metamodel.spi.source.CompositePluralAttributeElementSource;
import org.hibernate.metamodel.spi.source.CompositePluralAttributeIndexSource;
import org.hibernate.metamodel.spi.source.ConstraintSource;
import org.hibernate.metamodel.spi.source.DerivedValueSource;
import org.hibernate.metamodel.spi.source.DiscriminatorSource;
@ -1555,9 +1558,11 @@ public class Binder {
final String defaultElementJavaTypeName) {
bindBasicPluralElementRelationalValues( elementSource, elementBinding );
typeHelper.bindBasicCollectionElementType( elementBinding, elementSource, defaultElementJavaTypeName );
elementBinding.getPluralAttributeBinding().getAttribute().setElementType(
bindingContext().makeJavaType( elementBinding.getHibernateTypeDescriptor().getJavaTypeName() )
);
}
private void bindNonAssociationCollectionKey(
final AbstractPluralAttributeBinding attributeBinding,
final PluralAttributeSource attributeSource) {
@ -1633,6 +1638,7 @@ public class Binder {
);
bindAttributes( compositeAttributeBindingContainer, elementSource );
pluralAttributeBinding.getAttribute().setElementType( aggregate );
Type resolvedType = metadata.getTypeResolver().getTypeFactory().component(
new ComponentMetamodel( compositeAttributeBindingContainer, false, false )
);
@ -1679,16 +1685,6 @@ public class Binder {
.getNature() != PluralAttributeElementBinding.Nature.ONE_TO_MANY
)
);
if ( attributeBinding.getPluralAttributeElementBinding()
.getNature() == PluralAttributeElementBinding.Nature.ONE_TO_MANY ) {
for ( RelationalValueBinding relationalValueBinding : indexBinding.getRelationalValueBindings() ) {
if ( Column.class.isInstance( relationalValueBinding.getValue() ) ) {
// TODO: fix this when column nullability is refactored
Column column = (Column) relationalValueBinding.getValue();
column.setNullable( true );
}
}
}
// TODO: create a foreign key if non-inverse and the index is an association
typeHelper.bindHibernateTypeDescriptor(
@ -1700,6 +1696,65 @@ public class Binder {
indexBinding.getHibernateTypeDescriptor().getResolvedTypeMapping(),
indexBinding.getRelationalValueBindings()
);
IndexedPluralAttribute indexedPluralAttribute =
(IndexedPluralAttribute) indexBinding.getIndexedPluralAttributeBinding().getAttribute();
indexedPluralAttribute.setIndexType(
bindingContext().makeJavaType( indexBinding.getHibernateTypeDescriptor().getJavaTypeName() )
);
}
private void bindCompositeCollectionIndex(
final CompositePluralAttributeIndexBinding indexBinding,
final CompositePluralAttributeIndexSource indexSource,
final String defaultIndexJavaTypeName) {
final PluralAttributeBinding pluralAttributeBinding = indexBinding.getIndexedPluralAttributeBinding();
ValueHolder<Class<?>> defaultElementJavaClassReference = null;
// Create the aggregate type
// TODO: aggregateName should be set to elementSource.getPath() (which is currently not implemented)
// or Binder should define AttributeBindingContainer paths instead.
String aggregateName = pluralAttributeBinding.getAttribute().getRole() + ".index";
final Aggregate aggregate;
if ( indexSource.getClassName() != null ) {
aggregate = new Aggregate(
aggregateName,
indexSource.getClassName(),
indexSource.getClassReference() != null ?
indexSource.getClassReference() :
bindingContext().makeClassReference( indexSource.getClassName() ),
null
);
}
else {
defaultElementJavaClassReference = bindingContext().makeClassReference( defaultIndexJavaTypeName );
aggregate = new Aggregate(
aggregateName,
defaultElementJavaClassReference.getValue().getName(),
defaultElementJavaClassReference,
null
);
}
final CompositeAttributeBindingContainer compositeAttributeBindingContainer =
indexBinding.createCompositeAttributeBindingContainer(
aggregate,
null,
null
);
bindAttributes( compositeAttributeBindingContainer, indexSource );
Type resolvedType = metadata.getTypeResolver().getTypeFactory().component(
new ComponentMetamodel( compositeAttributeBindingContainer, false, false )
);
// TODO: binding the HibernateTypeDescriptor should be simplified since we know the class name already
typeHelper.bindHibernateTypeDescriptor(
indexBinding.getHibernateTypeDescriptor(),
aggregate.getClassName(),
null,
defaultElementJavaClassReference == null ? null : defaultElementJavaClassReference.getValue().getName(),
resolvedType
);
IndexedPluralAttribute indexedPluralAttribute =
(IndexedPluralAttribute) indexBinding.getIndexedPluralAttributeBinding().getAttribute();
indexedPluralAttribute.setIndexType( aggregate );
}
private SingularAttributeBinding determineReferencedAttributeBinding(
@ -1728,7 +1783,6 @@ public class Binder {
referencedEntityBinding.getHierarchyDetails().getEntityIdentifier()
);
Type resolvedElementType = metadata.getTypeResolver().getTypeFactory().manyToOne(
referencedEntityBinding.getEntity().getName(),
null,
@ -1747,6 +1801,7 @@ public class Binder {
);
// no need to bind JDBC data types because element is referenced EntityBinding's ID
elementBinding.setCascadeStyle( determineCascadeStyle( elementSource.getCascadeStyles() ) );
elementBinding.getPluralAttributeBinding().getAttribute().setElementType( referencedEntityBinding.getEntity() );
}
private void bindManyToManyCollectionElement(
@ -1774,13 +1829,13 @@ public class Binder {
);
}
typeHelper.bindManyToManyAttributeType(
elementBinding,
elementSource,
referencedEntityBinding,
defaultElementJavaTypeName
);
elementBinding.getPluralAttributeBinding().getAttribute().setElementType( referencedEntityBinding.getEntity() );
elementBinding.setCascadeStyle( determineCascadeStyle( elementSource.getCascadeStyles() ) );
elementBinding.setManyToManyWhere( elementSource.getWhere() );
elementBinding.setManyToManyOrderBy( elementSource.getOrderBy() );
@ -1882,12 +1937,22 @@ public class Binder {
final IndexedPluralAttributeSource attributeSource,
final IndexedPluralAttributeBinding attributeBinding,
final ReflectedCollectionJavaTypes reflectedCollectionJavaTypes) {
final String defaultCollectionIndexJavaTypeName =
HibernateTypeHelper.defaultCollectionIndexJavaTypeName( reflectedCollectionJavaTypes );
switch ( attributeSource.getIndexSource().getNature() ) {
case BASIC: {
bindBasicCollectionIndex(
attributeBinding,
(BasicPluralAttributeIndexSource) attributeSource.getIndexSource(),
HibernateTypeHelper.defaultCollectionIndexJavaTypeName( reflectedCollectionJavaTypes )
defaultCollectionIndexJavaTypeName
);
break;
}
case AGGREGATE: {
bindCompositeCollectionIndex(
(CompositePluralAttributeIndexBinding) attributeBinding.getPluralAttributeIndexBinding(),
(CompositePluralAttributeIndexSource) attributeSource.getIndexSource(),
defaultCollectionIndexJavaTypeName
);
break;
}
@ -1900,6 +1965,16 @@ public class Binder {
);
}
}
if ( attributeBinding.getPluralAttributeElementBinding()
.getNature() == PluralAttributeElementBinding.Nature.ONE_TO_MANY ) {
for ( RelationalValueBinding relationalValueBinding : attributeBinding.getPluralAttributeIndexBinding().getRelationalValueBindings() ) {
if ( Column.class.isInstance( relationalValueBinding.getValue() ) ) {
// TODO: fix this when column nullability is refactored
Column column = (Column) relationalValueBinding.getValue();
column.setNullable( true );
}
}
}
}
private void bindPluralAggregateAttribute(
@ -2258,15 +2333,12 @@ public class Binder {
foreignKey.setDeleteRule( keySource.getOnDeleteAction() );
keyBinding.setForeignKey( foreignKey );
final HibernateTypeDescriptor pluralAttributeKeyTypeDescriptor = keyBinding.getHibernateTypeDescriptor();
final HibernateTypeDescriptor referencedTypeDescriptor =
keyBinding.getReferencedAttributeBinding().getHibernateTypeDescriptor();
pluralAttributeKeyTypeDescriptor.setExplicitTypeName( referencedTypeDescriptor.getExplicitTypeName() );
pluralAttributeKeyTypeDescriptor.setJavaTypeName( referencedTypeDescriptor.getJavaTypeName() );
// TODO: not sure about the following...
pluralAttributeKeyTypeDescriptor.setToOne( referencedTypeDescriptor.isToOne() );
pluralAttributeKeyTypeDescriptor.getTypeParameters().putAll( referencedTypeDescriptor.getTypeParameters() );
final Type resolvedKeyType = referencedTypeDescriptor.getResolvedTypeMapping();
pluralAttributeKeyTypeDescriptor.setResolvedTypeMapping( resolvedKeyType );
;
pluralAttributeKeyTypeDescriptor.copyFrom(
keyBinding.getReferencedAttributeBinding()
.getHibernateTypeDescriptor()
);
final Type resolvedKeyType = pluralAttributeKeyTypeDescriptor.getResolvedTypeMapping();
Iterator<Column> fkColumnIterator = keyBinding.getForeignKey().getSourceColumns().iterator();
if ( resolvedKeyType.isComponentType() ) {

View File

@ -66,9 +66,11 @@ import org.hibernate.metamodel.spi.binding.EntityBinding;
import org.hibernate.metamodel.spi.binding.FetchProfile;
import org.hibernate.metamodel.spi.binding.HibernateTypeDescriptor;
import org.hibernate.metamodel.spi.binding.IdGenerator;
import org.hibernate.metamodel.spi.binding.IndexedPluralAttributeBinding;
import org.hibernate.metamodel.spi.binding.ManyToOneAttributeBinding;
import org.hibernate.metamodel.spi.binding.PluralAttributeBinding;
import org.hibernate.metamodel.spi.binding.PluralAttributeElementBinding;
import org.hibernate.metamodel.spi.binding.PluralAttributeIndexBinding;
import org.hibernate.metamodel.spi.binding.PluralAttributeKeyBinding;
import org.hibernate.metamodel.spi.binding.RelationalValueBinding;
import org.hibernate.metamodel.spi.binding.TypeDefinition;
@ -423,17 +425,28 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
referencedEntityBinding.getEntity().createSyntheticSingularAttribute(
SyntheticAttributeHelper.createBackRefAttributeName( pluralAttributeBinding.getAttribute().getRole() ) );
// Create the back reference attribute binding.
BackRefAttributeBinding backRefAttributeBinding =
referencedEntityBinding.makeBackRefAttributeBinding( syntheticAttribute, pluralAttributeBinding );
final HibernateTypeDescriptor keyTypeDescriptor = keyBinding.getHibernateTypeDescriptor();
final HibernateTypeDescriptor hibernateTypeDescriptor = backRefAttributeBinding.getHibernateTypeDescriptor();
hibernateTypeDescriptor.setJavaTypeName( keyTypeDescriptor.getJavaTypeName() );
hibernateTypeDescriptor.setExplicitTypeName( keyTypeDescriptor.getExplicitTypeName() );
hibernateTypeDescriptor.setToOne( keyTypeDescriptor.isToOne() );
hibernateTypeDescriptor.getTypeParameters().putAll( keyTypeDescriptor.getTypeParameters() );
hibernateTypeDescriptor.setResolvedTypeMapping( keyTypeDescriptor.getResolvedTypeMapping() );
BackRefAttributeBinding backRefAttributeBinding = referencedEntityBinding.makeBackRefAttributeBinding(
syntheticAttribute, pluralAttributeBinding, false
);
backRefAttributeBinding.getHibernateTypeDescriptor().copyFrom( keyBinding.getHibernateTypeDescriptor() );
backRefAttributeBinding.getAttribute().resolveType(
keyBinding.getReferencedAttributeBinding().getAttribute().getSingularAttributeType() );
if ( pluralAttributeBinding.hasIndex() ) {
SingularAttribute syntheticIndexAttribute =
referencedEntityBinding.getEntity().createSyntheticSingularAttribute(
SyntheticAttributeHelper.createIndexBackRefAttributeName( pluralAttributeBinding.getAttribute().getRole() ) );
BackRefAttributeBinding indexBackRefAttributeBinding = referencedEntityBinding.makeBackRefAttributeBinding(
syntheticIndexAttribute, pluralAttributeBinding, true
);
final PluralAttributeIndexBinding indexBinding =
( (IndexedPluralAttributeBinding) pluralAttributeBinding ).getPluralAttributeIndexBinding();
indexBackRefAttributeBinding.getHibernateTypeDescriptor().copyFrom(
indexBinding.getHibernateTypeDescriptor()
);
indexBackRefAttributeBinding.getAttribute().resolveType(
indexBinding.getPluralAttributeIndexType()
);
}
}
for ( MetadataSourceProcessor metadataSourceProcessor : metadataSourceProcessors ) {

View File

@ -142,7 +142,7 @@ public abstract class AbstractComponentAttributeSourceImpl extends AbstractHbmSo
}
// todo duplicated with org.hibernate.metamodel.internal.source.hbm.AbstractEntitySourceImpl
protected AttributeSource buildAttributeSource(JaxbMapElement attributeElement){
return new MapSource(
return new MapSourceImpl(
sourceMappingDocument(),
attributeElement,
parentContainer

View File

@ -274,7 +274,7 @@ public abstract class AbstractEntitySourceImpl
List<JaxbMapElement> propertyElements){
for ( JaxbMapElement element : propertyElements ) {
results.add(
new MapSource(
new MapSourceImpl(
sourceMappingDocument(),
element, this
)

View File

@ -0,0 +1,163 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, 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.hbm;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.internal.util.ValueHolder;
import org.hibernate.jaxb.spi.hbm.JaxbCompositeIndexElement;
import org.hibernate.jaxb.spi.hbm.JaxbCompositeMapKeyElement;
import org.hibernate.jaxb.spi.hbm.JaxbKeyManyToOneElement;
import org.hibernate.jaxb.spi.hbm.JaxbKeyPropertyElement;
import org.hibernate.metamodel.spi.binding.PluralAttributeIndexBinding;
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
import org.hibernate.metamodel.spi.source.AttributeSource;
import org.hibernate.metamodel.spi.source.CompositePluralAttributeIndexSource;
import org.hibernate.metamodel.spi.source.LocalBindingContext;
import org.hibernate.metamodel.spi.source.RelationalValueSource;
/**
* @author Gail Badner
*/
public class CompositePluralAttributeIndexSourceImpl
extends AbstractHbmSourceNode
implements CompositePluralAttributeIndexSource {
private final String className;
private final List<AttributeSource> attributeSources;
public CompositePluralAttributeIndexSourceImpl(
MappingDocument mappingDocument,
JaxbCompositeIndexElement compositeIndexElement) {
this(
mappingDocument,
compositeIndexElement.getClazz(),
compositeIndexElement.getKeyProperty(),
compositeIndexElement.getKeyManyToOne()
);
}
public CompositePluralAttributeIndexSourceImpl(
MappingDocument mappingDocument,
JaxbCompositeMapKeyElement compositeMapKeyElement) {
this(
mappingDocument,
compositeMapKeyElement.getClazz(),
compositeMapKeyElement.getKeyProperty(),
compositeMapKeyElement.getKeyManyToOne()
);
}
private CompositePluralAttributeIndexSourceImpl(
MappingDocument mappingDocument,
String className,
List<JaxbKeyPropertyElement> keyPropertyElements,
List<JaxbKeyManyToOneElement> keyManyToOneElements) {
super( mappingDocument );
this.className = bindingContext().qualifyClassName( className );
this.attributeSources = buildAttributeSources(
mappingDocument,
keyPropertyElements,
keyManyToOneElements
);
}
@Override
public PluralAttributeIndexBinding.Nature getNature() {
return PluralAttributeIndexBinding.Nature.AGGREGATE;
}
@Override
public String getClassName() {
return className;
}
@Override
public ValueHolder<Class<?>> getClassReference() {
return bindingContext().makeClassReference( className );
}
@Override
public String getPath() {
// todo : implementing this requires passing in the collection source and being able to resolve the collection's role
return null;
}
@Override
public List<AttributeSource> attributeSources() {
return attributeSources;
}
private static List<AttributeSource> buildAttributeSources(
MappingDocument mappingDocument,
List<JaxbKeyPropertyElement> keyPropertyElements,
List<JaxbKeyManyToOneElement> keyManyToOneElements) {
List<AttributeSource> attributeSources = new ArrayList<AttributeSource>();
for ( JaxbKeyPropertyElement keyProperty : keyPropertyElements ){
attributeSources.add(
new KeyAttributeSourceImpl(
mappingDocument,
keyProperty,
SingularAttributeBinding.NaturalIdMutability.NOT_NATURAL_ID
)
);
}
for (JaxbKeyManyToOneElement keyManyToOne :keyManyToOneElements ){
attributeSources.add(
new KeyManyToOneSourceImpl(
mappingDocument,
keyManyToOne,
SingularAttributeBinding.NaturalIdMutability.NOT_NATURAL_ID
)
);
}
return attributeSources;
}
@Override
public LocalBindingContext getLocalBindingContext() {
return bindingContext();
}
@Override
public List<RelationalValueSource> relationalValueSources() {
return null;
}
@Override
public boolean areValuesIncludedInInsertByDefault() {
return true;
}
@Override
public boolean areValuesIncludedInUpdateByDefault() {
return true;
}
@Override
public boolean areValuesNullableByDefault() {
return true;
}
}

View File

@ -26,23 +26,23 @@ package org.hibernate.metamodel.internal.source.hbm;
import org.hibernate.AssertionFailure;
import org.hibernate.cfg.NotYetImplementedException;
import org.hibernate.jaxb.spi.hbm.JaxbMapElement;
import org.hibernate.jaxb.spi.hbm.JaxbMapKeyElement;
import org.hibernate.metamodel.spi.source.AttributeSourceContainer;
import org.hibernate.metamodel.spi.source.IndexedPluralAttributeSource;
import org.hibernate.metamodel.spi.source.PluralAttributeIndexSource;
/**
*
*/
public class MapSource extends AbstractPluralAttributeSourceImpl implements IndexedPluralAttributeSource {
public class MapSourceImpl extends AbstractPluralAttributeSourceImpl implements IndexedPluralAttributeSource {
private final MapKeySourceImpl indexSource;
private final PluralAttributeIndexSource indexSource;
/**
* @param sourceMappingDocument
* @param mapElement
* @param container
*/
public MapSource(
public MapSourceImpl(
MappingDocument sourceMappingDocument,
JaxbMapElement mapElement,
AttributeSourceContainer container) {
@ -54,10 +54,10 @@ public class MapSource extends AbstractPluralAttributeSourceImpl implements Inde
this.indexSource = new MapKeySourceImpl( sourceMappingDocument, mapElement.getIndex() );
}
else if ( mapElement.getCompositeMapKey() != null ) {
throw new NotYetImplementedException( "<composite-map-key> is not supported yet" );
this.indexSource = new CompositePluralAttributeIndexSourceImpl( sourceMappingDocument, mapElement.getCompositeMapKey() );
}
else if ( mapElement.getCompositeIndex() != null ) {
throw new NotYetImplementedException( "<composite-index> is not supported yet" );
this.indexSource = new CompositePluralAttributeIndexSourceImpl( sourceMappingDocument, mapElement.getCompositeIndex() );
}
else if ( mapElement.getMapKeyManyToMany() != null ) {
throw new NotYetImplementedException( "<map-key-many-to-many> is not supported yet" );
@ -74,7 +74,7 @@ public class MapSource extends AbstractPluralAttributeSourceImpl implements Inde
}
@Override
public MapKeySourceImpl getIndexSource() {
public PluralAttributeIndexSource getIndexSource() {
return indexSource;
}

View File

@ -35,16 +35,18 @@ import org.hibernate.metamodel.spi.relational.Column;
*/
public class BackRefAttributeBinding extends BasicAttributeBinding {
PluralAttributeBinding pluralAttributeBinding;
private final PluralAttributeBinding pluralAttributeBinding;
private final boolean isIndexBackRef;
BackRefAttributeBinding(
EntityBinding entityBinding,
SingularAttribute attribute,
PluralAttributeBinding pluralAttributeBinding) {
PluralAttributeBinding pluralAttributeBinding,
boolean isIndexBackRef) {
super(
entityBinding,
attribute,
createRelationalValueBindings( pluralAttributeBinding ),
createRelationalValueBindings( pluralAttributeBinding, isIndexBackRef ),
null,
false,
false,
@ -53,12 +55,24 @@ public class BackRefAttributeBinding extends BasicAttributeBinding {
PropertyGeneration.NEVER
);
this.pluralAttributeBinding = pluralAttributeBinding;
this.isIndexBackRef = isIndexBackRef;
}
private static List<RelationalValueBinding> createRelationalValueBindings(PluralAttributeBinding pluralAttributeBinding) {
List<RelationalValueBinding> relationalValueBindings = new ArrayList<RelationalValueBinding>( );
for ( Column column : pluralAttributeBinding.getPluralAttributeKeyBinding().getForeignKey().getSourceColumns() ) {
relationalValueBindings.add( new RelationalValueBinding( column, true, false ) );
private static List<RelationalValueBinding> createRelationalValueBindings(
PluralAttributeBinding pluralAttributeBinding,
boolean isIndexBackRef) {
List<RelationalValueBinding> relationalValueBindings;
if ( isIndexBackRef ) {
PluralAttributeIndexBinding indexBinding =
( (IndexedPluralAttributeBinding) pluralAttributeBinding).getPluralAttributeIndexBinding();
relationalValueBindings = indexBinding.getRelationalValueBindings();
}
else {
relationalValueBindings = new ArrayList<RelationalValueBinding>( );
for ( Column column : pluralAttributeBinding.getPluralAttributeKeyBinding().getForeignKey().getSourceColumns() ) {
relationalValueBindings.add( new RelationalValueBinding( column, true, false ) );
}
}
return relationalValueBindings;
}
@ -81,6 +95,10 @@ public class BackRefAttributeBinding extends BasicAttributeBinding {
return true;
}
public boolean isIndexBackRef() {
return isIndexBackRef;
}
@Override
public boolean hasDerivedValue() {
return false;
@ -90,4 +108,9 @@ public class BackRefAttributeBinding extends BasicAttributeBinding {
public boolean isNullable() {
return false;
}
@Override
public boolean isIncludedInUpdate() {
return false;
}
}

View File

@ -650,7 +650,9 @@ public class EntityBinding extends AbstractAttributeBindingContainer implements
}
public BackRefAttributeBinding makeBackRefAttributeBinding(
SingularAttribute syntheticAttribute, PluralAttributeBinding pluralAttributeBinding) {
SingularAttribute syntheticAttribute,
PluralAttributeBinding pluralAttributeBinding,
boolean isIndexBackRef) {
if ( ! syntheticAttribute.isSynthetic() ) {
throw new AssertionFailure(
"Illegal attempt to create synthetic attribute binding from non-synthetic attribute reference"
@ -659,7 +661,8 @@ public class EntityBinding extends AbstractAttributeBindingContainer implements
final BackRefAttributeBinding binding = new BackRefAttributeBinding(
this,
syntheticAttribute,
pluralAttributeBinding
pluralAttributeBinding,
isIndexBackRef
);
registerAttributeBinding( binding );

View File

@ -81,4 +81,12 @@ public class HibernateTypeDescriptor {
setToOne( resolvedTypeMapping.isEntityType() );
}
}
public void copyFrom(HibernateTypeDescriptor hibernateTypeDescriptor) {
setJavaTypeName( hibernateTypeDescriptor.getJavaTypeName() );
setExplicitTypeName( hibernateTypeDescriptor.getExplicitTypeName() );
setToOne( hibernateTypeDescriptor.isToOne() );
getTypeParameters().putAll( hibernateTypeDescriptor.getTypeParameters() );
setResolvedTypeMapping( hibernateTypeDescriptor.getResolvedTypeMapping() );
}
}

View File

@ -0,0 +1,36 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, 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.spi.source;
import org.hibernate.internal.util.ValueHolder;
/**
* @author Gail Badner
*/
public interface CompositePluralAttributeIndexSource
extends PluralAttributeIndexSource, AttributeSourceContainer {
public String getClassName();
public ValueHolder<Class<?>> getClassReference();
}

View File

@ -126,16 +126,21 @@ public final class PropertyAccessorFactory {
* <p/> *
* @param entityName The name of the entity owning the backref property.
* @param collectionRole The collection role.
* @param isIndexBackRef Is this an index backref?
* @param mode The entity mode.
* @return An appropriate accessor.
* @throws MappingException
*/
public static PropertyAccessor getBackRefPropertyAccessor(String entityName, String collectionRole, EntityMode mode) {
public static PropertyAccessor getBackRefPropertyAccessor(
String entityName,
String collectionRole,
boolean isIndexBackRef,
EntityMode mode) {
if ( null == mode || EntityMode.POJO.equals( mode ) ) {
//TODO: this is temporary in that the end result will probably not take a Property reference per-se.
return new BackrefPropertyAccessor(
collectionRole, entityName
);
return isIndexBackRef ?
new IndexPropertyAccessor( collectionRole, entityName ) :
new BackrefPropertyAccessor( collectionRole, entityName );
}
else if (EntityMode.MAP.equals( mode ) ) {
//TODO: this is temporary in that the end result will probably not take a Property reference per-se.

View File

@ -467,7 +467,10 @@ public class PropertyFactory {
if ( mappingProperty.isBackRef() ) {
BackRefAttributeBinding backRefAttributeBinding = (BackRefAttributeBinding) mappingProperty;
return PropertyAccessorFactory.getBackRefPropertyAccessor(
backRefAttributeBinding.getEntityName(), backRefAttributeBinding.getCollectionRole(), entityMode
backRefAttributeBinding.getEntityName(),
backRefAttributeBinding.getCollectionRole(),
backRefAttributeBinding.isIndexBackRef(),
entityMode
);
}
else {

View File

@ -43,7 +43,6 @@ import static org.junit.Assert.assertTrue;
*
* @author Steve Ebersole
*/
@FailureExpectedWithNewMetamodel
public class BackrefCompositeMapKeyTest extends BaseCoreFunctionalTestCase {
@Override
public String[] getMappings() {