HHH-7088 - Implement secondary table support in new metamodel code

This commit is contained in:
Steve Ebersole 2012-02-21 15:02:01 -06:00
parent b6902ad211
commit f76524786c
15 changed files with 458 additions and 221 deletions

View File

@ -58,6 +58,7 @@ import org.hibernate.metamodel.spi.binding.ManyToOneAttributeBinding;
import org.hibernate.metamodel.spi.binding.MetaAttribute;
import org.hibernate.metamodel.spi.binding.PluralAttributeElementNature;
import org.hibernate.metamodel.spi.binding.RelationalValueBinding;
import org.hibernate.metamodel.spi.binding.SecondaryTable;
import org.hibernate.metamodel.spi.binding.SingularAssociationAttributeBinding;
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
import org.hibernate.metamodel.spi.domain.Attribute;
@ -96,6 +97,7 @@ import org.hibernate.metamodel.spi.source.Orderable;
import org.hibernate.metamodel.spi.source.PluralAttributeElementSource;
import org.hibernate.metamodel.spi.source.PluralAttributeNature;
import org.hibernate.metamodel.spi.source.PluralAttributeSource;
import org.hibernate.metamodel.spi.source.PrimaryKeyJoinColumnSource;
import org.hibernate.metamodel.spi.source.RelationalValueSource;
import org.hibernate.metamodel.spi.source.RelationalValueSourceContainer;
import org.hibernate.metamodel.spi.source.RootEntitySource;
@ -1348,10 +1350,13 @@ public class Binder {
}
private void bindSecondaryTables(EntitySource entitySource, EntityBinding entityBinding) {
final TableSpecification primaryEntityTable = entityBinding.getPrimaryTable();
for ( SecondaryTableSource secondaryTableSource : entitySource.getSecondaryTables() ) {
final TableSpecification secondaryTable;
final TableSpecificationSource source = secondaryTableSource.getTableSource();
if ( TableSource.class.isInstance( source ) ) {
final Table table = createTable(
secondaryTable = createTable(
(TableSource) source,
new InferredNamingStrategy() {
@Override
@ -1363,12 +1368,52 @@ public class Binder {
}
}
);
// todo : finish up...
// 1) no need to keep secondary tables on EntityBinding because we should be able to look them
// up from Schema
// 2) process foreign key
entityBinding.addSecondaryTable( table.getLogicalName().getName(), table );
}
else {
secondaryTable = createInLineView( (InLineViewSource) source );
}
// todo : really need a concept like SecondaryTableSource in the binding model as well
// so that EntityBinding can know the proper foreign key to use to build SQL statements.
ForeignKey foreignKey = null;
if ( secondaryTableSource.getForeignKeyName() != null ) {
foreignKey = secondaryTable.locateForeignKey( secondaryTableSource.getForeignKeyName() );
if ( foreignKey == null ) {
foreignKey = secondaryTable.createForeignKey(
primaryEntityTable,
secondaryTableSource.getForeignKeyName()
);
}
}
else {
// for now lets assume we have to create it, but eventually we should look through the
// candidate foreign keys referencing primary table also...
foreignKey = secondaryTable.createForeignKey( primaryEntityTable, null );
}
for ( PrimaryKeyJoinColumnSource joinColumnSource : secondaryTableSource.getJoinColumns() ) {
// todo : currently we only support columns here, not formulas
// todo : apply naming strategy to infer missing column name
Column fkColumn = secondaryTable.locateColumn( joinColumnSource.getColumnName() );
if ( fkColumn == null ) {
fkColumn = secondaryTable.createColumn( joinColumnSource.getColumnName() );
if ( joinColumnSource.getColumnDefinition() != null ) {
fkColumn.setSqlType( joinColumnSource.getColumnDefinition() );
}
}
if ( joinColumnSource.getReferencedColumnName() != null ) {
final Column referencedColumn = primaryEntityTable.locateColumn(
joinColumnSource.getReferencedColumnName()
);
foreignKey.addColumnMapping( fkColumn, referencedColumn );
}
else {
foreignKey.addColumn( fkColumn );
}
}
entityBinding.addSecondaryTable( new SecondaryTable( secondaryTable, foreignKey ) );
}
}

View File

@ -63,28 +63,158 @@ import org.hibernate.metamodel.spi.source.SubclassEntitySource;
* @author Steve Ebersole
* @author Hardy Ferentschik
*/
public abstract class AbstractEntitySourceImpl implements EntitySource {
private final MappingDocument sourceMappingDocument;
public abstract class AbstractEntitySourceImpl
extends AbstractHbmSourceNode
implements EntitySource, Helper.InLineViewNameInferrer {
private final EntityElement entityElement;
private final Set<SecondaryTableSource> secondaryTableSources;
private final String className;
private final String entityName;
private List<SubclassEntitySource> subclassEntitySources = new ArrayList<SubclassEntitySource>();
private int inLineViewCount = 0;
// logically final, but built during 'afterInstantiation' callback
private List<AttributeSource> attributeSources;
private Set<SecondaryTableSource> secondaryTableSources;
private List<SubclassEntitySource> subclassEntitySources;
protected AbstractEntitySourceImpl(MappingDocument sourceMappingDocument, EntityElement entityElement) {
this.sourceMappingDocument = sourceMappingDocument;
super( sourceMappingDocument );
this.entityElement = entityElement;
secondaryTableSources = extractSecondaryTables( entityElement, sourceMappingDocument.getMappingLocalBindingContext() );
this.className = bindingContext().qualifyClassName( entityElement.getName() );
this.entityName = StringHelper.isNotEmpty( entityElement.getEntityName() )
? entityElement.getEntityName()
: className;
}
private static Set<SecondaryTableSource> extractSecondaryTables(EntityElement entityElement, HbmBindingContext bindingContext) {
@Override
public String inferInLineViewName() {
return entityName + '#' + (++inLineViewCount);
}
protected void afterInstantiation() {
this.attributeSources = buildAttributeSources();
this.secondaryTableSources = buildSecondaryTables();
this.subclassEntitySources = buildSubClassSources();
}
protected List<AttributeSource> buildAttributeSources() {
List<AttributeSource> attributeSources = new ArrayList<AttributeSource>();
buildAttributeSources( attributeSources );
return attributeSources;
}
protected List<AttributeSource> buildAttributeSources(List<AttributeSource> attributeSources) {
processAttributes(
attributeSources,
entityElement.getPropertyOrManyToOneOrOneToOne(),
null,
SingularAttributeSource.NaturalIdMutability.NOT_NATURAL_ID
);
return attributeSources;
}
protected void processAttributes(
List<AttributeSource> results,
List attributeElements,
String logicalTableName,
SingularAttributeSource.NaturalIdMutability naturalIdMutability) {
for ( Object attributeElement : attributeElements ) {
if ( JaxbPropertyElement.class.isInstance( attributeElement ) ) {
results.add(
new PropertyAttributeSourceImpl(
sourceMappingDocument(),
JaxbPropertyElement.class.cast( attributeElement ),
logicalTableName,
naturalIdMutability
)
);
}
else if ( JaxbComponentElement.class.isInstance( attributeElement ) ) {
results.add(
new ComponentAttributeSourceImpl(
sourceMappingDocument(),
(JaxbComponentElement) attributeElement,
this,
logicalTableName,
naturalIdMutability
)
);
}
else if ( JaxbManyToOneElement.class.isInstance( attributeElement ) ) {
results.add(
new ManyToOneAttributeSourceImpl(
sourceMappingDocument(),
JaxbManyToOneElement.class.cast( attributeElement ),
logicalTableName,
naturalIdMutability
)
);
}
else if ( JaxbOneToOneElement.class.isInstance( attributeElement ) ) {
// todo : implement
}
else if ( JaxbAnyElement.class.isInstance( attributeElement ) ) {
// todo : implement
}
else if ( JaxbBagElement.class.isInstance( attributeElement ) ) {
results.add(
new BagAttributeSourceImpl(
JaxbBagElement.class.cast( attributeElement ),
this
)
);
}
else if ( JaxbIdbagElement.class.isInstance( attributeElement ) ) {
// todo : implement
}
else if ( JaxbSetElement.class.isInstance( attributeElement ) ) {
results.add(
new SetAttributeSourceImpl(
JaxbSetElement.class.cast( attributeElement ),
this
)
);
}
else if ( JaxbListElement.class.isInstance( attributeElement ) ) {
// todo : implement
}
else if ( JaxbMapElement.class.isInstance( attributeElement ) ) {
// todo : implement
}
else {
throw new AssertionFailure( "Unexpected attribute element type encountered : " + attributeElement.getClass() );
}
}
}
protected List<SubclassEntitySource> buildSubClassSources() {
// todo : implement subclass processing
return Collections.emptyList();
}
private Set<SecondaryTableSource> buildSecondaryTables() {
if ( ! JoinElementSource.class.isInstance( entityElement ) ) {
return Collections.emptySet();
}
final Set<SecondaryTableSource> secondaryTableSources = new HashSet<SecondaryTableSource>();
for ( JaxbJoinElement joinElement : ( (JoinElementSource) entityElement ).getJoin() ) {
secondaryTableSources.add( new SecondaryTableSourceImpl( joinElement, bindingContext ) );
final SecondaryTableSourceImpl secondaryTableSource = new SecondaryTableSourceImpl(
sourceMappingDocument(),
joinElement,
this
);
secondaryTableSources.add( secondaryTableSource );
final String logicalTableName = secondaryTableSource.getLogicalTableNameForContainedColumns();
processAttributes(
attributeSources,
joinElement.getPropertyOrManyToOneOrComponent(),
logicalTableName,
SingularAttributeSource.NaturalIdMutability.NOT_NATURAL_ID
);
}
return secondaryTableSources;
}
@ -93,30 +223,24 @@ public abstract class AbstractEntitySourceImpl implements EntitySource {
return entityElement;
}
protected MappingDocument sourceMappingDocument() {
return sourceMappingDocument;
}
@Override
public Origin getOrigin() {
return sourceMappingDocument.getOrigin();
return origin();
}
@Override
public LocalBindingContext getLocalBindingContext() {
return sourceMappingDocument.getMappingLocalBindingContext();
return bindingContext();
}
@Override
public String getEntityName() {
return StringHelper.isNotEmpty( entityElement.getEntityName() )
? entityElement.getEntityName()
: getClassName();
return entityName;
}
@Override
public String getClassName() {
return getLocalBindingContext().qualifyClassName( entityElement.getName() );
return className;
}
@Override
@ -218,95 +342,14 @@ public abstract class AbstractEntitySourceImpl implements EntitySource {
@Override
public String getPath() {
return sourceMappingDocument.getMappingLocalBindingContext().determineEntityName( entityElement );
return bindingContext().determineEntityName( entityElement );
}
@Override
public List<AttributeSource> attributeSources() {
List<AttributeSource> attributeSources = new ArrayList<AttributeSource>();
processAttributes( attributeSources );
return attributeSources;
}
protected List<AttributeSource> processAttributes(List<AttributeSource> attributeSources) {
processAttributes(
attributeSources,
entityElement.getPropertyOrManyToOneOrOneToOne(),
SingularAttributeSource.NaturalIdMutability.NOT_NATURAL_ID
);
return attributeSources;
}
protected void processAttributes(
List<AttributeSource> results,
List attributeElements,
SingularAttributeSource.NaturalIdMutability naturalIdMutability) {
for ( Object attributeElement : attributeElements ) {
if ( JaxbPropertyElement.class.isInstance( attributeElement ) ) {
results.add(
new PropertyAttributeSourceImpl(
JaxbPropertyElement.class.cast( attributeElement ),
sourceMappingDocument().getMappingLocalBindingContext(),
naturalIdMutability
)
);
}
else if ( JaxbComponentElement.class.isInstance( attributeElement ) ) {
results.add(
new ComponentAttributeSourceImpl(
(JaxbComponentElement) attributeElement,
this,
sourceMappingDocument.getMappingLocalBindingContext(),
naturalIdMutability
)
);
}
else if ( JaxbManyToOneElement.class.isInstance( attributeElement ) ) {
results.add(
new ManyToOneAttributeSourceImpl(
JaxbManyToOneElement.class.cast( attributeElement ),
sourceMappingDocument().getMappingLocalBindingContext(),
naturalIdMutability
)
);
}
else if ( JaxbOneToOneElement.class.isInstance( attributeElement ) ) {
// todo : implement
}
else if ( JaxbAnyElement.class.isInstance( attributeElement ) ) {
// todo : implement
}
else if ( JaxbBagElement.class.isInstance( attributeElement ) ) {
results.add(
new BagAttributeSourceImpl(
JaxbBagElement.class.cast( attributeElement ),
this
)
);
}
else if ( JaxbIdbagElement.class.isInstance( attributeElement ) ) {
// todo : implement
}
else if ( JaxbSetElement.class.isInstance( attributeElement ) ) {
results.add(
new SetAttributeSourceImpl(
JaxbSetElement.class.cast( attributeElement ),
this
)
);
}
else if ( JaxbListElement.class.isInstance( attributeElement ) ) {
// todo : implement
}
else if ( JaxbMapElement.class.isInstance( attributeElement ) ) {
// todo : implement
}
else {
throw new AssertionFailure( "Unexpected attribute element type encountered : " + attributeElement.getClass() );
}
}
}
private EntityHierarchyImpl entityHierarchy;
public void injectHierarchy(EntityHierarchyImpl entityHierarchy) {

View File

@ -0,0 +1,73 @@
/*
* 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.hbm;
import org.hibernate.internal.jaxb.JaxbRoot;
import org.hibernate.internal.jaxb.Origin;
import org.hibernate.internal.jaxb.mapping.hbm.JaxbHibernateMapping;
import org.hibernate.internal.util.Value;
import org.hibernate.metamodel.spi.source.MappingException;
/**
* Base class for any and all source objects coming from {@code hbm.xml} parsing. Defines standard access
* back to the {@link MappingDocument} object and the services it provides (namely access to
* {@link HbmBindingContext}).
*
* @author Steve Ebersole
*/
public abstract class AbstractHbmSourceNode {
private final MappingDocument sourceMappingDocument;
protected AbstractHbmSourceNode(MappingDocument sourceMappingDocument) {
this.sourceMappingDocument = sourceMappingDocument;
}
protected MappingDocument sourceMappingDocument() {
return sourceMappingDocument;
}
protected HbmBindingContext bindingContext() {
return sourceMappingDocument().getMappingLocalBindingContext();
}
protected Origin origin() {
return sourceMappingDocument().getOrigin();
}
protected JaxbRoot<JaxbHibernateMapping> mappingRoot() {
return sourceMappingDocument().getJaxbRoot();
}
protected Value<Class<?>> makeClassReference(String className) {
return bindingContext().makeClassReference( bindingContext().qualifyClassName( className ) );
}
protected MappingException makeMappingException(String message) {
return bindingContext().makeMappingException( message );
}
protected MappingException makeMappingException(String message, Exception cause) {
return bindingContext().makeMappingException( message, cause );
}
}

View File

@ -50,7 +50,7 @@ import org.hibernate.metamodel.spi.source.TableSpecificationSource;
* @author Steve Ebersole
*/
public abstract class AbstractPluralAttributeSourceImpl
implements PluralAttributeSource {
implements PluralAttributeSource, Helper.InLineViewNameInferrer {
private final PluralAttributeElement pluralAttributeElement;
private final AttributeSourceContainer container;
@ -140,12 +140,14 @@ public abstract class AbstractPluralAttributeSourceImpl
return elementSource;
}
@Override
public String inferInLineViewName() {
return container().getPath() + "." + pluralAttributeElement.getName();
}
@Override
public TableSpecificationSource getCollectionTableSpecificationSource() {
return Helper.createTableSource(
pluralAttributeElement,
container().getPath() + "." + pluralAttributeElement.getName()
);
return Helper.createTableSource( pluralAttributeElement, this );
}
@Override

View File

@ -46,30 +46,82 @@ import org.hibernate.metamodel.spi.source.ExplicitHibernateTypeSource;
import org.hibernate.metamodel.spi.source.MetaAttributeSource;
import org.hibernate.metamodel.spi.source.RelationalValueSource;
import org.hibernate.metamodel.spi.source.SingularAttributeNature;
import org.hibernate.metamodel.spi.source.SingularAttributeSource;
/**
* @author Steve Ebersole
*/
public class ComponentAttributeSourceImpl implements ComponentAttributeSource {
class ComponentAttributeSourceImpl extends AbstractHbmSourceNode implements ComponentAttributeSource {
private final JaxbComponentElement componentElement;
private final AttributeSourceContainer parentContainer;
private final List<AttributeSource> subAttributeSources;
private final NaturalIdMutability naturalIdMutability;
private final Value<Class<?>> componentClassReference;
private final String path;
public ComponentAttributeSourceImpl(
MappingDocument sourceMappingDocument,
JaxbComponentElement componentElement,
AttributeSourceContainer parentContainer,
LocalBindingContext bindingContext,
String logicalTableName,
NaturalIdMutability naturalIdMutability) {
super( sourceMappingDocument );
this.componentElement = componentElement;
this.parentContainer = parentContainer;
this.naturalIdMutability = naturalIdMutability;
this.componentClassReference = bindingContext.makeClassReference(
bindingContext.qualifyClassName( componentElement.getClazz() )
);
this.componentClassReference = makeClassReference( componentElement.getClazz() );
this.path = parentContainer.getPath() + '.' + componentElement.getName();
this.subAttributeSources = buildAttributeSources( logicalTableName );
}
private List<AttributeSource> buildAttributeSources(String logicalTableName) {
List<AttributeSource> attributeSources = new ArrayList<AttributeSource>();
for ( Object attributeElement : componentElement.getPropertyOrManyToOneOrOneToOne() ) {
if ( JaxbPropertyElement.class.isInstance( attributeElement ) ) {
attributeSources.add(
new PropertyAttributeSourceImpl(
sourceMappingDocument(),
JaxbPropertyElement.class.cast( attributeElement ),
logicalTableName,
naturalIdMutability
)
);
}
else if ( JaxbComponentElement.class.isInstance( attributeElement ) ) {
attributeSources.add(
new ComponentAttributeSourceImpl(
sourceMappingDocument(),
(JaxbComponentElement) attributeElement,
this,
logicalTableName,
naturalIdMutability
)
);
}
else if ( JaxbManyToOneElement.class.isInstance( attributeElement ) ) {
attributeSources.add(
new ManyToOneAttributeSourceImpl(
sourceMappingDocument(),
JaxbManyToOneElement.class.cast( attributeElement ),
logicalTableName,
naturalIdMutability
)
);
}
else if ( JaxbOneToOneElement.class.isInstance( attributeElement ) ) {
// todo : implement
}
else if ( JaxbAnyElement.class.isInstance( attributeElement ) ) {
// todo : implement
}
else if ( JaxbOneToManyElement.class.isInstance( attributeElement ) ) {
// todo : implement
}
else if ( JaxbManyToManyElement.class.isInstance( attributeElement ) ) {
// todo : implement
}
}
return attributeSources;
}
@Override
@ -113,50 +165,7 @@ public class ComponentAttributeSourceImpl implements ComponentAttributeSource {
@Override
public List<AttributeSource> attributeSources() {
List<AttributeSource> attributeSources = new ArrayList<AttributeSource>();
for ( Object attributeElement : componentElement.getPropertyOrManyToOneOrOneToOne() ) {
if ( JaxbPropertyElement.class.isInstance( attributeElement ) ) {
attributeSources.add(
new PropertyAttributeSourceImpl(
JaxbPropertyElement.class.cast( attributeElement ),
getLocalBindingContext(),
naturalIdMutability
)
);
}
else if ( JaxbComponentElement.class.isInstance( attributeElement ) ) {
attributeSources.add(
new ComponentAttributeSourceImpl(
(JaxbComponentElement) attributeElement,
this,
getLocalBindingContext(),
naturalIdMutability
)
);
}
else if ( JaxbManyToOneElement.class.isInstance( attributeElement ) ) {
attributeSources.add(
new ManyToOneAttributeSourceImpl(
JaxbManyToOneElement.class.cast( attributeElement ),
getLocalBindingContext(),
naturalIdMutability
)
);
}
else if ( JaxbOneToOneElement.class.isInstance( attributeElement ) ) {
// todo : implement
}
else if ( JaxbAnyElement.class.isInstance( attributeElement ) ) {
// todo : implement
}
else if ( JaxbOneToManyElement.class.isInstance( attributeElement ) ) {
// todo : implement
}
else if ( JaxbManyToManyElement.class.isInstance( attributeElement ) ) {
// todo : implement
}
}
return attributeSources;
return subAttributeSources;
}
@Override

View File

@ -289,7 +289,13 @@ public class Helper {
return null;
}
public static TableSpecificationSource createTableSource(TableInformationSource jaxbTableSource, String context) {
public static interface InLineViewNameInferrer {
public String inferInLineViewName();
}
public static TableSpecificationSource createTableSource(
TableInformationSource jaxbTableSource,
InLineViewNameInferrer inLineViewNameInferrer) {
if ( jaxbTableSource.getSubselectAttribute() == null && jaxbTableSource.getSubselect() == null ) {
return new TableSourceImpl(
jaxbTableSource.getSchema(),
@ -304,7 +310,9 @@ public class Helper {
jaxbTableSource.getSubselectAttribute() != null
? jaxbTableSource.getSubselectAttribute()
: jaxbTableSource.getSubselect(),
context
jaxbTableSource.getTable() == null
? inLineViewNameInferrer.inferInLineViewName()
: jaxbTableSource.getTable()
);
}

View File

@ -32,7 +32,6 @@ import org.hibernate.engine.spi.CascadeStyle;
import org.hibernate.internal.jaxb.mapping.hbm.JaxbManyToOneElement;
import org.hibernate.mapping.PropertyGeneration;
import org.hibernate.metamodel.spi.source.ExplicitHibernateTypeSource;
import org.hibernate.metamodel.spi.source.LocalBindingContext;
import org.hibernate.metamodel.spi.source.MappingException;
import org.hibernate.metamodel.spi.source.MetaAttributeSource;
import org.hibernate.metamodel.spi.source.RelationalValueSource;
@ -44,18 +43,18 @@ import org.hibernate.metamodel.spi.source.ToOneAttributeSource;
*
* @author Steve Ebersole
*/
class ManyToOneAttributeSourceImpl implements ToOneAttributeSource {
class ManyToOneAttributeSourceImpl extends AbstractHbmSourceNode implements ToOneAttributeSource {
private final JaxbManyToOneElement manyToOneElement;
private final LocalBindingContext bindingContext;
private final NaturalIdMutability naturalIdMutability;
private final List<RelationalValueSource> valueSources;
ManyToOneAttributeSourceImpl(
MappingDocument sourceMappingDocument,
final JaxbManyToOneElement manyToOneElement,
LocalBindingContext bindingContext,
final String logicalTableName,
NaturalIdMutability naturalIdMutability) {
super( sourceMappingDocument );
this.manyToOneElement = manyToOneElement;
this.bindingContext = bindingContext;
this.naturalIdMutability = naturalIdMutability;
this.valueSources = Helper.buildValueSources(
new Helper.ValueSourcesAdapter() {
@ -76,8 +75,7 @@ class ManyToOneAttributeSourceImpl implements ToOneAttributeSource {
@Override
public String getContainingTableName() {
// todo : need to implement this...
return null;
return logicalTableName;
}
@Override
@ -90,7 +88,7 @@ class ManyToOneAttributeSourceImpl implements ToOneAttributeSource {
return manyToOneElement.isUpdate();
}
},
bindingContext
bindingContext()
);
}
@ -131,7 +129,7 @@ class ManyToOneAttributeSourceImpl implements ToOneAttributeSource {
@Override
public Iterable<CascadeStyle> getCascadeStyles() {
return Helper.interpretCascadeStyles( manyToOneElement.getCascade(), bindingContext );
return Helper.interpretCascadeStyles( manyToOneElement.getCascade(), bindingContext() );
}
@Override
@ -154,7 +152,7 @@ class ManyToOneAttributeSourceImpl implements ToOneAttributeSource {
return FetchTiming.DELAYED;
}
else {
return bindingContext.getMappingDefaults().areAssociationsLazy()
return bindingContext().getMappingDefaults().areAssociationsLazy()
? FetchTiming.DELAYED
: FetchTiming.IMMEDIATE;
}
@ -175,7 +173,7 @@ class ManyToOneAttributeSourceImpl implements ToOneAttributeSource {
lazySelection,
manyToOneElement.getName()
),
bindingContext.getOrigin()
origin()
);
}
@ -196,7 +194,7 @@ class ManyToOneAttributeSourceImpl implements ToOneAttributeSource {
}
else {
if ( "auto".equals( outerJoinSelection ) ) {
return bindingContext.getMappingDefaults().areAssociationsLazy()
return bindingContext().getMappingDefaults().areAssociationsLazy()
? FetchStyle.SELECT
: FetchStyle.JOIN;
}

View File

@ -29,7 +29,6 @@ import java.util.Map;
import org.hibernate.internal.jaxb.mapping.hbm.JaxbPropertyElement;
import org.hibernate.mapping.PropertyGeneration;
import org.hibernate.metamodel.spi.source.ExplicitHibernateTypeSource;
import org.hibernate.metamodel.spi.source.LocalBindingContext;
import org.hibernate.metamodel.spi.source.MetaAttributeSource;
import org.hibernate.metamodel.spi.source.RelationalValueSource;
import org.hibernate.metamodel.spi.source.SingularAttributeNature;
@ -40,16 +39,18 @@ import org.hibernate.metamodel.spi.source.SingularAttributeSource;
*
* @author Steve Ebersole
*/
class PropertyAttributeSourceImpl implements SingularAttributeSource {
class PropertyAttributeSourceImpl extends AbstractHbmSourceNode implements SingularAttributeSource {
private final JaxbPropertyElement propertyElement;
private final ExplicitHibernateTypeSource typeSource;
private final List<RelationalValueSource> valueSources;
private final NaturalIdMutability naturalIdMutability;
PropertyAttributeSourceImpl(
MappingDocument sourceMappingDocument,
final JaxbPropertyElement propertyElement,
LocalBindingContext bindingContext,
final String logicalTableName,
NaturalIdMutability naturalIdMutability) {
super( sourceMappingDocument );
this.propertyElement = propertyElement;
this.typeSource = new ExplicitHibernateTypeSource() {
private final String name = propertyElement.getTypeAttribute() != null
@ -90,8 +91,7 @@ class PropertyAttributeSourceImpl implements SingularAttributeSource {
@Override
public String getContainingTableName() {
// todo : need to implement this...
return null;
return logicalTableName;
}
@Override
@ -104,7 +104,7 @@ class PropertyAttributeSourceImpl implements SingularAttributeSource {
return Helper.getBooleanValue( propertyElement.isUpdate(), true );
}
},
bindingContext
bindingContext()
);
this.naturalIdMutability = naturalIdMutability;
}

View File

@ -23,7 +23,6 @@
*/
package org.hibernate.metamodel.internal.source.hbm;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.EntityMode;
@ -44,6 +43,7 @@ import org.hibernate.metamodel.spi.source.RelationalValueSource;
import org.hibernate.metamodel.spi.source.RootEntitySource;
import org.hibernate.metamodel.spi.source.SimpleIdentifierSource;
import org.hibernate.metamodel.spi.source.SingularAttributeSource;
import org.hibernate.metamodel.spi.source.SubclassEntitySource;
import org.hibernate.metamodel.spi.source.TableSpecificationSource;
import org.hibernate.metamodel.spi.source.VersionAttributeSource;
@ -57,10 +57,9 @@ public class RootEntitySourceImpl extends AbstractEntitySourceImpl implements Ro
MappingDocument sourceMappingDocument,
JaxbHibernateMapping.JaxbClass entityElement) {
super( sourceMappingDocument, entityElement );
this.primaryTable = Helper.createTableSource(
entityElement,
sourceMappingDocument.getMappingLocalBindingContext().determineEntityName( entityElement )
);
this.primaryTable = Helper.createTableSource( entityElement, this );
afterInstantiation();
}
@Override
@ -126,20 +125,19 @@ public class RootEntitySourceImpl extends AbstractEntitySourceImpl implements Ro
}
@Override
public List<AttributeSource> attributeSources() {
List<AttributeSource> attributeSources = new ArrayList<AttributeSource>();
protected List<AttributeSource> buildAttributeSources(List<AttributeSource> attributeSources) {
final JaxbHibernateMapping.JaxbClass.JaxbNaturalId naturalId = entityElement().getNaturalId();
if ( naturalId != null ) {
processAttributes(
attributeSources,
naturalId.getPropertyOrManyToOneOrComponent(),
null,
naturalId.isMutable()
? SingularAttributeSource.NaturalIdMutability.MUTABLE
: SingularAttributeSource.NaturalIdMutability.IMMUTABLE
);
}
processAttributes( attributeSources );
return attributeSources;
return super.buildAttributeSources( attributeSources );
}
@Override
@ -152,7 +150,6 @@ public class RootEntitySourceImpl extends AbstractEntitySourceImpl implements Ro
return entityElement().isMutable();
}
@Override
public boolean isExplicitPolymorphism() {
return "explicit".equals( entityElement().getPolymorphism() );

View File

@ -28,30 +28,32 @@ import java.util.List;
import org.hibernate.internal.jaxb.mapping.hbm.JaxbColumnElement;
import org.hibernate.internal.jaxb.mapping.hbm.JaxbJoinElement;
import org.hibernate.metamodel.spi.source.InLineViewSource;
import org.hibernate.metamodel.spi.source.PrimaryKeyJoinColumnSource;
import org.hibernate.metamodel.spi.source.SecondaryTableSource;
import org.hibernate.metamodel.spi.source.TableSource;
import org.hibernate.metamodel.spi.source.TableSpecificationSource;
/**
* @author Steve Ebersole
*/
public class SecondaryTableSourceImpl implements SecondaryTableSource {
class SecondaryTableSourceImpl extends AbstractHbmSourceNode implements SecondaryTableSource {
private final JaxbJoinElement joinElement;
private final TableSpecificationSource joinTable;
private final List<PrimaryKeyJoinColumnSource> joinColumns;
public SecondaryTableSourceImpl(JaxbJoinElement joinElement, HbmBindingContext bindingContext) {
public SecondaryTableSourceImpl(
MappingDocument sourceMappingDocument,
JaxbJoinElement joinElement,
Helper.InLineViewNameInferrer inLineViewNameInferrer) {
super( sourceMappingDocument );
this.joinElement = joinElement;
this.joinTable = Helper.createTableSource(
joinElement,
// todo : need to implement this
null
);
this.joinTable = Helper.createTableSource( joinElement, inLineViewNameInferrer );
joinColumns = new ArrayList<PrimaryKeyJoinColumnSource>();
if ( joinElement.getKey().getColumnAttribute() != null ) {
if ( joinElement.getKey().getColumn().size() > 0 ) {
throw bindingContext.makeMappingException( "<join/> defined both column attribute and nested <column/>" );
throw makeMappingException( "<join/> defined both column attribute and nested <column/>" );
}
joinColumns.add(
new PrimaryKeyJoinColumnSource() {
@ -108,4 +110,10 @@ public class SecondaryTableSourceImpl implements SecondaryTableSource {
public List<PrimaryKeyJoinColumnSource> getJoinColumns() {
return joinColumns;
}
public String getLogicalTableNameForContainedColumns() {
return TableSource.class.isInstance( joinTable )
? ( (TableSource) joinTable ).getExplicitTableName()
: ( (InLineViewSource) joinTable ).getLogicalName();
}
}

View File

@ -23,6 +23,8 @@
*/
package org.hibernate.metamodel.internal.source.hbm;
import java.util.List;
import org.hibernate.internal.jaxb.mapping.hbm.EntityElement;
import org.hibernate.internal.jaxb.mapping.hbm.JaxbSubclassElement;
import org.hibernate.internal.jaxb.mapping.hbm.TableInformationSource;
@ -44,10 +46,7 @@ public class SubclassEntitySourceImpl extends AbstractEntitySourceImpl implement
super( sourceMappingDocument, entityElement );
this.container = container;
this.primaryTable = TableInformationSource.class.isInstance( entityElement )
? Helper.createTableSource(
(TableInformationSource) entityElement,
sourceMappingDocument.getMappingLocalBindingContext().determineEntityName( entityElement )
)
? Helper.createTableSource( (TableInformationSource) entityElement, this )
: null;
}

View File

@ -66,7 +66,7 @@ public class EntityBinding implements AttributeBindingContainer {
private Entity entity;
private TableSpecification primaryTable;
private String primaryTableName;
private Map<String, TableSpecification> secondaryTables = new HashMap<String, TableSpecification>();
private Map<String, SecondaryTable> secondaryTables = new HashMap<String, SecondaryTable>();
private Value<Class<?>> proxyInterfaceType;
@ -234,17 +234,17 @@ public class EntityBinding implements AttributeBindingContainer {
if ( tableName == null || tableName.equals( getPrimaryTableName() ) ) {
return primaryTable;
}
TableSpecification tableSpec = secondaryTables.get( tableName );
if ( tableSpec == null ) {
throw new AssertionFailure(
String.format(
"Unable to find table %s amongst tables %s",
tableName,
secondaryTables.keySet()
)
);
}
return tableSpec;
SecondaryTable secondaryTable = secondaryTables.get( tableName );
if ( secondaryTable == null ) {
throw new AssertionFailure(
String.format(
"Unable to find table %s amongst tables %s",
tableName,
secondaryTables.keySet()
)
);
}
return secondaryTable.getSecondaryTableReference();
}
public String getPrimaryTableName() {
return primaryTableName;
@ -254,8 +254,8 @@ public class EntityBinding implements AttributeBindingContainer {
this.primaryTableName = primaryTableName;
}
public void addSecondaryTable(String tableName, TableSpecification table) {
secondaryTables.put( tableName, table );
public void addSecondaryTable(SecondaryTable secondaryTable) {
secondaryTables.put( secondaryTable.getSecondaryTableReference().getLogicalName().getName(), secondaryTable );
}
public boolean isVersioned() {

View File

@ -0,0 +1,48 @@
/*
* 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.spi.binding;
import org.hibernate.metamodel.spi.relational.ForeignKey;
import org.hibernate.metamodel.spi.relational.TableSpecification;
/**
* @author Steve Ebersole
*/
public class SecondaryTable {
private final TableSpecification secondaryTableReference;
private final ForeignKey foreignKeyReference;
public SecondaryTable(TableSpecification secondaryTableReference, ForeignKey foreignKeyReference) {
this.secondaryTableReference = secondaryTableReference;
this.foreignKeyReference = foreignKeyReference;
}
public TableSpecification getSecondaryTableReference() {
return secondaryTableReference;
}
public ForeignKey getForeignKeyReference() {
return foreignKeyReference;
}
}

View File

@ -64,10 +64,7 @@ public abstract class AbstractTableSpecification implements TableSpecification {
if ( valueMap.containsKey( name ) ) {
return (Column) valueMap.get( name );
}
final Column column = new Column( this, valueList.size(), name );
valueMap.put( name, column );
valueList.add( column );
return column;
return createColumn( name );
}
@Override
@ -78,6 +75,14 @@ public abstract class AbstractTableSpecification implements TableSpecification {
return null;
}
@Override
public Column createColumn(String name) {
final Column column = new Column( this, valueList.size(), name );
valueMap.put( name, column );
valueList.add( column );
return column;
}
@Override
public DerivedValue locateOrCreateDerivedValue(String fragment) {
if ( valueMap.containsKey( fragment ) ) {

View File

@ -77,6 +77,8 @@ public interface TableSpecification extends ValueContainer, Loggable {
*/
public Column locateColumn(String name);
public Column createColumn(String name);
/**
* Factory method for creating a {@link DerivedValue} associated with this container.
*