HHH-8360 HHH-7843 : one-to-one and mappedBy associations
HHH-8360 HHH-7843 : one-to-one and mappedBy associations
This commit is contained in:
parent
c9738beaf4
commit
00fed4c443
File diff suppressed because it is too large
Load Diff
|
@ -123,6 +123,7 @@ public class ForeignKeyHelper {
|
|||
final AttributeBinding referencedAttributeBinding = explicitName != null
|
||||
? referencedEntityBinding.locateAttributeBindingByPath( explicitName, true )
|
||||
: referencedEntityBinding.locateAttributeBinding(
|
||||
resolutionDelegate.getReferencedTable( resolutionContext ),
|
||||
resolutionDelegate.getJoinColumns( resolutionContext ),
|
||||
true
|
||||
);
|
||||
|
|
|
@ -299,21 +299,28 @@ class HibernateTypeHelper {
|
|||
void bindJdbcDataType(
|
||||
final Type resolvedHibernateType,
|
||||
final List<RelationalValueBinding> relationalValueBindings) {
|
||||
if ( relationalValueBindings.size() <= 1 ) {
|
||||
if ( resolvedHibernateType == null ) {
|
||||
throw new IllegalArgumentException( "resolvedHibernateType must be non-null." );
|
||||
}
|
||||
if ( relationalValueBindings == null || relationalValueBindings.isEmpty() ) {
|
||||
throw new IllegalArgumentException( "relationalValueBindings must be non-null." );
|
||||
}
|
||||
if ( relationalValueBindings.size() == 1 ) {
|
||||
bindJdbcDataType( resolvedHibernateType, relationalValueBindings.get( 0 ).getValue() );
|
||||
return;
|
||||
}
|
||||
final Type resolvedRelationalType =
|
||||
resolvedHibernateType.isEntityType()
|
||||
? EntityType.class.cast( resolvedHibernateType ).getIdentifierOrUniqueKeyType( metadata() )
|
||||
: resolvedHibernateType;
|
||||
if ( !CompositeType.class.isInstance( resolvedRelationalType ) ) {
|
||||
throw bindingContext
|
||||
.makeMappingException( "Column number mismatch" ); // todo refine the exception message
|
||||
}
|
||||
Type[] subTypes = CompositeType.class.cast( resolvedRelationalType ).getSubtypes();
|
||||
for ( int i = 0; i < subTypes.length; i++ ) {
|
||||
bindJdbcDataType( subTypes[i], relationalValueBindings.get( i ).getValue() );
|
||||
else {
|
||||
final Type resolvedRelationalType =
|
||||
resolvedHibernateType.isEntityType()
|
||||
? EntityType.class.cast( resolvedHibernateType ).getIdentifierOrUniqueKeyType( metadata() )
|
||||
: resolvedHibernateType;
|
||||
if ( !CompositeType.class.isInstance( resolvedRelationalType ) ) {
|
||||
throw bindingContext
|
||||
.makeMappingException( "Column number mismatch" ); // todo refine the exception message
|
||||
}
|
||||
Type[] subTypes = CompositeType.class.cast( resolvedRelationalType ).getSubtypes();
|
||||
for ( int i = 0; i < subTypes.length; i++ ) {
|
||||
bindJdbcDataType( subTypes[i], relationalValueBindings.get( i ).getValue() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -39,10 +39,11 @@ public class ManyToManyCollectionTableNamingStrategyHelper extends TableNamingSt
|
|||
private final String propertyName;
|
||||
|
||||
public ManyToManyCollectionTableNamingStrategyHelper(
|
||||
final AbstractPluralAttributeBinding pluralAttributeBinding,
|
||||
final String attributePath,
|
||||
final boolean isInverse,
|
||||
final EntityBinding entityBinding,
|
||||
final EntityBinding associatedEntityBinding) {
|
||||
super( pluralAttributeBinding.getContainer().seekEntityBinding() );
|
||||
super( entityBinding );
|
||||
if ( isInverse ) {
|
||||
ownerEntityBinding = associatedEntityBinding;
|
||||
inverseEntityBinding = entityBinding;
|
||||
|
@ -59,7 +60,7 @@ public class ManyToManyCollectionTableNamingStrategyHelper extends TableNamingSt
|
|||
Table.class.isInstance( inverseEntityBinding.getPrimaryTable() )
|
||||
? ( (Table) inverseEntityBinding.getPrimaryTable() ).getPhysicalName().getText()
|
||||
: null;
|
||||
propertyName = Binder.createAttributePath( pluralAttributeBinding );
|
||||
propertyName = attributePath;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -37,6 +37,7 @@ import org.hibernate.metamodel.spi.domain.Attribute;
|
|||
import org.hibernate.metamodel.spi.relational.Column;
|
||||
import org.hibernate.metamodel.spi.relational.DerivedValue;
|
||||
import org.hibernate.metamodel.spi.relational.TableSpecification;
|
||||
import org.hibernate.metamodel.spi.relational.Value;
|
||||
import org.hibernate.metamodel.spi.source.ColumnSource;
|
||||
import org.hibernate.metamodel.spi.source.DerivedValueSource;
|
||||
import org.hibernate.metamodel.spi.source.LocalBindingContext;
|
||||
|
@ -51,11 +52,21 @@ public class RelationalValueBindingHelper {
|
|||
private final TableHelper tableHelper;
|
||||
private final NaturalIdUniqueKeyHelper uniqueKeyHelper;
|
||||
|
||||
RelationalValueBindingHelper(LocalBindingContext bindingContext) {
|
||||
public RelationalValueBindingHelper(LocalBindingContext bindingContext) {
|
||||
this.tableHelper = new TableHelper( bindingContext );
|
||||
this.uniqueKeyHelper = new NaturalIdUniqueKeyHelper();
|
||||
}
|
||||
|
||||
public boolean hasDerivedValue(List<RelationalValueBinding> relationalValueBindings) {
|
||||
for ( RelationalValueBinding relationalValueBinding : relationalValueBindings ) {
|
||||
if (relationalValueBinding.isDerived() ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public List<RelationalValueBinding> createRelationalValueBindings(
|
||||
final AttributeBindingContainer attributeBindingContainer,
|
||||
final RelationalValueSourceContainer valueSourceContainer,
|
||||
|
@ -168,4 +179,19 @@ public class RelationalValueBindingHelper {
|
|||
}
|
||||
return valueBindings;
|
||||
}
|
||||
|
||||
public List<RelationalValueBinding> bindInverseRelationalValueBindings(
|
||||
TableSpecification table,
|
||||
List<? extends Value> values) {
|
||||
final List<RelationalValueBinding> relationalValueBindings =
|
||||
new ArrayList<RelationalValueBinding>( values.size() );
|
||||
for ( Value value : values ) {
|
||||
final RelationalValueBinding relationalValueBinding =
|
||||
value.getValueType() == Value.ValueType.COLUMN ?
|
||||
new RelationalValueBinding( table, (Column) value, false, false ) :
|
||||
new RelationalValueBinding( table, (DerivedValue) value );
|
||||
relationalValueBindings.add( relationalValueBinding );
|
||||
}
|
||||
return relationalValueBindings;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
package org.hibernate.metamodel.internal;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
|
@ -35,7 +36,6 @@ import org.jboss.logging.Logger;
|
|||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.metamodel.spi.binding.EntityBinding;
|
||||
import org.hibernate.metamodel.spi.relational.Column;
|
||||
import org.hibernate.metamodel.spi.source.AggregatedCompositeIdentifierSource;
|
||||
import org.hibernate.metamodel.spi.source.AttributeSource;
|
||||
|
@ -50,7 +50,6 @@ 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.ToOneAttributeSource;
|
||||
import org.hibernate.metamodel.spi.source.ToOneAttributeSourceNatureResolver;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
|
@ -67,10 +66,6 @@ public class SourceIndex {
|
|||
private final Map<AttributeSourceKey, AttributeSourceKey> mappedByAttributeKeysByOwnerAttributeKeys =
|
||||
new HashMap<AttributeSourceKey, AttributeSourceKey>();
|
||||
|
||||
public void indexRootEntitySource(final RootEntitySource entitySource) {
|
||||
indexEntitySource( entitySource, entitySource );
|
||||
}
|
||||
|
||||
public void indexEntitySource(final RootEntitySource rootEntitySource, final EntitySource entitySource) {
|
||||
String entityName = entitySource.getEntityName();
|
||||
EntitySourceIndex entitySourceIndex = new EntitySourceIndex( this, rootEntitySource, entitySource );
|
||||
|
@ -79,15 +74,18 @@ public class SourceIndex {
|
|||
indexAttributes( entitySourceIndex );
|
||||
}
|
||||
|
||||
public void resolveAssociationSources(EntityBinding entityBinding) {
|
||||
entitySourceIndexByEntityName.get( entityBinding.getEntityName() ).resolveAssociationSources( entityBinding );
|
||||
public void resolveAssociationSources(EntityHierarchyHelper.LocalBindingContextExecutionContext bindingContextContext) {
|
||||
entitySourceIndexByEntityName
|
||||
.get( bindingContextContext.getEntityBinding().getEntityName() )
|
||||
.resolveAttributeSources( bindingContextContext );
|
||||
}
|
||||
|
||||
public Map<AttributeSourceKey, SingularAttributeSource> getSingularAttributeSources(
|
||||
String entityName,
|
||||
boolean isMappedBy,
|
||||
SingularAttributeSource.Nature nature) {
|
||||
final EntitySourceIndex entitySourceIndex = entitySourceIndexByEntityName.get( entityName );
|
||||
return entitySourceIndex.getSingularAttributeSources( nature );
|
||||
return entitySourceIndex.getSingularAttributeSources( isMappedBy, nature );
|
||||
}
|
||||
|
||||
public Map<AttributeSourceKey, PluralAttributeSource> getPluralAttributeSources(
|
||||
|
@ -278,11 +276,15 @@ public class SourceIndex {
|
|||
private final SourceIndex sourceIndex;
|
||||
private final RootEntitySource rootEntitySource;
|
||||
private final EntitySource entitySource;
|
||||
private final Map<SingularAttributeSource.Nature, Map<AttributeSourceKey, SingularAttributeSource>> identifierAttributeSourcesByNature =
|
||||
new HashMap<SingularAttributeSource.Nature, Map<AttributeSourceKey, SingularAttributeSource>>();
|
||||
// TODO: split out inverse and non-inverse SingularAttributeSource maps.
|
||||
private final Map<SingularAttributeSource.Nature, Map<AttributeSourceKey, SingularAttributeSource>> singularAttributeSourcesByNature =
|
||||
new HashMap<SingularAttributeSource.Nature, Map<AttributeSourceKey, SingularAttributeSource>>();
|
||||
private final Map<SingularAttributeSource.Nature, Map<AttributeSourceKey, SingularAttributeSource>>
|
||||
identifierAttributeSourcesByNature = new EnumMap<SingularAttributeSource.Nature, Map<AttributeSourceKey, SingularAttributeSource>>( SingularAttributeSource.Nature.class );
|
||||
private final Map<SingularAttributeSource.Nature, Map<AttributeSourceKey, SingularAttributeSource>>
|
||||
nonMappedBySingularAttributeSourcesByNature = new EnumMap<SingularAttributeSource.Nature, Map<AttributeSourceKey, SingularAttributeSource>>( SingularAttributeSource.Nature.class );
|
||||
private final Map<SingularAttributeSource.Nature, Map<AttributeSourceKey, SingularAttributeSource>>
|
||||
mappedBySingularAttributeSourcesByNature = new EnumMap<SingularAttributeSource.Nature, Map<AttributeSourceKey, SingularAttributeSource>>( SingularAttributeSource.Nature.class );
|
||||
private final Map<AttributeSourceKey, SingularAttributeSource> unresolvedSingularAttributeSourcesByKey =
|
||||
new HashMap<AttributeSourceKey, SingularAttributeSource>();
|
||||
|
||||
// TODO: the following should not need to be LinkedHashMap, but it appears that some unit tests
|
||||
// depend on the ordering
|
||||
// TODO: rework nonInversePluralAttributeSourcesByKey and inversePluralAttributeSourcesByKey
|
||||
|
@ -291,10 +293,6 @@ public class SourceIndex {
|
|||
private final Map<AttributeSourceKey, PluralAttributeSource> inversePluralAttributeSourcesByKey =
|
||||
new LinkedHashMap<AttributeSourceKey, PluralAttributeSource>();
|
||||
|
||||
private EntitySourceIndex(final SourceIndex sourceIndex, final RootEntitySource rootEntitySource) {
|
||||
this( sourceIndex, rootEntitySource, rootEntitySource );
|
||||
}
|
||||
|
||||
private EntitySourceIndex(
|
||||
final SourceIndex sourceIndex,
|
||||
final RootEntitySource rootEntitySource,
|
||||
|
@ -310,12 +308,21 @@ public class SourceIndex {
|
|||
boolean isInIdentifier) {
|
||||
final AttributeSourceKey attributeSourceKey =
|
||||
new AttributeSourceKey( entitySource.getEntityName(), pathBase, attributeSource.getName() );
|
||||
if ( attributeSource.getNature() == null ) {
|
||||
unresolvedSingularAttributeSourcesByKey.put( attributeSourceKey, attributeSource );
|
||||
return;
|
||||
}
|
||||
|
||||
final Map<SingularAttributeSource.Nature, Map<AttributeSourceKey, SingularAttributeSource>> map;
|
||||
if ( isInIdentifier ) {
|
||||
map = identifierAttributeSourcesByNature;
|
||||
}
|
||||
else if ( ToOneAttributeSource.class.isInstance( attributeSource ) &&
|
||||
ToOneAttributeSource.class.cast( attributeSource ).isMappedBy() ) {
|
||||
map = mappedBySingularAttributeSourcesByNature;
|
||||
}
|
||||
else {
|
||||
map = singularAttributeSourcesByNature;
|
||||
map = nonMappedBySingularAttributeSourcesByNature;
|
||||
}
|
||||
indexSingularAttributeSource(
|
||||
attributeSourceKey,
|
||||
|
@ -344,10 +351,14 @@ public class SourceIndex {
|
|||
}
|
||||
|
||||
private Map<AttributeSourceKey, SingularAttributeSource> getSingularAttributeSources(
|
||||
boolean isMappedBy,
|
||||
SingularAttributeSource.Nature nature) {
|
||||
final Map<AttributeSourceKey, SingularAttributeSource> entries;
|
||||
if ( singularAttributeSourcesByNature.containsKey( nature ) ) {
|
||||
entries = Collections.unmodifiableMap( singularAttributeSourcesByNature.get( nature ) );
|
||||
if ( isMappedBy && mappedBySingularAttributeSourcesByNature.containsKey( nature ) ) {
|
||||
entries = Collections.unmodifiableMap( mappedBySingularAttributeSourcesByNature.get( nature ) );
|
||||
}
|
||||
else if ( !isMappedBy && nonMappedBySingularAttributeSourcesByNature.containsKey( nature ) ) {
|
||||
entries = Collections.unmodifiableMap( nonMappedBySingularAttributeSourcesByNature.get( nature ) );
|
||||
}
|
||||
else {
|
||||
entries = Collections.emptyMap();
|
||||
|
@ -383,119 +394,80 @@ public class SourceIndex {
|
|||
return Collections.unmodifiableMap( map );
|
||||
}
|
||||
|
||||
private void resolveAssociationSources(final EntityBinding entityBinding) {
|
||||
// Cycle through non-inverse plural attributes.
|
||||
for ( Map.Entry<AttributeSourceKey,PluralAttributeSource> entry : inversePluralAttributeSourcesByKey.entrySet() ) {
|
||||
final AttributeSourceKey pluralAttributeSourceKey = entry.getKey();
|
||||
final PluralAttributeSource pluralAttributeSource = entry.getValue();
|
||||
private void resolveAttributeSources(EntityHierarchyHelper.LocalBindingContextExecutionContext bindingContextContext) {
|
||||
final AttributeSourceResolutionContext sourceResolutionContext =
|
||||
new AttributeSourceResolutionContextImpl( bindingContextContext );
|
||||
// Resolve plural attributes.
|
||||
for ( PluralAttributeSource pluralAttributeSource : inversePluralAttributeSourcesByKey.values() ) {
|
||||
if ( pluralAttributeSource.getMappedBy() != null ) {
|
||||
// This plural attribute is mappedBy the opposite side of the association,
|
||||
// so it needs to be resolved.
|
||||
// TODO: this should really just resolve PluralAttributeElementSource.Nature
|
||||
pluralAttributeSource.resolvePluralAttributeElementSource(
|
||||
new AttributeSourceResolutionContext() {
|
||||
@Override
|
||||
public IdentifierSource resolveIdentifierSource(String entityName) {
|
||||
return sourceIndex.entitySourceIndex( entityName ).rootEntitySource.getIdentifierSource();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AttributeSource resolveAttributeSource(String referencedEntityName, String mappedBy) {
|
||||
AttributeSourceKey ownerAttributeSourceKey = new AttributeSourceKey( referencedEntityName, mappedBy );
|
||||
AttributeSource ownerAttributeSource = sourceIndex.attributeSource( referencedEntityName, mappedBy );
|
||||
// TODO: is this needed? if so, make more obvious and rename method.
|
||||
// If it's not needed, then resolvePluralAttributeElementSource() and
|
||||
// and resolvePluralAttributeIndexSource() can use the same
|
||||
// AttributeSourceResolutionContext.
|
||||
sourceIndex.addMappedByAssociationByOwnerAssociation(
|
||||
ownerAttributeSourceKey,
|
||||
pluralAttributeSourceKey
|
||||
);
|
||||
return ownerAttributeSource;
|
||||
}
|
||||
}
|
||||
);
|
||||
pluralAttributeSource.resolvePluralAttributeElementSource( sourceResolutionContext );
|
||||
}
|
||||
if ( IndexedPluralAttributeSource.class.isInstance( pluralAttributeSource ) ) {
|
||||
IndexedPluralAttributeSource indexedPluralAttributeSource =
|
||||
(IndexedPluralAttributeSource) pluralAttributeSource;
|
||||
indexedPluralAttributeSource.resolvePluralAttributeIndexSource(
|
||||
new AttributeSourceResolutionContext() {
|
||||
@Override
|
||||
public IdentifierSource resolveIdentifierSource(String entityName) {
|
||||
return sourceIndex.entitySourceIndex( entityName ).rootEntitySource.getIdentifierSource();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AttributeSource resolveAttributeSource(String referencedEntityName, String mappedBy) {;
|
||||
return sourceIndex.attributeSource( referencedEntityName, mappedBy );
|
||||
}
|
||||
}
|
||||
);
|
||||
indexedPluralAttributeSource.resolvePluralAttributeIndexSource( sourceResolutionContext );
|
||||
}
|
||||
}
|
||||
|
||||
for ( Map.Entry<AttributeSourceKey,PluralAttributeSource> entry : nonInversePluralAttributeSourcesByKey.entrySet() ) {
|
||||
final AttributeSourceKey pluralAttributeSourceKey = entry.getKey();
|
||||
final PluralAttributeSource pluralAttributeSource = entry.getValue();
|
||||
for ( PluralAttributeSource pluralAttributeSource : nonInversePluralAttributeSourcesByKey.values() ) {
|
||||
if ( IndexedPluralAttributeSource.class.isInstance( pluralAttributeSource ) ) {
|
||||
IndexedPluralAttributeSource indexedPluralAttributeSource =
|
||||
(IndexedPluralAttributeSource) pluralAttributeSource;
|
||||
indexedPluralAttributeSource.resolvePluralAttributeIndexSource(
|
||||
new AttributeSourceResolutionContext() {
|
||||
@Override
|
||||
public IdentifierSource resolveIdentifierSource(String entityName) {
|
||||
return sourceIndex.entitySourceIndex( entityName ).rootEntitySource.getIdentifierSource();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AttributeSource resolveAttributeSource(String referencedEntityName, String mappedBy) {;
|
||||
return sourceIndex.attributeSource( referencedEntityName, mappedBy );
|
||||
}
|
||||
}
|
||||
);
|
||||
indexedPluralAttributeSource.resolvePluralAttributeIndexSource( sourceResolutionContext );
|
||||
}
|
||||
}
|
||||
|
||||
final Map<AttributeSourceKey,SingularAttributeSource> unresolvedSingularAttributeSourceMap =
|
||||
singularAttributeSourcesByNature.get( null );
|
||||
if ( unresolvedSingularAttributeSourceMap != null ) {
|
||||
// cycle through unresolved SingularAttributeSource.
|
||||
// TODO: rework so approach is similar to one-to-many/many-to-many resolution.
|
||||
for ( Iterator<Map.Entry<AttributeSourceKey,SingularAttributeSource>> it = unresolvedSingularAttributeSourceMap.entrySet().iterator(); it.hasNext(); ) {
|
||||
final Map.Entry<AttributeSourceKey,SingularAttributeSource> entry = it.next();
|
||||
final AttributeSourceKey attributeSourceKey = entry.getKey();
|
||||
final SingularAttributeSource attributeSource = entry.getValue();
|
||||
if ( !ToOneAttributeSource.class.isInstance( attributeSource ) ) {
|
||||
throw new AssertionFailure(
|
||||
String.format( "Only a ToOneAttributeSource is expected to have a null nature; attribute: %s ", attributeSourceKey )
|
||||
);
|
||||
}
|
||||
ToOneAttributeSource toOneAttributeSource = (ToOneAttributeSource) attributeSource;
|
||||
toOneAttributeSource.resolveToOneAttributeSourceNature(
|
||||
new ToOneAttributeSourceNatureResolver.ToOneAttributeSourceNatureResolutionContext() {
|
||||
|
||||
@Override
|
||||
public boolean areIdentifierColumnsDefined() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Column> getIdentifierColumns() {
|
||||
// TODO: should this return columns from EntityIdentifier???
|
||||
// (broken for joined-subclass)
|
||||
return entityBinding.getPrimaryTable().getPrimaryKey().getColumns();
|
||||
}
|
||||
}
|
||||
// cycle through unresolved SingularAttributeSource.
|
||||
// TODO: rework so approach is similar to one-to-many/many-to-many resolution.
|
||||
for ( Iterator<Map.Entry<AttributeSourceKey,SingularAttributeSource>> it = unresolvedSingularAttributeSourcesByKey.entrySet().iterator(); it.hasNext(); ) {
|
||||
final Map.Entry<AttributeSourceKey,SingularAttributeSource> entry = it.next();
|
||||
final AttributeSourceKey attributeSourceKey = entry.getKey();
|
||||
final SingularAttributeSource attributeSource = entry.getValue();
|
||||
if ( !ToOneAttributeSource.class.isInstance( attributeSource ) ) {
|
||||
throw new AssertionFailure(
|
||||
String.format( "Only a ToOneAttributeSource is expected to have a null nature; attribute: %s ", attributeSourceKey )
|
||||
);
|
||||
if ( toOneAttributeSource.getNature() == null ) {
|
||||
throw new AssertionFailure(
|
||||
String.format( "Null nature should have been resolved: %s ", attributeSourceKey )
|
||||
);
|
||||
}
|
||||
it.remove();
|
||||
indexSingularAttributeSource( attributeSourceKey,attributeSource, singularAttributeSourcesByNature );
|
||||
}
|
||||
ToOneAttributeSource toOneAttributeSource = (ToOneAttributeSource) attributeSource;
|
||||
toOneAttributeSource.resolveToOneAttributeSource( sourceResolutionContext );
|
||||
if ( toOneAttributeSource.getNature() == null ) {
|
||||
throw new AssertionFailure(
|
||||
String.format( "Null nature should have been resolved: %s ", attributeSourceKey )
|
||||
);
|
||||
}
|
||||
indexSingularAttributeSource(
|
||||
attributeSourceKey,
|
||||
attributeSource,
|
||||
toOneAttributeSource.isMappedBy() ?
|
||||
mappedBySingularAttributeSourcesByNature :
|
||||
nonMappedBySingularAttributeSourcesByNature
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class AttributeSourceResolutionContextImpl implements AttributeSourceResolutionContext {
|
||||
private final EntityHierarchyHelper.LocalBindingContextExecutionContext bindingContextContext;
|
||||
|
||||
public AttributeSourceResolutionContextImpl(
|
||||
EntityHierarchyHelper.LocalBindingContextExecutionContext bindingContextContext) {
|
||||
this.bindingContextContext = bindingContextContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IdentifierSource resolveIdentifierSource(String entityName) {
|
||||
return bindingContextContext.getRootEntitySource().getIdentifierSource();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AttributeSource resolveAttributeSource(String entityName, String attributeName) {
|
||||
return sourceIndex.attributeSource( entityName, attributeName );
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Column> resolveIdentifierColumns() {
|
||||
return bindingContextContext.getEntityBinding().getPrimaryTable().getPrimaryKey().getColumns();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ import org.jboss.logging.Logger;
|
|||
import org.hibernate.TruthValue;
|
||||
import org.hibernate.cfg.ObjectNameNormalizer;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.metamodel.spi.binding.AttributeBindingContainer;
|
||||
import org.hibernate.metamodel.spi.relational.Column;
|
||||
import org.hibernate.metamodel.spi.relational.Identifier;
|
||||
import org.hibernate.metamodel.spi.relational.Schema;
|
||||
|
@ -38,9 +39,11 @@ import org.hibernate.metamodel.spi.source.ColumnSource;
|
|||
import org.hibernate.metamodel.spi.source.InLineViewSource;
|
||||
import org.hibernate.metamodel.spi.source.LocalBindingContext;
|
||||
import org.hibernate.metamodel.spi.source.MappingDefaults;
|
||||
import org.hibernate.metamodel.spi.source.SingularAttributeSource;
|
||||
import org.hibernate.metamodel.spi.source.SizeSource;
|
||||
import org.hibernate.metamodel.spi.source.TableSource;
|
||||
import org.hibernate.metamodel.spi.source.TableSpecificationSource;
|
||||
import org.hibernate.metamodel.spi.source.ToOneAttributeSource;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* 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.resolver;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.metamodel.spi.binding.AttributeBindingContainer;
|
||||
import org.hibernate.metamodel.spi.binding.EntityBinding;
|
||||
import org.hibernate.metamodel.spi.binding.RelationalValueBinding;
|
||||
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.relational.Column;
|
||||
import org.hibernate.metamodel.spi.relational.ForeignKey;
|
||||
import org.hibernate.metamodel.spi.relational.TableSpecification;
|
||||
import org.hibernate.metamodel.spi.source.ManyToManyPluralAttributeElementSource;
|
||||
import org.hibernate.metamodel.spi.source.PluralAttributeSource;
|
||||
import org.hibernate.metamodel.spi.source.ToOneAttributeSource;
|
||||
|
||||
/**
|
||||
+ * @author Gail Badner
|
||||
+ */
|
||||
public interface AssociationRelationalBindingResolver {
|
||||
|
||||
SingularAttributeBinding resolveOneToOneReferencedAttributeBinding(
|
||||
final ToOneAttributeSource attributeSource,
|
||||
final EntityBinding referencedEntityBinding);
|
||||
|
||||
List<RelationalValueBinding> resolveOneToOneRelationalValueBindings(
|
||||
final ToOneAttributeSource attributeSource,
|
||||
final AttributeBindingContainer attributeBindingContainer,
|
||||
final SingularAttributeBinding referencedAttributeBinding);
|
||||
|
||||
ForeignKey resolveOneToOneForeignKey(
|
||||
ToOneAttributeSource attributeSource,
|
||||
TableSpecification sourceTable,
|
||||
List<Column> sourceColumns,
|
||||
EntityBinding referencedEntityBinding);
|
||||
|
||||
SingularAttributeBinding resolveManyToOneReferencedAttributeBinding(
|
||||
final AttributeBindingContainer attributeBindingContainer,
|
||||
final ToOneAttributeSource attributeSource,
|
||||
final EntityBinding referencedEntityBinding);
|
||||
|
||||
// TODO: referencedAttributeBinding and referencedEntityBinding are both included due to a bug that can
|
||||
// cause entityBinding != entityBinding.hierarchyDetails.getEntityIdentifier().getAttributeBinding().getContainer()
|
||||
List<RelationalValueBinding> resolveManyToOneRelationalValueBindings(
|
||||
final ToOneAttributeSource attributeSource,
|
||||
final AttributeBindingContainer attributeBindingContainer,
|
||||
final SingularAttributeBinding referencedAttributeBinding,
|
||||
final EntityBinding referencedEntityBinding);
|
||||
|
||||
ForeignKey resolveManyToOneForeignKey(
|
||||
ToOneAttributeSource attributeSource,
|
||||
AttributeBindingContainer attributeBindingContainer,
|
||||
List<RelationalValueBinding> relationalValueBindings,
|
||||
EntityBinding referencedEntityBinding);
|
||||
|
||||
List<RelationalValueBinding> resolveManyToManyElementRelationalValueBindings(
|
||||
final EntityBinding entityBinding,
|
||||
final ManyToManyPluralAttributeElementSource elementSource,
|
||||
final TableSpecification collectionTable,
|
||||
final EntityBinding referencedEntityBinding);
|
||||
|
||||
ForeignKey resolveManyToManyElementForeignKey(
|
||||
final EntityBinding entityBinding,
|
||||
final ManyToManyPluralAttributeElementSource elementSource,
|
||||
final TableSpecification collectionTable,
|
||||
final List<RelationalValueBinding> relationalValueBindings,
|
||||
final EntityBinding referencedEntityBinding);
|
||||
|
||||
TableSpecification resolveManyToManyCollectionTable(
|
||||
PluralAttributeSource pluralAttributeSource,
|
||||
String attributePath,
|
||||
EntityBinding entityBinding,
|
||||
EntityBinding referencedEntityBinding);
|
||||
|
||||
List<RelationalValueBinding> resolvePluralAttributeKeyRelationalValueBindings(
|
||||
final PluralAttributeSource attributeSource,
|
||||
final EntityBinding entityBinding,
|
||||
final TableSpecification collectionTable,
|
||||
final EntityBinding referencedEntityBinding);
|
||||
|
||||
ForeignKey resolvePluralAttributeKeyForeignKey(
|
||||
final PluralAttributeSource attributeSource,
|
||||
final EntityBinding entityBinding,
|
||||
final TableSpecification collectionTable,
|
||||
final List<RelationalValueBinding> relationalValueBindings,
|
||||
final EntityBinding referencedEntityBinding);
|
||||
|
||||
SingularAttributeBinding resolvePluralAttributeKeyReferencedBinding(
|
||||
final AttributeBindingContainer attributeBindingContainer,
|
||||
final PluralAttributeSource attributeSource);
|
||||
}
|
|
@ -0,0 +1,350 @@
|
|||
/*
|
||||
* 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.resolver;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.cfg.NotYetImplementedException;
|
||||
import org.hibernate.metamodel.internal.ForeignKeyHelper;
|
||||
import org.hibernate.metamodel.internal.RelationalValueBindingHelper;
|
||||
import org.hibernate.metamodel.spi.binding.AttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.AttributeBindingContainer;
|
||||
import org.hibernate.metamodel.spi.binding.EntityBinding;
|
||||
import org.hibernate.metamodel.spi.binding.ManyToManyPluralAttributeElementBinding;
|
||||
import org.hibernate.metamodel.spi.binding.ManyToOneAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.PluralAttributeBinding;
|
||||
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.relational.Column;
|
||||
import org.hibernate.metamodel.spi.relational.ForeignKey;
|
||||
import org.hibernate.metamodel.spi.relational.TableSpecification;
|
||||
import org.hibernate.metamodel.spi.source.AssociationSource;
|
||||
import org.hibernate.metamodel.spi.source.LocalBindingContext;
|
||||
import org.hibernate.metamodel.spi.source.ManyToManyPluralAttributeElementSource;
|
||||
import org.hibernate.metamodel.spi.source.MappedByAssociationSource;
|
||||
import org.hibernate.metamodel.spi.source.PluralAttributeSource;
|
||||
import org.hibernate.metamodel.spi.source.ToOneAttributeSource;
|
||||
import org.hibernate.type.ForeignKeyDirection;
|
||||
|
||||
/**
|
||||
+ * @author Gail Badner
|
||||
+ */
|
||||
public class MappedByAssociationRelationalBindingResolverImpl implements AssociationRelationalBindingResolver {
|
||||
private final LocalBindingContext bindingContext;
|
||||
private final ForeignKeyHelper foreignKeyHelper;
|
||||
private final RelationalValueBindingHelper relationalValueBindingHelper;
|
||||
|
||||
public MappedByAssociationRelationalBindingResolverImpl(LocalBindingContext bindingContext) {
|
||||
this.bindingContext = bindingContext;
|
||||
this.foreignKeyHelper = new ForeignKeyHelper( bindingContext );
|
||||
this.relationalValueBindingHelper = new RelationalValueBindingHelper( bindingContext );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SingularAttributeBinding resolveOneToOneReferencedAttributeBinding(
|
||||
ToOneAttributeSource attributeSource,
|
||||
EntityBinding referencedEntityBinding) {
|
||||
return (SingularAttributeBinding) referencedEntityBinding.locateAttributeBindingByPath(
|
||||
getMappedByAssociationSource( attributeSource ).getMappedBy(),
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RelationalValueBinding> resolveOneToOneRelationalValueBindings(
|
||||
final ToOneAttributeSource attributeSource,
|
||||
AttributeBindingContainer attributeBindingContainer,
|
||||
SingularAttributeBinding referencedAttributeBinding) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ForeignKey resolveOneToOneForeignKey(
|
||||
ToOneAttributeSource attributeSource,
|
||||
TableSpecification sourceTable,
|
||||
List<Column> sourceColumns,
|
||||
EntityBinding referencedEntityBinding) {
|
||||
// TODO: get rid of this duplication!!!
|
||||
if ( attributeSource.getForeignKeyDirection() == ForeignKeyDirection.TO_PARENT ) {
|
||||
throw new AssertionFailure( "Cannot create a foreign key for one-to-one with foreign key direction going to the parent." );
|
||||
}
|
||||
final List<Column> targetColumns = foreignKeyHelper.determineForeignKeyTargetColumns(
|
||||
referencedEntityBinding,
|
||||
attributeSource
|
||||
);
|
||||
final TableSpecification targetTable = foreignKeyHelper.determineForeignKeyTargetTable(
|
||||
referencedEntityBinding,
|
||||
attributeSource
|
||||
);
|
||||
return foreignKeyHelper.locateOrCreateForeignKey(
|
||||
attributeSource.getExplicitForeignKeyName(),
|
||||
sourceTable,
|
||||
sourceColumns,
|
||||
targetTable,
|
||||
targetColumns
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SingularAttributeBinding resolveManyToOneReferencedAttributeBinding(
|
||||
AttributeBindingContainer attributeBindingContainer,
|
||||
ToOneAttributeSource attributeSource,
|
||||
EntityBinding referencedEntityBinding) {
|
||||
// This is a mappedBy many-to-one. This should only happen when the owning many-to-one uses a join table.
|
||||
// TODO: confirm the above is true.
|
||||
final SecondaryTable ownerSecondaryTable = getOwnerSecondaryTable(
|
||||
getMappedByAssociationSource( attributeSource ),
|
||||
referencedEntityBinding
|
||||
);
|
||||
return referencedEntityBinding.locateAttributeBinding(
|
||||
ownerSecondaryTable.getForeignKeyReference().getTargetTable(),
|
||||
ownerSecondaryTable.getForeignKeyReference().getTargetColumns(),
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RelationalValueBinding> resolveManyToOneRelationalValueBindings(
|
||||
ToOneAttributeSource attributeSource,
|
||||
AttributeBindingContainer attributeBindingContainer,
|
||||
SingularAttributeBinding referencedAttributeBinding,
|
||||
EntityBinding referencedEntityBinding) {
|
||||
// A many-to-one can only have mappedBy specified if there is a join table.
|
||||
// TODO: confirm this is true.
|
||||
// The relational value bindings for the attribute being processed
|
||||
// will contain the columns that make up the FK join tables on the
|
||||
// owner's secondary table.
|
||||
final SecondaryTable ownerSecondaryTable = getOwnerSecondaryTable(
|
||||
getMappedByAssociationSource( attributeSource ),
|
||||
referencedEntityBinding
|
||||
);
|
||||
return relationalValueBindingHelper.bindInverseRelationalValueBindings(
|
||||
ownerSecondaryTable.getForeignKeyReference().getSourceTable(),
|
||||
ownerSecondaryTable.getForeignKeyReference().getSourceColumns()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ForeignKey resolveManyToOneForeignKey(
|
||||
ToOneAttributeSource attributeSource,
|
||||
AttributeBindingContainer attributeBindingContainer,
|
||||
List<RelationalValueBinding> relationalValueBindings,
|
||||
EntityBinding referencedEntityBinding) {
|
||||
// A many-to-one can only have mappedBy specified if there is a join table.
|
||||
// TODO: confirm this is true.
|
||||
final SecondaryTable ownerSecondaryTable = getOwnerSecondaryTable(
|
||||
getMappedByAssociationSource( attributeSource ),
|
||||
referencedEntityBinding
|
||||
);
|
||||
return ownerSecondaryTable.getForeignKeyReference();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RelationalValueBinding> resolveManyToManyElementRelationalValueBindings(
|
||||
final EntityBinding entityBinding,
|
||||
final ManyToManyPluralAttributeElementSource elementSource,
|
||||
final TableSpecification collectionTable,
|
||||
final EntityBinding referencedEntityBinding) {
|
||||
{
|
||||
final AttributeBinding ownerAttributeBinding = getOwnerAttributeBinding(
|
||||
getMappedByAssociationSource( elementSource )
|
||||
);
|
||||
final List<RelationalValueBinding> relationalValueBindings;
|
||||
if ( ownerAttributeBinding.getAttribute().isSingular() ) {
|
||||
// the owner is a many-to-one on a join table; the target will be the FK target
|
||||
// for the secondary table.
|
||||
final SecondaryTable ownerSecondaryTable =
|
||||
referencedEntityBinding.getSecondaryTables().get( collectionTable.getLogicalName() );
|
||||
relationalValueBindings = relationalValueBindingHelper.bindInverseRelationalValueBindings(
|
||||
collectionTable,
|
||||
ownerSecondaryTable.getForeignKeyReference().getSourceColumns()
|
||||
);
|
||||
}
|
||||
else {
|
||||
final PluralAttributeBinding ownerPluralAttributeBinding = (PluralAttributeBinding) ownerAttributeBinding;
|
||||
relationalValueBindings = relationalValueBindingHelper.bindInverseRelationalValueBindings(
|
||||
collectionTable,
|
||||
ownerPluralAttributeBinding.getPluralAttributeKeyBinding().getValues()
|
||||
);
|
||||
}
|
||||
return relationalValueBindings;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ForeignKey resolveManyToManyElementForeignKey(
|
||||
final EntityBinding entityBinding,
|
||||
final ManyToManyPluralAttributeElementSource elementSource,
|
||||
final TableSpecification collectionTable,
|
||||
final List<RelationalValueBinding> relationalValueBindings,
|
||||
final EntityBinding referencedEntityBinding) {
|
||||
final AttributeBinding ownerAttributeBinding = getOwnerAttributeBinding(
|
||||
getMappedByAssociationSource( elementSource )
|
||||
);
|
||||
if ( ownerAttributeBinding.getAttribute().isSingular() ) {
|
||||
// the owner is a many-to-one on a join table; the target will be the FK target
|
||||
// for the secondary table.
|
||||
final SecondaryTable ownerSecondaryTable =
|
||||
referencedEntityBinding.getSecondaryTables().get( collectionTable.getLogicalName() );
|
||||
return ownerSecondaryTable.getForeignKeyReference();
|
||||
}
|
||||
else {
|
||||
final PluralAttributeBinding ownerPluralAttributeBinding = (PluralAttributeBinding) ownerAttributeBinding;
|
||||
return ownerPluralAttributeBinding.getPluralAttributeKeyBinding().getForeignKey();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableSpecification resolveManyToManyCollectionTable(
|
||||
PluralAttributeSource pluralAttributeSource,
|
||||
String attributePath,
|
||||
EntityBinding entityBinding,
|
||||
EntityBinding referencedEntityBinding) {
|
||||
final AttributeBinding ownerAttributeBinding = getOwnerAttributeBinding(
|
||||
getMappedByAssociationSource( (AssociationSource) pluralAttributeSource.getElementSource() )
|
||||
);
|
||||
return ownerAttributeBinding.getAttribute().isSingular() ?
|
||||
( (SingularAssociationAttributeBinding) ownerAttributeBinding ).getTable() :
|
||||
( (PluralAttributeBinding) ownerAttributeBinding ).getPluralAttributeKeyBinding().getCollectionTable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RelationalValueBinding> resolvePluralAttributeKeyRelationalValueBindings(
|
||||
PluralAttributeSource attributeSource,
|
||||
EntityBinding entityBinding,
|
||||
TableSpecification collectionTable,
|
||||
EntityBinding referencedEntityBinding) {
|
||||
final AttributeBinding ownerAttributeBinding = getOwnerAttributeBinding(
|
||||
getMappedByAssociationSource( (AssociationSource) attributeSource.getElementSource() )
|
||||
);
|
||||
if ( ownerAttributeBinding.getAttribute().isSingular() ) {
|
||||
return ( (ManyToOneAttributeBinding) ownerAttributeBinding ).getRelationalValueBindings();
|
||||
}
|
||||
else {
|
||||
final PluralAttributeBinding pluralOwnerAttributeBinding = (PluralAttributeBinding) ownerAttributeBinding;
|
||||
final ManyToManyPluralAttributeElementBinding ownerElementBinding =
|
||||
(ManyToManyPluralAttributeElementBinding) pluralOwnerAttributeBinding.getPluralAttributeElementBinding();
|
||||
return ownerElementBinding.getRelationalValueBindings();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ForeignKey resolvePluralAttributeKeyForeignKey(
|
||||
PluralAttributeSource attributeSource,
|
||||
EntityBinding entityBinding,
|
||||
TableSpecification collectionTable,
|
||||
List<RelationalValueBinding> sourceRelationalValueBindings,
|
||||
EntityBinding referencedEntityBinding) {
|
||||
final AttributeBinding ownerAttributeBinding = getOwnerAttributeBinding(
|
||||
getMappedByAssociationSource( (AssociationSource) attributeSource.getElementSource() )
|
||||
);
|
||||
final ForeignKey foreignKey;
|
||||
if ( ownerAttributeBinding.getAttribute().isSingular() ) {
|
||||
foreignKey = ( (ManyToOneAttributeBinding) ownerAttributeBinding ).getForeignKey();
|
||||
}
|
||||
else {
|
||||
final PluralAttributeBinding pluralOwnerAttributeBinding = (PluralAttributeBinding) ownerAttributeBinding;
|
||||
final ManyToManyPluralAttributeElementBinding ownerElementBinding =
|
||||
(ManyToManyPluralAttributeElementBinding) pluralOwnerAttributeBinding.getPluralAttributeElementBinding();
|
||||
foreignKey = ownerElementBinding.getForeignKey();
|
||||
}
|
||||
foreignKey.setDeleteRule( attributeSource.getKeySource().getOnDeleteAction() );
|
||||
return foreignKey;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public SingularAttributeBinding resolvePluralAttributeKeyReferencedBinding(
|
||||
AttributeBindingContainer attributeBindingContainer,
|
||||
PluralAttributeSource attributeSource) {
|
||||
final AttributeBinding ownerAttributeBinding = getOwnerAttributeBinding(
|
||||
getMappedByAssociationSource( (AssociationSource) attributeSource.getElementSource() )
|
||||
);
|
||||
final SingularAttributeBinding referencedAttributeBinding;
|
||||
if ( ownerAttributeBinding.getAttribute().isSingular() ) {
|
||||
referencedAttributeBinding =
|
||||
( (SingularAssociationAttributeBinding) ownerAttributeBinding ).getReferencedAttributeBinding();
|
||||
}
|
||||
else {
|
||||
final PluralAttributeBinding ownerPluralAttributeBinding = (PluralAttributeBinding) ownerAttributeBinding;
|
||||
final ManyToManyPluralAttributeElementBinding ownerElementBinding =
|
||||
(ManyToManyPluralAttributeElementBinding) ownerPluralAttributeBinding
|
||||
.getPluralAttributeElementBinding();
|
||||
referencedAttributeBinding = attributeBindingContainer.seekEntityBinding().locateAttributeBinding(
|
||||
ownerElementBinding.getForeignKey().getTargetTable(),
|
||||
ownerElementBinding.getForeignKey().getTargetColumns(),
|
||||
true
|
||||
);
|
||||
if ( referencedAttributeBinding == null ) {
|
||||
throw new NotYetImplementedException( "Referenced columns not used by an attribute binding is not supported yet." );
|
||||
}
|
||||
}
|
||||
return referencedAttributeBinding;
|
||||
}
|
||||
|
||||
private MappedByAssociationSource getMappedByAssociationSource(AssociationSource associationSource) {
|
||||
if ( !associationSource.isMappedBy() || !MappedByAssociationSource.class.isInstance( associationSource ) ) {
|
||||
throw new AssertionFailure( "Expected a MappedByAssociationSource." );
|
||||
}
|
||||
return (MappedByAssociationSource) associationSource;
|
||||
}
|
||||
|
||||
private AttributeBinding getOwnerAttributeBinding(MappedByAssociationSource associationSource) {
|
||||
final EntityBinding referencedEntityBinding = bindingContext.getMetadataImplementor().getEntityBinding(
|
||||
associationSource.getReferencedEntityName()
|
||||
);
|
||||
final AttributeBinding ownerAttributeBinding = referencedEntityBinding.locateAttributeBindingByPath(
|
||||
associationSource.getMappedBy(),
|
||||
true
|
||||
);
|
||||
if ( ownerAttributeBinding == null ) {
|
||||
throw bindingContext.makeMappingException(
|
||||
String.format(
|
||||
"Attribute not found: [%s.%s]",
|
||||
referencedEntityBinding.getEntityName(),
|
||||
associationSource.getMappedBy()
|
||||
)
|
||||
);
|
||||
}
|
||||
return ownerAttributeBinding;
|
||||
}
|
||||
|
||||
private SecondaryTable getOwnerSecondaryTable(
|
||||
MappedByAssociationSource attributeSource,
|
||||
EntityBinding referencedEntityBinding) {
|
||||
SingularAssociationAttributeBinding ownerAttributeBinding =
|
||||
(SingularAssociationAttributeBinding) referencedEntityBinding.locateAttributeBinding(
|
||||
attributeSource.getMappedBy()
|
||||
);
|
||||
TableSpecification table = ownerAttributeBinding.getTable();
|
||||
if ( referencedEntityBinding.getPrimaryTable().equals( table ) ) {
|
||||
throw new AssertionFailure( "many-to-one has mappedby specified but it does not use a join table." );
|
||||
}
|
||||
return referencedEntityBinding.getSecondaryTables().get( table.getLogicalName() );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,420 @@
|
|||
/*
|
||||
* 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.resolver;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.cfg.NamingStrategy;
|
||||
import org.hibernate.cfg.NotYetImplementedException;
|
||||
import org.hibernate.metamodel.internal.Binder;
|
||||
import org.hibernate.metamodel.internal.ForeignKeyHelper;
|
||||
import org.hibernate.metamodel.internal.ManyToManyCollectionTableNamingStrategyHelper;
|
||||
import org.hibernate.metamodel.internal.RelationalValueBindingHelper;
|
||||
import org.hibernate.metamodel.internal.TableHelper;
|
||||
import org.hibernate.metamodel.spi.binding.AttributeBindingContainer;
|
||||
import org.hibernate.metamodel.spi.binding.EntityBinding;
|
||||
import org.hibernate.metamodel.spi.binding.RelationalValueBinding;
|
||||
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.relational.Column;
|
||||
import org.hibernate.metamodel.spi.relational.ForeignKey;
|
||||
import org.hibernate.metamodel.spi.relational.TableSpecification;
|
||||
import org.hibernate.metamodel.spi.relational.Value;
|
||||
import org.hibernate.metamodel.spi.source.AssociationSource;
|
||||
import org.hibernate.metamodel.spi.source.ForeignKeyContributingSource;
|
||||
import org.hibernate.metamodel.spi.source.LocalBindingContext;
|
||||
import org.hibernate.metamodel.spi.source.ManyToManyPluralAttributeElementSource;
|
||||
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.RelationalValueSourceContainer;
|
||||
import org.hibernate.metamodel.spi.source.SingularAttributeSource;
|
||||
import org.hibernate.metamodel.spi.source.TableSpecificationSource;
|
||||
import org.hibernate.metamodel.spi.source.ToOneAttributeSource;
|
||||
import org.hibernate.type.ForeignKeyDirection;
|
||||
|
||||
/**
|
||||
+ * @author Gail Badner
|
||||
+ */
|
||||
public class StandardAssociationRelationalBindingResolverImpl implements AssociationRelationalBindingResolver {
|
||||
private final RelationalValueBindingHelper relationalValueBindingHelper;
|
||||
private final ForeignKeyHelper foreignKeyHelper;
|
||||
private final TableHelper tableHelper;
|
||||
|
||||
public StandardAssociationRelationalBindingResolverImpl(LocalBindingContext bindingContext) {
|
||||
this.relationalValueBindingHelper = new RelationalValueBindingHelper( bindingContext );
|
||||
this.foreignKeyHelper = new ForeignKeyHelper( bindingContext );
|
||||
this.tableHelper = new TableHelper( bindingContext );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SingularAttributeBinding resolveOneToOneReferencedAttributeBinding(
|
||||
ToOneAttributeSource attributeSource,
|
||||
EntityBinding referencedEntityBinding) {
|
||||
return resolveReferencedAttributeBinding( attributeSource, referencedEntityBinding );
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RelationalValueBinding> resolveOneToOneRelationalValueBindings(
|
||||
final ToOneAttributeSource attributeSource,
|
||||
AttributeBindingContainer attributeBindingContainer,
|
||||
SingularAttributeBinding referencedAttributeBinding) {
|
||||
if ( ! attributeSource.relationalValueSources().isEmpty() ) {
|
||||
final TableSpecification defaultTable =
|
||||
locateDefaultTableSpecificationForAttribute(
|
||||
attributeBindingContainer,
|
||||
attributeSource
|
||||
);
|
||||
return resolveRelationalValueBindings(
|
||||
attributeSource,
|
||||
attributeBindingContainer.seekEntityBinding(),
|
||||
defaultTable,
|
||||
false,
|
||||
attributeSource.getDefaultNamingStrategies(
|
||||
attributeBindingContainer.seekEntityBinding().getEntity().getName(),
|
||||
defaultTable.getLogicalName().getText(),
|
||||
referencedAttributeBinding
|
||||
)
|
||||
);
|
||||
}
|
||||
else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
private TableSpecification locateDefaultTableSpecificationForAttribute(
|
||||
final AttributeBindingContainer attributeBindingContainer,
|
||||
final SingularAttributeSource attributeSource) {
|
||||
return attributeSource.getContainingTableName() == null ?
|
||||
attributeBindingContainer.getPrimaryTable() :
|
||||
attributeBindingContainer.seekEntityBinding().locateTable( attributeSource.getContainingTableName() );
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ForeignKey resolveOneToOneForeignKey(
|
||||
ToOneAttributeSource attributeSource,
|
||||
TableSpecification sourceTable,
|
||||
List<Column> sourceColumns,
|
||||
EntityBinding referencedEntityBinding) {
|
||||
if ( attributeSource.getForeignKeyDirection() == ForeignKeyDirection.TO_PARENT ) {
|
||||
throw new AssertionFailure( "Cannot create a foreign key for one-to-one with foreign key direction going to the parent." );
|
||||
}
|
||||
|
||||
final TableSpecification targetTable = foreignKeyHelper.determineForeignKeyTargetTable(
|
||||
referencedEntityBinding,
|
||||
attributeSource
|
||||
);
|
||||
final List<Column> targetColumns = foreignKeyHelper.determineForeignKeyTargetColumns(
|
||||
referencedEntityBinding,
|
||||
attributeSource
|
||||
);
|
||||
return foreignKeyHelper.locateOrCreateForeignKey(
|
||||
attributeSource.getExplicitForeignKeyName(),
|
||||
sourceTable,
|
||||
sourceColumns,
|
||||
targetTable,
|
||||
targetColumns
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SingularAttributeBinding resolveManyToOneReferencedAttributeBinding(
|
||||
AttributeBindingContainer attributeBindingContainer,
|
||||
ToOneAttributeSource attributeSource,
|
||||
EntityBinding referencedEntityBinding) {
|
||||
return resolveReferencedAttributeBinding( attributeSource, referencedEntityBinding );
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RelationalValueBinding> resolveManyToOneRelationalValueBindings(
|
||||
ToOneAttributeSource attributeSource,
|
||||
AttributeBindingContainer attributeBindingContainer,
|
||||
SingularAttributeBinding referencedAttributeBinding,
|
||||
EntityBinding referencedEntityBinding) {
|
||||
final TableSpecification defaultTable =
|
||||
locateDefaultTableSpecificationForAttribute(
|
||||
attributeBindingContainer,
|
||||
attributeSource
|
||||
);
|
||||
return resolveRelationalValueBindings(
|
||||
attributeSource,
|
||||
attributeBindingContainer.seekEntityBinding(),
|
||||
defaultTable,
|
||||
false,
|
||||
attributeSource.getDefaultNamingStrategies(
|
||||
attributeBindingContainer.seekEntityBinding().getEntity().getName(),
|
||||
defaultTable.getLogicalName().getText(),
|
||||
referencedAttributeBinding
|
||||
)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ForeignKey resolveManyToOneForeignKey(
|
||||
ToOneAttributeSource attributeSource,
|
||||
AttributeBindingContainer attributeBindingContainer,
|
||||
List<RelationalValueBinding> relationalValueBindings,
|
||||
EntityBinding referencedEntityBinding) {
|
||||
final List<Column> targetColumns = foreignKeyHelper.determineForeignKeyTargetColumns(
|
||||
referencedEntityBinding,
|
||||
attributeSource
|
||||
);
|
||||
return locateOrCreateForeignKey(
|
||||
attributeSource,
|
||||
referencedEntityBinding,
|
||||
relationalValueBindings.get( 0 ).getTable(),
|
||||
relationalValueBindings,
|
||||
targetColumns
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RelationalValueBinding> resolveManyToManyElementRelationalValueBindings(
|
||||
final EntityBinding entityBinding,
|
||||
final ManyToManyPluralAttributeElementSource elementSource,
|
||||
final TableSpecification collectionTable,
|
||||
final EntityBinding referencedEntityBinding) {
|
||||
final List<Column> targetColumns =
|
||||
foreignKeyHelper.determineForeignKeyTargetColumns(
|
||||
referencedEntityBinding,
|
||||
elementSource
|
||||
);
|
||||
final List<Binder.DefaultNamingStrategy> namingStrategies = new ArrayList<Binder.DefaultNamingStrategy>( targetColumns.size() );
|
||||
for ( final Column targetColumn : targetColumns ) {
|
||||
namingStrategies.add(
|
||||
new Binder.DefaultNamingStrategy() {
|
||||
@Override
|
||||
public String defaultName(NamingStrategy namingStrategy) {
|
||||
return namingStrategy.foreignKeyColumnName(
|
||||
elementSource.getAttributeSource().getName(),
|
||||
referencedEntityBinding.getEntityName(),
|
||||
referencedEntityBinding.getPrimaryTableName(),
|
||||
targetColumn.getColumnName().getText()
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
return resolveRelationalValueBindings(
|
||||
elementSource,
|
||||
entityBinding,
|
||||
collectionTable,
|
||||
true,
|
||||
namingStrategies
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ForeignKey resolveManyToManyElementForeignKey(
|
||||
final EntityBinding entityBinding,
|
||||
final ManyToManyPluralAttributeElementSource elementSource,
|
||||
final TableSpecification collectionTable,
|
||||
final List<RelationalValueBinding> relationalValueBindings,
|
||||
final EntityBinding referencedEntityBinding) {
|
||||
final List<Column> targetColumns =
|
||||
foreignKeyHelper.determineForeignKeyTargetColumns(
|
||||
referencedEntityBinding,
|
||||
elementSource
|
||||
);
|
||||
return locateOrCreateForeignKey(
|
||||
elementSource,
|
||||
referencedEntityBinding,
|
||||
collectionTable,
|
||||
relationalValueBindings,
|
||||
targetColumns
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableSpecification resolveManyToManyCollectionTable(
|
||||
PluralAttributeSource pluralAttributeSource,
|
||||
String attributePath,
|
||||
EntityBinding entityBinding,
|
||||
EntityBinding referencedEntityBinding) {
|
||||
|
||||
final TableSpecificationSource collectionTableSource = pluralAttributeSource.getCollectionTableSpecificationSource();
|
||||
return tableHelper.createTable(
|
||||
collectionTableSource,
|
||||
new ManyToManyCollectionTableNamingStrategyHelper(
|
||||
attributePath,
|
||||
pluralAttributeSource.isInverse(),
|
||||
entityBinding,
|
||||
referencedEntityBinding
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RelationalValueBinding> resolvePluralAttributeKeyRelationalValueBindings(
|
||||
final PluralAttributeSource attributeSource,
|
||||
final EntityBinding entityBinding,
|
||||
final TableSpecification collectionTable,
|
||||
final EntityBinding referencedEntityBinding) {
|
||||
final PluralAttributeKeySource keySource = attributeSource.getKeySource();
|
||||
|
||||
final List<Column>targetColumns = foreignKeyHelper.determineForeignKeyTargetColumns(
|
||||
referencedEntityBinding,
|
||||
keySource
|
||||
);
|
||||
final List<Binder.DefaultNamingStrategy> namingStrategies = new ArrayList<Binder.DefaultNamingStrategy>( targetColumns.size() );
|
||||
|
||||
final String ownedAttributeName;
|
||||
if ( attributeSource.getElementSource().getNature().isAssociation() ) {
|
||||
final AssociationSource associationSource = (AssociationSource) attributeSource.getElementSource();
|
||||
if ( associationSource.getOwnedAssociationSources().size() > 1 ) {
|
||||
throw new NotYetImplementedException( "Cannot determine default naming strategy when an association owns more than 1 other association." );
|
||||
}
|
||||
if ( associationSource.getOwnedAssociationSources().isEmpty() ) {
|
||||
ownedAttributeName = null;
|
||||
}
|
||||
else {
|
||||
final AssociationSource ownedAssociationSource = associationSource.getOwnedAssociationSources().iterator().next();
|
||||
ownedAttributeName = ownedAssociationSource.getAttributeSource().getName();
|
||||
}
|
||||
}
|
||||
else {
|
||||
ownedAttributeName = null;
|
||||
}
|
||||
|
||||
for ( final Column targetColumn : targetColumns ) {
|
||||
namingStrategies.add(
|
||||
new Binder.DefaultNamingStrategy() {
|
||||
@Override
|
||||
public String defaultName(NamingStrategy namingStrategy) {
|
||||
return namingStrategy.foreignKeyColumnName(
|
||||
ownedAttributeName,
|
||||
entityBinding.getEntityName(),
|
||||
entityBinding.getPrimaryTableName(),
|
||||
targetColumn.getColumnName().getText()
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
return resolveRelationalValueBindings(
|
||||
keySource,
|
||||
entityBinding,
|
||||
collectionTable,
|
||||
attributeSource.getElementSource().getNature() != PluralAttributeElementSource.Nature.ONE_TO_MANY,
|
||||
namingStrategies
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ForeignKey resolvePluralAttributeKeyForeignKey(
|
||||
final PluralAttributeSource attributeSource,
|
||||
final EntityBinding entityBinding,
|
||||
final TableSpecification collectionTable,
|
||||
final List<RelationalValueBinding> sourceRelationalValueBindings,
|
||||
final EntityBinding referencedEntityBinding) {
|
||||
final PluralAttributeKeySource keySource = attributeSource.getKeySource();
|
||||
List<Column> targetColumns =
|
||||
foreignKeyHelper.determineForeignKeyTargetColumns(
|
||||
referencedEntityBinding,
|
||||
keySource
|
||||
);
|
||||
ForeignKey foreignKey = locateOrCreateForeignKey(
|
||||
keySource,
|
||||
referencedEntityBinding,
|
||||
collectionTable,
|
||||
sourceRelationalValueBindings,
|
||||
targetColumns
|
||||
);
|
||||
foreignKey.setDeleteRule( keySource.getOnDeleteAction() );
|
||||
return foreignKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SingularAttributeBinding resolvePluralAttributeKeyReferencedBinding(
|
||||
AttributeBindingContainer attributeBindingContainer,
|
||||
PluralAttributeSource attributeSource) {
|
||||
return foreignKeyHelper.determineReferencedAttributeBinding(
|
||||
attributeSource.getKeySource(),
|
||||
attributeBindingContainer.seekEntityBinding()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
private SingularAttributeBinding resolveReferencedAttributeBinding(
|
||||
ToOneAttributeSource attributeSource,
|
||||
EntityBinding referencedEntityBinding) {
|
||||
return foreignKeyHelper.determineReferencedAttributeBinding( attributeSource, referencedEntityBinding );
|
||||
}
|
||||
|
||||
public List<RelationalValueBinding> resolveRelationalValueBindings(
|
||||
final RelationalValueSourceContainer relationalValueSourceContainer,
|
||||
EntityBinding entityBinding,
|
||||
TableSpecification defaultTable,
|
||||
boolean forceNonNullable,
|
||||
List<Binder.DefaultNamingStrategy> defaultNamingStrategies) {
|
||||
return relationalValueBindingHelper.createRelationalValueBindings(
|
||||
entityBinding,
|
||||
relationalValueSourceContainer,
|
||||
defaultTable,
|
||||
defaultNamingStrategies,
|
||||
forceNonNullable
|
||||
);
|
||||
}
|
||||
|
||||
private ForeignKey locateOrCreateForeignKey(
|
||||
final ForeignKeyContributingSource foreignKeyContributingSource,
|
||||
final EntityBinding referencedEntityBinding,
|
||||
final TableSpecification sourceTable,
|
||||
final List<RelationalValueBinding> sourceRelationalValueBindings,
|
||||
final List<Column> targetColumns) {
|
||||
final TableSpecification targetTable = foreignKeyHelper.determineForeignKeyTargetTable(
|
||||
referencedEntityBinding,
|
||||
foreignKeyContributingSource
|
||||
);
|
||||
return foreignKeyHelper.locateOrCreateForeignKey(
|
||||
foreignKeyContributingSource.getExplicitForeignKeyName(),
|
||||
sourceTable,
|
||||
extractColumnsFromRelationalValueBindings( sourceRelationalValueBindings ),
|
||||
targetTable,
|
||||
targetColumns
|
||||
);
|
||||
}
|
||||
|
||||
// TODO: try to get rid of this...
|
||||
private static List<Column> extractColumnsFromRelationalValueBindings(
|
||||
final List<RelationalValueBinding> valueBindings) {
|
||||
List<Column> columns = new ArrayList<Column>( valueBindings.size() );
|
||||
for ( RelationalValueBinding relationalValueBinding : valueBindings ) {
|
||||
final Value value = relationalValueBinding.getValue();
|
||||
// todo : currently formulas are not supported here... :(
|
||||
if ( !Column.class.isInstance( value ) ) {
|
||||
throw new NotYetImplementedException(
|
||||
"Derived values are not supported when creating a foreign key that targets columns."
|
||||
);
|
||||
}
|
||||
columns.add( (Column) value );
|
||||
}
|
||||
return columns;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* 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.annotations;
|
||||
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.MappedAttribute;
|
||||
import org.hibernate.metamodel.spi.source.FilterSource;
|
||||
import org.hibernate.metamodel.spi.source.ManyToManyPluralAttributeElementSource;
|
||||
|
||||
/**
|
||||
+ * @author Gail Badner
|
||||
+ */
|
||||
public abstract class AbstractManyToManyPluralAttributeElementSourceImpl
|
||||
extends AbstractPluralAssociationElementSourceImpl
|
||||
implements ManyToManyPluralAttributeElementSource {
|
||||
|
||||
|
||||
public AbstractManyToManyPluralAttributeElementSourceImpl(
|
||||
PluralAttributeSourceImpl pluralAttributeSource,
|
||||
final String relativePath) {
|
||||
super( pluralAttributeSource, relativePath );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUnique() {
|
||||
return pluralAssociationAttribute().getNature() == MappedAttribute.Nature.ONE_TO_MANY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getReferencedEntityAttributeName() {
|
||||
// HBM only
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FilterSource[] getFilterSources() {
|
||||
return new FilterSource[0]; //todo
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWhere() {
|
||||
return pluralAssociationAttribute().getWhereClause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchTiming getFetchTiming() {
|
||||
return FetchTiming.IMMEDIATE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Nature getNature() {
|
||||
return Nature.MANY_TO_MANY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOrdered() {
|
||||
return StringHelper.isNotEmpty( pluralAssociationAttribute().getOrderBy() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOrder() {
|
||||
return pluralAssociationAttribute().getOrderBy();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* 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.annotations;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
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.AssociationPluralAttributeElementSource;
|
||||
import org.hibernate.metamodel.spi.source.AttributeSource;
|
||||
import org.hibernate.metamodel.spi.source.MappedByAssociationSource;
|
||||
|
||||
/**
|
||||
+ * @author Gail Badner
|
||||
+ */
|
||||
public abstract class AbstractPluralAssociationElementSourceImpl
|
||||
extends AbstractPluralAttributeElementSourceImpl implements AssociationPluralAttributeElementSource {
|
||||
private final PluralAttributeSourceImpl pluralAttributeSource;
|
||||
private final Set<MappedByAssociationSource> ownedAssociationSources = new HashSet<MappedByAssociationSource>( );
|
||||
|
||||
public AbstractPluralAssociationElementSourceImpl(
|
||||
final PluralAttributeSourceImpl pluralAttributeSource,
|
||||
final String relativePath) {
|
||||
super( pluralAttributeSource.pluralAssociationAttribute(), relativePath );
|
||||
this.pluralAttributeSource = pluralAttributeSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getReferencedEntityName() {
|
||||
return pluralAssociationAttribute().getReferencedEntityType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNotFoundAnException() {
|
||||
return !pluralAssociationAttribute().isIgnoreNotFound();
|
||||
}
|
||||
|
||||
public AttributeSource getAttributeSource() {
|
||||
return pluralAttributeSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<MappedByAssociationSource> getOwnedAssociationSources() {
|
||||
return ownedAssociationSources;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addMappedByAssociationSource(MappedByAssociationSource attributeSource) {
|
||||
if ( attributeSource == null ) {
|
||||
throw new IllegalArgumentException( "attributeSource must be non-null." );
|
||||
}
|
||||
ownedAssociationSources.add( attributeSource );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMappedBy() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<CascadeStyle> getCascadeStyles() {
|
||||
return EnumConversionHelper.cascadeTypeToCascadeStyleSet(
|
||||
pluralAssociationAttribute().getCascadeTypes(),
|
||||
pluralAssociationAttribute().getHibernateCascadeTypes(),
|
||||
pluralAssociationAttribute().getContext()
|
||||
);
|
||||
}
|
||||
|
||||
protected PluralAssociationAttribute pluralAssociationAttribute() {
|
||||
return pluralAttributeSource.pluralAssociationAttribute();
|
||||
}
|
||||
}
|
|
@ -33,12 +33,12 @@ import org.hibernate.metamodel.spi.source.PluralAttributeSource;
|
|||
/**
|
||||
* @author Strong Liu <stliu@hibernate.org>
|
||||
*/
|
||||
public abstract class AbstractPluralAttributeElementSource implements AnnotationAttributeSource {
|
||||
public abstract class AbstractPluralAttributeElementSourceImpl implements AnnotationAttributeSource {
|
||||
private final String path;
|
||||
protected AttributeOverride attributeOverride;
|
||||
protected AssociationOverride associationOverride;
|
||||
|
||||
public AbstractPluralAttributeElementSource(
|
||||
public AbstractPluralAttributeElementSourceImpl(
|
||||
final PluralAssociationAttribute associationAttribute,
|
||||
final String relativePath) {
|
||||
if ( associationAttribute.getPluralAttributeNature() == PluralAttributeSource.Nature.MAP ) {
|
|
@ -0,0 +1,129 @@
|
|||
package org.hibernate.metamodel.internal.source.annotations;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.engine.FetchStyle;
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.engine.spi.CascadeStyle;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.MappedAttribute;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.SingularAssociationAttribute;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.EnumConversionHelper;
|
||||
import org.hibernate.metamodel.spi.source.AttributeSource;
|
||||
import org.hibernate.metamodel.spi.source.MappedByAssociationSource;
|
||||
import org.hibernate.metamodel.spi.source.SingularAttributeSource;
|
||||
import org.hibernate.metamodel.spi.source.ToOneAttributeSource;
|
||||
import org.hibernate.type.ForeignKeyDirection;
|
||||
|
||||
public abstract class AbstractToOneAttributeSourceImpl extends SingularAttributeSourceImpl implements ToOneAttributeSource{
|
||||
private final SingularAssociationAttribute associationAttribute;
|
||||
private final Set<CascadeStyle> cascadeStyles;
|
||||
private final Set<MappedByAssociationSource> ownedAssociationSources = new HashSet<MappedByAssociationSource>();
|
||||
private SingularAttributeSource.Nature nature;
|
||||
|
||||
public AbstractToOneAttributeSourceImpl(SingularAssociationAttribute associationAttribute, String relativePath) {
|
||||
super( associationAttribute, relativePath );
|
||||
this.associationAttribute = associationAttribute;
|
||||
this.cascadeStyles = EnumConversionHelper.cascadeTypeToCascadeStyleSet(
|
||||
associationAttribute.getCascadeTypes(),
|
||||
associationAttribute.getHibernateCascadeTypes(),
|
||||
associationAttribute.getContext()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SingularAttributeSource.Nature getNature() {
|
||||
return nature;
|
||||
}
|
||||
|
||||
protected SingularAssociationAttribute associationAttribute() {
|
||||
return associationAttribute;
|
||||
}
|
||||
|
||||
protected void setNature(SingularAttributeSource.Nature nature) {
|
||||
if ( this.nature != null ) {
|
||||
throw new IllegalStateException( "nature is already initialized." );
|
||||
}
|
||||
this.nature = nature;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AttributeSource getAttributeSource() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getReferencedEntityName() {
|
||||
return associationAttribute.getReferencedEntityType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUnique() {
|
||||
return MappedAttribute.Nature.ONE_TO_ONE.equals( associationAttribute.getNature() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNotFoundAnException() {
|
||||
return !associationAttribute.isIgnoreNotFound();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<MappedByAssociationSource> getOwnedAssociationSources() {
|
||||
return ownedAssociationSources;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addMappedByAssociationSource(MappedByAssociationSource attributeSource) {
|
||||
if ( attributeSource == null ) {
|
||||
throw new IllegalArgumentException( "attributeSource must be non-null." );
|
||||
}
|
||||
ownedAssociationSources.add( attributeSource );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMappedBy() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<CascadeStyle> getCascadeStyles() {
|
||||
return cascadeStyles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchTiming getFetchTiming() {
|
||||
return associationAttribute.isLazy() ? FetchTiming.DELAYED : FetchTiming.IMMEDIATE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchStyle getFetchStyle() {
|
||||
if ( associationAttribute.getFetchStyle() != null ) {
|
||||
return associationAttribute.getFetchStyle();
|
||||
}
|
||||
else {
|
||||
return associationAttribute.isLazy() ? FetchStyle.SELECT : FetchStyle.JOIN;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUnWrapProxy() {
|
||||
return associationAttribute.isUnWrapProxy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append( "ToOneAttributeSourceImpl" );
|
||||
sb.append( "{associationAttribute=" ).append( associationAttribute );
|
||||
sb.append( ", cascadeStyles=" ).append( cascadeStyles );
|
||||
sb.append( '}' );
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ForeignKeyDirection getForeignKeyDirection() {
|
||||
return nature == Nature.ONE_TO_ONE && !associationAttribute.isOptional() ?
|
||||
ForeignKeyDirection.FROM_PARENT :
|
||||
ForeignKeyDirection.TO_PARENT;
|
||||
}
|
||||
}
|
|
@ -13,7 +13,8 @@ import org.hibernate.metamodel.spi.source.RelationalValueSource;
|
|||
/**
|
||||
* @author Hardy Ferentschik
|
||||
*/
|
||||
public class BasicPluralAttributeElementSourceImpl extends AbstractPluralAttributeElementSource implements BasicPluralAttributeElementSource {
|
||||
public class BasicPluralAttributeElementSourceImpl
|
||||
extends AbstractPluralAttributeElementSourceImpl implements BasicPluralAttributeElementSource {
|
||||
private final PluralAssociationAttribute associationAttribute;
|
||||
private final ConfiguredClass entityClass;
|
||||
private final Nature nature;
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
package org.hibernate.metamodel.internal.source.annotations;
|
||||
|
||||
import org.hibernate.TruthValue;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.AttributeOverride;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.BasicAttribute;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.Column;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.MappedAttribute;
|
||||
|
@ -37,20 +36,26 @@ import org.hibernate.metamodel.spi.source.SizeSource;
|
|||
*/
|
||||
public class ColumnSourceImpl implements ColumnSource {
|
||||
private final Column columnValues;
|
||||
private final String defaultTableName;
|
||||
private final String readFragement;
|
||||
private final String writeFragement;
|
||||
private final String checkCondition;
|
||||
|
||||
public ColumnSourceImpl(Column columnValues) {
|
||||
this( null, columnValues );
|
||||
this( null, columnValues, null );
|
||||
}
|
||||
|
||||
public ColumnSourceImpl(MappedAttribute attribute, Column columnValues) {
|
||||
this( attribute, columnValues, null );
|
||||
}
|
||||
|
||||
public ColumnSourceImpl(MappedAttribute attribute, Column columnValues, String defaultTableName) {
|
||||
boolean isBasicAttribute = attribute != null && attribute.getNature() == MappedAttribute.Nature.BASIC;
|
||||
this.readFragement = attribute != null && isBasicAttribute ? ( (BasicAttribute) attribute ).getCustomReadFragment() : null;
|
||||
this.writeFragement = attribute != null && isBasicAttribute ? ( (BasicAttribute) attribute ).getCustomWriteFragment() : null;
|
||||
this.checkCondition = attribute != null ? attribute.getCheckCondition() : null;
|
||||
this.columnValues = columnValues;
|
||||
this.defaultTableName = defaultTableName;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -128,12 +133,16 @@ public class ColumnSourceImpl implements ColumnSource {
|
|||
@Override
|
||||
public String getContainingTableName() {
|
||||
if ( columnValues == null ) {
|
||||
return null;
|
||||
return defaultTableName;
|
||||
}
|
||||
else if ( columnValues.getTable() == null ) {
|
||||
return defaultTableName;
|
||||
}
|
||||
else {
|
||||
return columnValues.getTable();
|
||||
}
|
||||
return columnValues.getTable();
|
||||
}
|
||||
|
||||
|
||||
// these come from attribute ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@Override
|
||||
|
|
|
@ -174,12 +174,13 @@ public class ComponentAttributeSourceImpl implements ComponentAttributeSource, A
|
|||
|
||||
@Override
|
||||
public String getContainingTableName() {
|
||||
// none, it is defined on the sub-attributes
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RelationalValueSource> relationalValueSources() {
|
||||
// none, they are defined on the simple sub-attributes
|
||||
// none, they are defined on the sub-attributes
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -35,6 +35,9 @@ import org.hibernate.AnnotationException;
|
|||
import org.hibernate.MappingException;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.jaxb.spi.Origin;
|
||||
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.internal.source.annotations.attribute.PrimaryKeyJoinColumn;
|
||||
import org.hibernate.metamodel.internal.source.annotations.entity.EntityClass;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.HibernateDotNames;
|
||||
|
@ -58,6 +61,7 @@ import org.jboss.jandex.ClassInfo;
|
|||
|
||||
/**
|
||||
* @author Hardy Ferentschik
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public class EntitySourceImpl implements EntitySource {
|
||||
private final EntityClass entityClass;
|
||||
|
@ -397,7 +401,7 @@ public class EntitySourceImpl implements EntitySource {
|
|||
JPADotNames.SECONDARY_TABLE
|
||||
);
|
||||
if ( secondaryTable != null ) {
|
||||
secondaryTableSources.add( createSecondaryTableSource( secondaryTable ) );
|
||||
secondaryTableSources.add( createSecondaryTableSource( secondaryTable, true ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -414,7 +418,20 @@ public class EntitySourceImpl implements EntitySource {
|
|||
AnnotationInstance[].class
|
||||
);
|
||||
for ( AnnotationInstance secondaryTable : tableAnnotations ) {
|
||||
secondaryTableSources.add( createSecondaryTableSource( secondaryTable ) );
|
||||
secondaryTableSources.add( createSecondaryTableSource( secondaryTable, true ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(AssociationAttribute associationAttribute: entityClass.getAssociationAttributes().values()){
|
||||
if( ( associationAttribute.getNature() == MappedAttribute.Nature.MANY_TO_ONE ||
|
||||
associationAttribute.getNature() == MappedAttribute.Nature.ONE_TO_ONE ) ) {
|
||||
AnnotationInstance joinTableAnnotation = JandexHelper.getSingleAnnotation(
|
||||
associationAttribute.annotations(),
|
||||
JPADotNames.JOIN_TABLE
|
||||
);
|
||||
if ( joinTableAnnotation != null ) {
|
||||
secondaryTableSources.add( createSecondaryTableSource( joinTableAnnotation, false ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -515,24 +532,35 @@ public class EntitySourceImpl implements EntitySource {
|
|||
}
|
||||
}
|
||||
|
||||
private SecondaryTableSource createSecondaryTableSource(AnnotationInstance tableAnnotation) {
|
||||
final List<PrimaryKeyJoinColumn> keys = collectionSecondaryTableKeys( tableAnnotation );
|
||||
private SecondaryTableSource createSecondaryTableSource(
|
||||
AnnotationInstance tableAnnotation,
|
||||
boolean isPrimaryKeyJoinColumn) {
|
||||
final List<? extends Column> keys = collectSecondaryTableKeys( tableAnnotation, isPrimaryKeyJoinColumn );
|
||||
return new SecondaryTableSourceImpl( new TableSourceImpl( tableAnnotation ), keys );
|
||||
}
|
||||
|
||||
private List<PrimaryKeyJoinColumn> collectionSecondaryTableKeys(final AnnotationInstance tableAnnotation) {
|
||||
private List<? extends Column> collectSecondaryTableKeys(
|
||||
final AnnotationInstance tableAnnotation,
|
||||
final boolean isPrimaryKeyJoinColumn) {
|
||||
final AnnotationInstance[] joinColumnAnnotations = JandexHelper.getValue(
|
||||
tableAnnotation,
|
||||
"pkJoinColumns",
|
||||
isPrimaryKeyJoinColumn ? "pkJoinColumns" : "joinColumns",
|
||||
AnnotationInstance[].class
|
||||
);
|
||||
|
||||
if ( joinColumnAnnotations == null ) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
final List<PrimaryKeyJoinColumn> keys = new ArrayList<PrimaryKeyJoinColumn>();
|
||||
final List<Column> keys = new ArrayList<Column>();
|
||||
for ( final AnnotationInstance joinColumnAnnotation : joinColumnAnnotations ) {
|
||||
keys.add( new PrimaryKeyJoinColumn( joinColumnAnnotation ) );
|
||||
final Column joinColumn;
|
||||
if ( isPrimaryKeyJoinColumn ) {
|
||||
joinColumn = new PrimaryKeyJoinColumn( joinColumnAnnotation );
|
||||
}
|
||||
else {
|
||||
joinColumn = new Column( joinColumnAnnotation );
|
||||
}
|
||||
keys.add( joinColumn );
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
|
|
|
@ -94,7 +94,7 @@ public class JoinedSubclassEntitySourceImpl extends SubclassEntitySourceImpl imp
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<Value> getJoinColumns(JoinColumnResolutionContext context) {
|
||||
public List<? extends Value> getJoinColumns(JoinColumnResolutionContext context) {
|
||||
List<Value> columns = new ArrayList<Value>();
|
||||
for ( String name : targetColumnNames ) {
|
||||
// the nulls represent table, schema and catalog name which are ignored anyway...
|
||||
|
|
|
@ -1,28 +1,15 @@
|
|||
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 extends AbstractPluralAttributeElementSource implements ManyToAnyPluralAttributeElementSource {
|
||||
private final PluralAssociationAttribute attribute;
|
||||
public class ManyToAnyPluralAttributeElementSourceImpl
|
||||
extends AbstractPluralAssociationElementSourceImpl implements ManyToAnyPluralAttributeElementSource {
|
||||
|
||||
public ManyToAnyPluralAttributeElementSourceImpl(PluralAssociationAttribute attribute, String relativePath) {
|
||||
super(attribute, relativePath);
|
||||
this.attribute = attribute;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<CascadeStyle> getCascadeStyles() {
|
||||
|
||||
return EnumConversionHelper.cascadeTypeToCascadeStyleSet(
|
||||
attribute.getCascadeTypes(),
|
||||
attribute.getHibernateCascadeTypes(),
|
||||
attribute.getContext() );
|
||||
public ManyToAnyPluralAttributeElementSourceImpl(PluralAttributeSourceImpl pluralAttributeSource, String relativePath) {
|
||||
super( pluralAttributeSource, relativePath );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
package org.hibernate.metamodel.internal.source.annotations;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.metamodel.spi.source.MappedByAssociationSource;
|
||||
import org.hibernate.metamodel.spi.source.RelationalValueSource;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public class ManyToManyMappedByPluralAttributeElementSourceImpl
|
||||
extends AbstractManyToManyPluralAttributeElementSourceImpl implements MappedByAssociationSource {
|
||||
|
||||
public ManyToManyMappedByPluralAttributeElementSourceImpl(
|
||||
PluralAttributeSourceImpl pluralAttributeSource,
|
||||
final String relativePath) {
|
||||
super( pluralAttributeSource, relativePath );
|
||||
if ( pluralAssociationAttribute().getMappedBy() == null ) {
|
||||
throw new AssertionFailure( "pluralAssociationAttribute().getMappedBy() must be non-null." );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getExplicitForeignKeyName() {
|
||||
throw new UnsupportedOperationException( "Not supported for attributes with mappedBy specified." ); }
|
||||
|
||||
@Override
|
||||
public JoinColumnResolutionDelegate getForeignKeyTargetColumnResolutionDelegate() {
|
||||
throw new UnsupportedOperationException( "Not supported for attributes with mappedBy specified." ); }
|
||||
|
||||
@Override
|
||||
public boolean areValuesIncludedInInsertByDefault() {
|
||||
throw new UnsupportedOperationException( "Not supported for attributes with mappedBy specified." ); }
|
||||
|
||||
@Override
|
||||
public boolean areValuesIncludedInUpdateByDefault() {
|
||||
throw new UnsupportedOperationException( "Not supported for attributes with mappedBy specified." ); }
|
||||
|
||||
@Override
|
||||
public boolean areValuesNullableByDefault() {
|
||||
throw new UnsupportedOperationException( "Not supported for attributes with mappedBy specified." ); }
|
||||
|
||||
@Override
|
||||
public boolean isMappedBy() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMappedBy() {
|
||||
return pluralAssociationAttribute().getMappedBy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RelationalValueSource> relationalValueSources() {
|
||||
throw new UnsupportedOperationException( "Not supported for attributes with mappedBy specified." ); }
|
||||
}
|
|
@ -24,88 +24,42 @@
|
|||
package org.hibernate.metamodel.internal.source.annotations;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
|
||||
import org.hibernate.cfg.NotYetImplementedException;
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.engine.spi.CascadeStyle;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.Column;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.PluralAssociationAttribute;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.EnumConversionHelper;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper;
|
||||
import org.hibernate.metamodel.spi.relational.TableSpecification;
|
||||
import org.hibernate.metamodel.spi.relational.Value;
|
||||
import org.hibernate.metamodel.spi.source.AttributeSource;
|
||||
import org.hibernate.metamodel.spi.source.FilterSource;
|
||||
import org.hibernate.metamodel.spi.source.ForeignKeyContributingSource;
|
||||
import org.hibernate.metamodel.spi.source.ManyToManyPluralAttributeElementSource;
|
||||
import org.hibernate.metamodel.spi.source.PluralAttributeSource;
|
||||
import org.hibernate.metamodel.spi.source.RelationalValueSource;
|
||||
import org.hibernate.metamodel.spi.source.ToOneAttributeSource;
|
||||
|
||||
/**
|
||||
* @author Hardy Ferentschik
|
||||
* @author Brett Meyer
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public class ManyToManyPluralAttributeElementSourceImpl extends AbstractPluralAttributeElementSource implements ManyToManyPluralAttributeElementSource {
|
||||
public class ManyToManyPluralAttributeElementSourceImpl
|
||||
extends AbstractManyToManyPluralAttributeElementSourceImpl
|
||||
implements ManyToManyPluralAttributeElementSource {
|
||||
|
||||
private final AttributeSource ownerAttributeSource;
|
||||
private final PluralAssociationAttribute associationAttribute;
|
||||
private final List<RelationalValueSource> relationalValueSources
|
||||
= new ArrayList<RelationalValueSource>();
|
||||
private final Collection<String> referencedColumnNames
|
||||
= new HashSet<String>();
|
||||
private final Iterable<CascadeStyle> cascadeStyles;
|
||||
private final boolean isUnique;
|
||||
|
||||
public ManyToManyPluralAttributeElementSourceImpl(
|
||||
AttributeSource ownerAttributeSource,
|
||||
PluralAssociationAttribute associationAttribute,
|
||||
boolean isUnique,
|
||||
PluralAttributeSourceImpl pluralAttributeSource,
|
||||
String relativePath) {
|
||||
super(associationAttribute, relativePath);
|
||||
this.ownerAttributeSource = ownerAttributeSource;
|
||||
this.associationAttribute = associationAttribute;
|
||||
this.isUnique = isUnique;
|
||||
|
||||
for ( Column column : associationAttribute.getInverseJoinColumnValues() ) {
|
||||
relationalValueSources.add( new ColumnSourceImpl( column ) );
|
||||
if ( column.getReferencedColumnName() != null ) {
|
||||
referencedColumnNames.add( column.getReferencedColumnName() );
|
||||
}
|
||||
super( pluralAttributeSource, relativePath );
|
||||
if ( pluralAttributeSource.getMappedBy() != null ) {
|
||||
throw new AssertionFailure( "pluralAttributeSource.getMappedBy() must be null." );
|
||||
}
|
||||
for ( Column column : pluralAttributeSource.pluralAssociationAttribute().getInverseJoinColumnValues() ) {
|
||||
relationalValueSources.add( new ColumnSourceImpl( column ) );
|
||||
}
|
||||
|
||||
cascadeStyles = EnumConversionHelper.cascadeTypeToCascadeStyleSet(
|
||||
associationAttribute.getCascadeTypes(),
|
||||
associationAttribute.getHibernateCascadeTypes(),
|
||||
associationAttribute.getContext() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getReferencedEntityName() {
|
||||
return associationAttribute.getReferencedEntityType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FilterSource[] getFilterSources() {
|
||||
return new FilterSource[0]; //todo
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getReferencedEntityAttributeName() {
|
||||
// HBM only
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getReferencedColumnNames() {
|
||||
return referencedColumnNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -113,62 +67,23 @@ public class ManyToManyPluralAttributeElementSourceImpl extends AbstractPluralAt
|
|||
return relationalValueSources;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<CascadeStyle> getCascadeStyles() {
|
||||
return cascadeStyles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNotFoundAnException() {
|
||||
return !associationAttribute.isIgnoreNotFound();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getExplicitForeignKeyName() {
|
||||
if ( associationAttribute.getMappedBy() != null ) {
|
||||
throw new NotYetImplementedException( "foreign key name on mappedBy side not implemented yet." );
|
||||
}
|
||||
else {
|
||||
return associationAttribute.getInverseForeignKeyName();
|
||||
}
|
||||
return pluralAssociationAttribute().getInverseForeignKeyName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JoinColumnResolutionDelegate getForeignKeyTargetColumnResolutionDelegate() {
|
||||
if ( associationAttribute.getMappedBy() != null ) {
|
||||
if ( ownerAttributeSource instanceof PluralAttributeSource ) {
|
||||
PluralAttributeSource ownerPluralAttributeSource = (PluralAttributeSource) ownerAttributeSource;
|
||||
return ownerPluralAttributeSource.getKeySource().getForeignKeyTargetColumnResolutionDelegate();
|
||||
|
||||
}
|
||||
else {
|
||||
ToOneAttributeSource ownerSingularAttributeSource = (ToOneAttributeSource) ownerAttributeSource;
|
||||
return ownerSingularAttributeSource.getForeignKeyTargetColumnResolutionDelegate();
|
||||
boolean hasReferencedColumn = false;
|
||||
for ( Column joinColumn : pluralAssociationAttribute().getInverseJoinColumnValues() ) {
|
||||
if ( joinColumn.getReferencedColumnName() != null ) {
|
||||
hasReferencedColumn = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return associationAttribute.getJoinColumnValues().isEmpty() ?
|
||||
null :
|
||||
new AnnotationJoinColumnResolutionDelegate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUnique() {
|
||||
return isUnique;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWhere() {
|
||||
return associationAttribute.getWhereClause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchTiming getFetchTiming() {
|
||||
return FetchTiming.IMMEDIATE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Nature getNature() {
|
||||
return Nature.MANY_TO_MANY;
|
||||
return hasReferencedColumn ?
|
||||
new AnnotationJoinColumnResolutionDelegate() :
|
||||
null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -186,16 +101,6 @@ public class ManyToManyPluralAttributeElementSourceImpl extends AbstractPluralAt
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOrdered() {
|
||||
return StringHelper.isNotEmpty( associationAttribute.getOrderBy() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOrder() {
|
||||
return associationAttribute.getOrderBy();
|
||||
}
|
||||
|
||||
// TODO: This needs reworked.
|
||||
public class AnnotationJoinColumnResolutionDelegate
|
||||
implements ForeignKeyContributingSource.JoinColumnResolutionDelegate {
|
||||
|
@ -206,12 +111,9 @@ public class ManyToManyPluralAttributeElementSourceImpl extends AbstractPluralAt
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<Value> getJoinColumns(JoinColumnResolutionContext context) {
|
||||
public List<? extends Value> getJoinColumns(JoinColumnResolutionContext context) {
|
||||
final List<Value> values = new ArrayList<Value>();
|
||||
for ( Column column : associationAttribute.getInverseJoinColumnValues() ) {
|
||||
if ( column.getReferencedColumnName() == null ) {
|
||||
return context.resolveRelationalValuesForAttribute( null );
|
||||
}
|
||||
for ( Column column : pluralAssociationAttribute().getInverseJoinColumnValues() ) {
|
||||
org.hibernate.metamodel.spi.relational.Column resolvedColumn = context.resolveColumn(
|
||||
column.getReferencedColumnName(),
|
||||
null,
|
||||
|
@ -236,7 +138,7 @@ public class ManyToManyPluralAttributeElementSourceImpl extends AbstractPluralAt
|
|||
|
||||
private String resolveLogicalJoinTableName() {
|
||||
final AnnotationInstance joinTableAnnotation = JandexHelper.getSingleAnnotation(
|
||||
associationAttribute.annotations(),
|
||||
pluralAssociationAttribute().annotations(),
|
||||
JPADotNames.JOIN_TABLE
|
||||
);
|
||||
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* 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.annotations;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.metamodel.spi.source.MappedByAssociationSource;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public class OneToManyMappedByPluralAttributeElementSourceImpl
|
||||
extends OneToManyPluralAttributeElementSourceImpl implements MappedByAssociationSource {
|
||||
|
||||
public OneToManyMappedByPluralAttributeElementSourceImpl(
|
||||
PluralAttributeSourceImpl pluralAttributeSource,
|
||||
String relativePath) {
|
||||
super( pluralAttributeSource, relativePath );
|
||||
if ( pluralAttributeSource.pluralAssociationAttribute().getMappedBy() == null ) {
|
||||
throw new AssertionFailure( "pluralAssociationAttribute().getMappedBy() must be non-null." );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMappedBy() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMappedBy() {
|
||||
return pluralAssociationAttribute().getMappedBy();
|
||||
}
|
||||
}
|
|
@ -23,71 +23,24 @@
|
|||
*/
|
||||
package org.hibernate.metamodel.internal.source.annotations;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
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.AttributeSource;
|
||||
import org.hibernate.metamodel.spi.source.OneToManyPluralAttributeElementSource;
|
||||
|
||||
/**
|
||||
* @author Hardy Ferentschik
|
||||
*/
|
||||
public class OneToManyPluralAttributeElementSourceImpl extends AbstractPluralAttributeElementSource implements OneToManyPluralAttributeElementSource {
|
||||
private final AttributeSource ownerAttributeSource;
|
||||
private final PluralAssociationAttribute associationAttribute;
|
||||
public class OneToManyPluralAttributeElementSourceImpl
|
||||
extends AbstractPluralAssociationElementSourceImpl implements OneToManyPluralAttributeElementSource {
|
||||
|
||||
public OneToManyPluralAttributeElementSourceImpl(
|
||||
AttributeSource ownerAttributeSource,
|
||||
PluralAssociationAttribute associationAttribute,
|
||||
PluralAttributeSourceImpl pluralAttributeSource,
|
||||
String relativePath) {
|
||||
super(associationAttribute, relativePath);
|
||||
this.ownerAttributeSource = ownerAttributeSource;
|
||||
this.associationAttribute = associationAttribute;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getReferencedEntityName() {
|
||||
return associationAttribute.getReferencedEntityType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNotFoundAnException() {
|
||||
return !associationAttribute.isIgnoreNotFound();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<CascadeStyle> getCascadeStyles() {
|
||||
return EnumConversionHelper.cascadeTypeToCascadeStyleSet(
|
||||
associationAttribute.getCascadeTypes(),
|
||||
associationAttribute.getHibernateCascadeTypes(),
|
||||
associationAttribute.getContext() );
|
||||
super( pluralAttributeSource, relativePath );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Nature getNature() {
|
||||
switch ( associationAttribute.getNature() ) {
|
||||
case MANY_TO_MANY: {
|
||||
return Nature.MANY_TO_MANY;
|
||||
}
|
||||
case MANY_TO_ANY: {
|
||||
return Nature.MANY_TO_ANY;
|
||||
}
|
||||
case ONE_TO_MANY: {
|
||||
return Nature.ONE_TO_MANY;
|
||||
}
|
||||
case ELEMENT_COLLECTION_BASIC: {
|
||||
return Nature.BASIC;
|
||||
}
|
||||
case ELEMENT_COLLECTION_EMBEDDABLE: {
|
||||
return Nature.AGGREGATE;
|
||||
}
|
||||
default: {
|
||||
throw new AssertionFailure( "Unexpected attribute nature: " + associationAttribute.getNature() );
|
||||
}
|
||||
}
|
||||
return Nature.ONE_TO_MANY;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -77,7 +77,9 @@ public class PluralAttributeKeySourceImpl implements PluralAttributeKeySource {
|
|||
|
||||
@Override
|
||||
public JoinColumnResolutionDelegate getForeignKeyTargetColumnResolutionDelegate() {
|
||||
|
||||
if ( attribute.getMappedBy() != null ) {
|
||||
throw new IllegalStateException( "Cannot determine foreign key information because association is not the owner." );
|
||||
}
|
||||
for ( Column joinColumn : attribute.getJoinColumnValues() ) {
|
||||
if ( StringHelper.isNotEmpty( joinColumn.getReferencedColumnName() ) ) {
|
||||
return new JoinColumnResolutionDelegateImpl( attribute );
|
||||
|
@ -107,7 +109,7 @@ public class PluralAttributeKeySourceImpl implements PluralAttributeKeySource {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<Value> getJoinColumns(JoinColumnResolutionContext context) {
|
||||
public List<? extends Value> getJoinColumns(JoinColumnResolutionContext context) {
|
||||
List<Column> joinColumnValues = attribute.getJoinColumnValues();
|
||||
if ( joinColumnValues.isEmpty() ) {
|
||||
return null;
|
||||
|
|
|
@ -30,7 +30,7 @@ import java.util.Map;
|
|||
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
|
||||
import org.hibernate.cfg.NotYetImplementedException;
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.engine.FetchStyle;
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
|
@ -43,10 +43,12 @@ import org.hibernate.metamodel.internal.source.annotations.util.HibernateDotName
|
|||
import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper;
|
||||
import org.hibernate.metamodel.spi.binding.Caching;
|
||||
import org.hibernate.metamodel.spi.binding.CustomSQL;
|
||||
import org.hibernate.metamodel.spi.source.AssociationSource;
|
||||
import org.hibernate.metamodel.spi.source.AttributeSource;
|
||||
import org.hibernate.metamodel.spi.source.AttributeSourceResolutionContext;
|
||||
import org.hibernate.metamodel.spi.source.HibernateTypeSource;
|
||||
import org.hibernate.metamodel.spi.source.FilterSource;
|
||||
import org.hibernate.metamodel.spi.source.MappedByAssociationSource;
|
||||
import org.hibernate.metamodel.spi.source.MetaAttributeSource;
|
||||
import org.hibernate.metamodel.spi.source.Orderable;
|
||||
import org.hibernate.metamodel.spi.source.PluralAttributeElementSource;
|
||||
|
@ -86,7 +88,7 @@ public class PluralAttributeSourceImpl implements AnnotationAttributeSource, Plu
|
|||
|
||||
if ( associationAttribute.getMappedBy() == null ) {
|
||||
this.ownerAttributeSource = this;
|
||||
this.elementSource = determineElementSource( this, associationAttribute, entityClass, attributePath );
|
||||
this.elementSource = determineElementSource( this, this, entityClass, attributePath );
|
||||
}
|
||||
this.filterSources = determineFilterSources(associationAttribute);
|
||||
}
|
||||
|
@ -160,12 +162,6 @@ public class PluralAttributeSourceImpl implements AnnotationAttributeSource, Plu
|
|||
return associationAttribute.getBatchSize();
|
||||
}
|
||||
|
||||
public static boolean usesJoinTable(AttributeSource ownerAttributeSource) {
|
||||
return ownerAttributeSource.isSingular() ?
|
||||
( (ToOneAttributeSource) ownerAttributeSource ).getContainingTableName() != null :
|
||||
( (PluralAttributeSource) ownerAttributeSource ).usesJoinTable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean usesJoinTable() {
|
||||
if ( associationAttribute.getMappedBy() != null ) {
|
||||
|
@ -192,18 +188,34 @@ public class PluralAttributeSourceImpl implements AnnotationAttributeSource, Plu
|
|||
|
||||
private static PluralAttributeElementSource determineElementSource(
|
||||
AttributeSource ownerAttributeSource,
|
||||
PluralAssociationAttribute associationAttribute,
|
||||
PluralAttributeSourceImpl pluralAttributeSource,
|
||||
ConfiguredClass entityClass,
|
||||
String relativePath) {
|
||||
switch ( associationAttribute.getNature() ) {
|
||||
if ( ownerAttributeSource == null ) {
|
||||
throw new AssertionFailure( "ownerAssociationSource must be non-null." );
|
||||
}
|
||||
final PluralAssociationAttribute associationAttribute = pluralAttributeSource.pluralAssociationAttribute();
|
||||
switch ( pluralAttributeSource.pluralAssociationAttribute().getNature() ) {
|
||||
case MANY_TO_MANY:
|
||||
return new ManyToManyPluralAttributeElementSourceImpl( ownerAttributeSource, associationAttribute, false, relativePath );
|
||||
return associationAttribute.getMappedBy() == null ?
|
||||
new ManyToManyPluralAttributeElementSourceImpl( pluralAttributeSource, relativePath ) :
|
||||
new ManyToManyMappedByPluralAttributeElementSourceImpl( pluralAttributeSource, relativePath );
|
||||
case MANY_TO_ANY:
|
||||
return new ManyToAnyPluralAttributeElementSourceImpl( associationAttribute, relativePath );
|
||||
return new ManyToAnyPluralAttributeElementSourceImpl( pluralAttributeSource, relativePath );
|
||||
case ONE_TO_MANY:
|
||||
return usesJoinTable( ownerAttributeSource ) ?
|
||||
new ManyToManyPluralAttributeElementSourceImpl( ownerAttributeSource, associationAttribute, true, relativePath ) :
|
||||
new OneToManyPluralAttributeElementSourceImpl( ownerAttributeSource, associationAttribute, relativePath );
|
||||
boolean usesJoinTable = ownerAttributeSource.isSingular() ?
|
||||
( (ToOneAttributeSource) ownerAttributeSource ).getContainingTableName() != null :
|
||||
( (PluralAttributeSource) ownerAttributeSource ).usesJoinTable();
|
||||
if ( usesJoinTable ) {
|
||||
return associationAttribute.getMappedBy() == null ?
|
||||
new ManyToManyPluralAttributeElementSourceImpl( pluralAttributeSource, relativePath ) :
|
||||
new ManyToManyMappedByPluralAttributeElementSourceImpl( pluralAttributeSource, relativePath );
|
||||
}
|
||||
else {
|
||||
return associationAttribute.getMappedBy() == null ?
|
||||
new OneToManyPluralAttributeElementSourceImpl( pluralAttributeSource, relativePath ) :
|
||||
new OneToManyMappedByPluralAttributeElementSourceImpl( pluralAttributeSource, relativePath );
|
||||
}
|
||||
case ELEMENT_COLLECTION_BASIC:
|
||||
return new BasicPluralAttributeElementSourceImpl( associationAttribute, entityClass, relativePath );
|
||||
case ELEMENT_COLLECTION_EMBEDDABLE: {
|
||||
|
@ -226,14 +238,7 @@ public class PluralAttributeSourceImpl implements AnnotationAttributeSource, Plu
|
|||
// todo - see org.hibernate.metamodel.internal.Binder#bindOneToManyCollectionKey
|
||||
// todo - needs to cater for @CollectionTable and @JoinTable
|
||||
if ( associationAttribute.getMappedBy() != null ) {
|
||||
if ( ownerAttributeSource.isSingular() ) {
|
||||
ToOneAttributeSource ownerSingularAttributeSource = (ToOneAttributeSource) ownerAttributeSource;
|
||||
throw new NotYetImplementedException( "mappedBy many-to-many owned by many-to-one not supported yet." );
|
||||
}
|
||||
else {
|
||||
PluralAttributeSource ownerPluralAttributeSource = (PluralAttributeSource) ownerAttributeSource;
|
||||
return ownerPluralAttributeSource.getCollectionTableSpecificationSource();
|
||||
}
|
||||
throw new IllegalStateException( "Cannot get collection table because this association is not the owner." );
|
||||
}
|
||||
final AnnotationInstance joinTableAnnotation = associationAttribute.getJoinTableAnnotation();
|
||||
return joinTableAnnotation == null ? null : new TableSourceImpl( joinTableAnnotation );
|
||||
|
@ -387,7 +392,22 @@ public class PluralAttributeSourceImpl implements AnnotationAttributeSource, Plu
|
|||
associationAttribute.getMappedBy()
|
||||
);
|
||||
// Initialize resolved entitySource.
|
||||
elementSource = determineElementSource( ownerAttributeSource, associationAttribute, entityClass, "" ); //TODO not sure what relativePath should be here
|
||||
elementSource = determineElementSource( ownerAttributeSource, this, entityClass, "" ); //TODO not sure what relativePath should be here
|
||||
if ( !MappedByAssociationSource.class.isInstance( elementSource ) ) {
|
||||
throw new AssertionFailure( "expected a mappedBy association." );
|
||||
}
|
||||
final AssociationSource ownerAssociationSource;
|
||||
if ( ownerAttributeSource.isSingular() ) {
|
||||
ownerAssociationSource = (ToOneAttributeSource) ownerAttributeSource;
|
||||
}
|
||||
else {
|
||||
final PluralAttributeSource pluralAttributeSource = (PluralAttributeSource) ownerAttributeSource;
|
||||
if ( !AssociationSource.class.isInstance( pluralAttributeSource.getElementSource() ) ) {
|
||||
throw new AssertionFailure( "Owner is not an association." );
|
||||
}
|
||||
ownerAssociationSource = (AssociationSource) pluralAttributeSource.getElementSource();
|
||||
}
|
||||
ownerAssociationSource.addMappedByAssociationSource( (MappedByAssociationSource) elementSource );
|
||||
}
|
||||
return elementSource;
|
||||
}
|
||||
|
|
|
@ -267,8 +267,12 @@ public class RootEntitySourceImpl extends EntitySourceImpl implements RootEntity
|
|||
break;
|
||||
case MANY_TO_ONE:
|
||||
case ONE_TO_ONE:
|
||||
//others??
|
||||
attributeSources.add( new ToOneAttributeSourceImpl( (SingularAssociationAttribute) attr,"" ) );
|
||||
final SingularAssociationAttribute associationAttribute = (SingularAssociationAttribute) attr;
|
||||
final SingularAttributeSource attributeSource =
|
||||
associationAttribute.getMappedBy() == null ?
|
||||
new ToOneAttributeSourceImpl( associationAttribute, "" ) :
|
||||
new ToOneMappedByAttributeSourceImpl( associationAttribute, "" );
|
||||
attributeSources.add( attributeSource );
|
||||
}
|
||||
}
|
||||
return attributeSources;
|
||||
|
|
|
@ -27,7 +27,7 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
|
||||
import org.hibernate.engine.FetchStyle;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.PrimaryKeyJoinColumn;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.Column;
|
||||
import org.hibernate.metamodel.spi.binding.CustomSQL;
|
||||
import org.hibernate.metamodel.spi.relational.TableSpecification;
|
||||
import org.hibernate.metamodel.spi.relational.Value;
|
||||
|
@ -45,21 +45,21 @@ public class SecondaryTableSourceImpl implements SecondaryTableSource {
|
|||
|
||||
public SecondaryTableSourceImpl(
|
||||
TableSpecificationSource joinTable,
|
||||
List<PrimaryKeyJoinColumn> joinColumns) {
|
||||
List<? extends Column> joinColumns) {
|
||||
this.joinTable = joinTable;
|
||||
|
||||
// todo : following normal annotation idiom for source, we probably want to move this stuff up to EntityClass...
|
||||
columnSources = new ArrayList<ColumnSource>();
|
||||
final List<String> targetColumnNames = new ArrayList<String>();
|
||||
boolean hadNamedTargetColumnReferences = false;
|
||||
for ( PrimaryKeyJoinColumn primaryKeyJoinColumnSource : joinColumns ) {
|
||||
for ( Column joinColumn : joinColumns ) {
|
||||
columnSources.add(
|
||||
new ColumnSourceImpl(
|
||||
primaryKeyJoinColumnSource
|
||||
joinColumn
|
||||
)
|
||||
);
|
||||
targetColumnNames.add( primaryKeyJoinColumnSource.getReferencedColumnName() );
|
||||
if ( primaryKeyJoinColumnSource.getReferencedColumnName() != null ) {
|
||||
targetColumnNames.add( joinColumn.getReferencedColumnName() );
|
||||
if ( joinColumn.getReferencedColumnName() != null ) {
|
||||
hadNamedTargetColumnReferences = true;
|
||||
}
|
||||
}
|
||||
|
@ -138,7 +138,7 @@ public class SecondaryTableSourceImpl implements SecondaryTableSource {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<Value> getJoinColumns(JoinColumnResolutionContext context) {
|
||||
public List<? extends Value> getJoinColumns(JoinColumnResolutionContext context) {
|
||||
List<Value> columns = new ArrayList<Value>();
|
||||
for ( String name : targetColumnNames ) {
|
||||
// the nulls represent table, schema and catalog name which are ignored anyway...
|
||||
|
|
|
@ -41,6 +41,7 @@ import org.hibernate.metamodel.internal.source.annotations.entity.ConfiguredClas
|
|||
import org.hibernate.metamodel.internal.source.annotations.entity.EmbeddableClass;
|
||||
import org.hibernate.metamodel.spi.source.AttributeSource;
|
||||
import org.hibernate.metamodel.spi.source.PluralAttributeSource;
|
||||
import org.hibernate.metamodel.spi.source.SingularAttributeSource;
|
||||
|
||||
/**
|
||||
* @author Strong Liu <stliu@hibernate.org>
|
||||
|
@ -110,7 +111,12 @@ public class SourceHelper {
|
|||
switch ( associationAttribute.getNature() ) {
|
||||
case ONE_TO_ONE:
|
||||
case MANY_TO_ONE: {
|
||||
ToOneAttributeSourceImpl source = new ToOneAttributeSourceImpl( (SingularAssociationAttribute) associationAttribute, relativePath );
|
||||
final SingularAssociationAttribute singularAssociationAttribute =
|
||||
(SingularAssociationAttribute) associationAttribute;
|
||||
final SingularAttributeSource source =
|
||||
associationAttribute.getMappedBy() == null ?
|
||||
new ToOneAttributeSourceImpl( singularAssociationAttribute, relativePath ) :
|
||||
new ToOneMappedByAttributeSourceImpl( singularAssociationAttribute, relativePath );
|
||||
attributeList.add( source );
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -33,65 +33,54 @@ import org.jboss.jandex.AnnotationInstance;
|
|||
|
||||
import org.hibernate.cfg.NamingStrategy;
|
||||
import org.hibernate.cfg.NotYetImplementedException;
|
||||
import org.hibernate.engine.FetchStyle;
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.engine.spi.CascadeStyle;
|
||||
import org.hibernate.internal.util.ValueHolder;
|
||||
import org.hibernate.metamodel.internal.Binder;
|
||||
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.internal.source.annotations.attribute.SingularAssociationAttribute;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.EnumConversionHelper;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper;
|
||||
import org.hibernate.metamodel.spi.binding.AttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.CompositeAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.relational.TableSpecification;
|
||||
import org.hibernate.metamodel.spi.relational.Value;
|
||||
import org.hibernate.metamodel.spi.source.AttributeSourceResolutionContext;
|
||||
import org.hibernate.metamodel.spi.source.ForeignKeyContributingSource;
|
||||
import org.hibernate.metamodel.spi.source.RelationalValueSource;
|
||||
import org.hibernate.metamodel.spi.source.SingularAttributeSource;
|
||||
import org.hibernate.metamodel.spi.source.ToOneAttributeSource;
|
||||
import org.hibernate.metamodel.spi.source.ToOneAttributeSourceNatureResolver;
|
||||
import org.hibernate.type.ForeignKeyDirection;
|
||||
|
||||
/**
|
||||
* @author Hardy Ferentschik
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public class ToOneAttributeSourceImpl extends SingularAttributeSourceImpl implements ToOneAttributeSource {
|
||||
private final AssociationAttribute associationAttribute;
|
||||
private final Set<CascadeStyle> cascadeStyles;
|
||||
private SingularAttributeSource.Nature nature;
|
||||
public class ToOneAttributeSourceImpl extends AbstractToOneAttributeSourceImpl implements ToOneAttributeSource {
|
||||
private List<RelationalValueSource> relationalValueSources;
|
||||
private String containingTableName;
|
||||
|
||||
public ToOneAttributeSourceImpl(SingularAssociationAttribute associationAttribute, String relativePath) {
|
||||
|
||||
super( associationAttribute, relativePath );
|
||||
this.associationAttribute = associationAttribute;
|
||||
this.cascadeStyles = EnumConversionHelper.cascadeTypeToCascadeStyleSet(
|
||||
associationAttribute.getCascadeTypes(),
|
||||
associationAttribute.getHibernateCascadeTypes(),
|
||||
associationAttribute.getContext()
|
||||
);
|
||||
this.nature = determineNatureIfPossible( associationAttribute );
|
||||
if ( associationAttribute.getMappedBy() != null ) {
|
||||
throw new IllegalArgumentException( "associationAttribute.getMappedBy() must be null" );
|
||||
}
|
||||
// Need to initialize relationalValueSources before determining logicalJoinTableName.
|
||||
this.relationalValueSources = resolveRelationalValueSources( associationAttribute );
|
||||
// Need to initialize logicalJoinTableName before determining nature.
|
||||
this.containingTableName = resolveContainingTableName( associationAttribute, relationalValueSources );
|
||||
setNature( determineNatureIfPossible( associationAttribute ) );
|
||||
}
|
||||
|
||||
private static Nature determineNatureIfPossible(SingularAssociationAttribute associationAttribute) {
|
||||
private Nature determineNatureIfPossible(
|
||||
SingularAssociationAttribute associationAttribute) {
|
||||
if ( MappedAttribute.Nature.MANY_TO_ONE.equals( associationAttribute.getNature() ) ) {
|
||||
return Nature.MANY_TO_ONE;
|
||||
}
|
||||
else if ( MappedAttribute.Nature.ONE_TO_ONE.equals( associationAttribute.getNature() ) ) {
|
||||
if ( associationAttribute.getMappedBy() != null ) {
|
||||
// This means it is a one-to-one, but it is not working yet.
|
||||
//return Nature.ONE_TO_ONE;
|
||||
throw new NotYetImplementedException( "@OneToOne with mappedBy specified is not supported yet." );
|
||||
if ( getContainingTableName() != null ) {
|
||||
return Nature.MANY_TO_ONE;
|
||||
}
|
||||
else if ( associationAttribute.hasPrimaryKeyJoinColumn() ) {
|
||||
return Nature.ONE_TO_ONE;
|
||||
}
|
||||
else if ( associationAttribute.getJoinTableAnnotation() != null ) {
|
||||
return Nature.MANY_TO_ONE;
|
||||
}
|
||||
else if ( associationAttribute.isId() ) {
|
||||
// if this association is part of the ID then this can't be a one-to-one
|
||||
return Nature.MANY_TO_ONE;
|
||||
|
@ -110,48 +99,36 @@ public class ToOneAttributeSourceImpl extends SingularAttributeSourceImpl implem
|
|||
}
|
||||
}
|
||||
@Override
|
||||
public Nature resolveToOneAttributeSourceNature(ToOneAttributeSourceNatureResolver.ToOneAttributeSourceNatureResolutionContext context) {
|
||||
if ( nature != null ) { return nature; }
|
||||
final List<org.hibernate.metamodel.spi.relational.Column> idColumns = context.getIdentifierColumns();
|
||||
if ( associationAttribute.getJoinColumnValues().size() != idColumns.size() ) {
|
||||
nature = Nature.MANY_TO_ONE;
|
||||
public void resolveToOneAttributeSource(AttributeSourceResolutionContext context) {
|
||||
if ( getNature() != null ) {
|
||||
return;
|
||||
}
|
||||
else {
|
||||
Set<String> joinColumnNames = new HashSet<String>( associationAttribute.getJoinColumnValues().size() );
|
||||
for ( Column joinColumn : associationAttribute.getJoinColumnValues() ) {
|
||||
joinColumnNames.add( joinColumn.getName() );
|
||||
// It would be nice to have the following block in determineNatureIfPossible(),
|
||||
// but it requires context.resolveIdentifierColumns(), it's here instead.
|
||||
if ( MappedAttribute.Nature.ONE_TO_ONE.equals( associationAttribute().getNature() ) ) {
|
||||
final List<org.hibernate.metamodel.spi.relational.Column> idColumns = context.resolveIdentifierColumns();
|
||||
if ( associationAttribute().getJoinColumnValues().size() != idColumns.size() ) {
|
||||
setNature( Nature.MANY_TO_ONE );
|
||||
}
|
||||
// if join columns are the entity's ID, then it is a one-to-one (mapToPk == true)
|
||||
boolean areJoinColumnsSameAsIdColumns = true;
|
||||
for ( org.hibernate.metamodel.spi.relational.Column idColumn : idColumns ) {
|
||||
if ( ! joinColumnNames.contains( idColumn.getColumnName().getText() ) ) {
|
||||
areJoinColumnsSameAsIdColumns = false;
|
||||
break;
|
||||
else {
|
||||
Set<String> joinColumnNames = new HashSet<String>( associationAttribute().getJoinColumnValues().size() );
|
||||
for ( Column joinColumn : associationAttribute().getJoinColumnValues() ) {
|
||||
joinColumnNames.add( joinColumn.getName() );
|
||||
}
|
||||
// if join columns are the entity's ID, then it is a one-to-one (mapToPk == true)
|
||||
boolean areJoinColumnsSameAsIdColumns = true;
|
||||
for ( org.hibernate.metamodel.spi.relational.Column idColumn : idColumns ) {
|
||||
if ( ! joinColumnNames.contains( idColumn.getColumnName().getText() ) ) {
|
||||
areJoinColumnsSameAsIdColumns = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
setNature( areJoinColumnsSameAsIdColumns ? Nature.ONE_TO_ONE : Nature.MANY_TO_ONE );
|
||||
}
|
||||
nature = areJoinColumnsSameAsIdColumns ? Nature.ONE_TO_ONE : Nature.MANY_TO_ONE;
|
||||
}
|
||||
return nature;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Nature getNature() {
|
||||
return nature;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getReferencedEntityName() {
|
||||
return associationAttribute.getReferencedEntityType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUnique() {
|
||||
return MappedAttribute.Nature.ONE_TO_ONE.equals( associationAttribute.getNature() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNotFoundAnException() {
|
||||
return !associationAttribute.isIgnoreNotFound();
|
||||
if ( getNature() == null ) {
|
||||
throw new NotYetImplementedException( "unknown type of to-one attribute." );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -174,7 +151,7 @@ public class ToOneAttributeSourceImpl extends SingularAttributeSourceImpl implem
|
|||
@Override
|
||||
public String defaultName(NamingStrategy namingStrategy) {
|
||||
return namingStrategy.foreignKeyColumnName(
|
||||
associationAttribute.getName(),
|
||||
associationAttribute().getName(),
|
||||
entityName,
|
||||
tableName,
|
||||
referencedAttributeBinding.getAttribute().getName()
|
||||
|
@ -186,32 +163,85 @@ public class ToOneAttributeSourceImpl extends SingularAttributeSourceImpl implem
|
|||
}
|
||||
}
|
||||
|
||||
private final ValueHolder<List<RelationalValueSource>> relationalValues = new ValueHolder<List<RelationalValueSource>>( new ValueHolder.DeferredInitializer<List<RelationalValueSource>>() {
|
||||
@Override
|
||||
public List<RelationalValueSource> initialize() {
|
||||
if ( associationAttribute.getJoinColumnValues().isEmpty() ) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<RelationalValueSource> valueSources = new ArrayList<RelationalValueSource>(
|
||||
associationAttribute.getJoinColumnValues()
|
||||
.size()
|
||||
);
|
||||
for ( Column column : associationAttribute.getJoinColumnValues() ) {
|
||||
valueSources.add( new ColumnSourceImpl( column ) );
|
||||
}
|
||||
return valueSources;
|
||||
}
|
||||
} );
|
||||
|
||||
@Override
|
||||
public List<RelationalValueSource> relationalValueSources() {
|
||||
return relationalValues.getValue();
|
||||
return relationalValueSources;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContainingTableName() {
|
||||
return containingTableName;
|
||||
}
|
||||
|
||||
private static List<RelationalValueSource> resolveRelationalValueSources(AssociationAttribute associationAttribute) {
|
||||
final List<RelationalValueSource> valueSources;
|
||||
final List<Column> joinColumns;
|
||||
if ( associationAttribute.getJoinTableAnnotation() == null ) {
|
||||
joinColumns = associationAttribute.getJoinColumnValues();
|
||||
}
|
||||
else {
|
||||
joinColumns = associationAttribute.getInverseJoinColumnValues();
|
||||
}
|
||||
if ( joinColumns.isEmpty() ) {
|
||||
valueSources = Collections.emptyList();
|
||||
}
|
||||
else {
|
||||
valueSources = new ArrayList<RelationalValueSource>( joinColumns.size() );
|
||||
for ( Column joinColumn : joinColumns ) {
|
||||
valueSources.add(
|
||||
new ColumnSourceImpl(
|
||||
associationAttribute,
|
||||
joinColumn,
|
||||
getDefaultLogicalJoinTableName( associationAttribute )
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
return valueSources;
|
||||
}
|
||||
|
||||
private static String getDefaultLogicalJoinTableName(AssociationAttribute associationAttribute) {
|
||||
if ( associationAttribute.getJoinTableAnnotation() == null ) {
|
||||
return null;
|
||||
}
|
||||
return JandexHelper.getValue( associationAttribute.getJoinTableAnnotation(), "name", String.class );
|
||||
}
|
||||
|
||||
|
||||
private static String resolveContainingTableName(
|
||||
AssociationAttribute associationAttribute,
|
||||
List<RelationalValueSource> relationalValueSources) {
|
||||
if ( relationalValueSources.isEmpty() ) {
|
||||
return getDefaultLogicalJoinTableName( associationAttribute );
|
||||
}
|
||||
String logicalTableName = relationalValueSources.get( 0 ).getContainingTableName();
|
||||
for ( int i = 1; i< relationalValueSources.size(); i++ ) {
|
||||
if ( logicalTableName == null ) {
|
||||
if ( relationalValueSources.get( i ).getContainingTableName() != null ) {
|
||||
throw new IllegalStateException( "Relational value sources refer to null and non-null containing tables." );
|
||||
}
|
||||
}
|
||||
else if ( !logicalTableName.equals( relationalValueSources.get( i ).getContainingTableName() ) ) {
|
||||
throw new IllegalStateException( "Relational value sources do not refer to the same containing table." );
|
||||
}
|
||||
}
|
||||
return logicalTableName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JoinColumnResolutionDelegate getForeignKeyTargetColumnResolutionDelegate() {
|
||||
return associationAttribute.getJoinColumnValues()
|
||||
.isEmpty() ? null : new AnnotationJoinColumnResolutionDelegate();
|
||||
List<Column> joinColumns =
|
||||
associationAttribute().getJoinTableAnnotation() == null ?
|
||||
associationAttribute().getJoinColumnValues() :
|
||||
associationAttribute().getInverseJoinColumnValues();
|
||||
boolean hasReferencedColumn = false;
|
||||
for ( Column joinColumn : joinColumns ) {
|
||||
if ( joinColumn.getReferencedColumnName() != null ) {
|
||||
hasReferencedColumn = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return hasReferencedColumn ? new AnnotationJoinColumnResolutionDelegate() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -219,66 +249,23 @@ public class ToOneAttributeSourceImpl extends SingularAttributeSourceImpl implem
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<CascadeStyle> getCascadeStyles() {
|
||||
return cascadeStyles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchTiming getFetchTiming() {
|
||||
return associationAttribute.isLazy() ? FetchTiming.DELAYED : FetchTiming.IMMEDIATE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchStyle getFetchStyle() {
|
||||
if ( associationAttribute.getFetchStyle() != null ) {
|
||||
return associationAttribute.getFetchStyle();
|
||||
}
|
||||
else {
|
||||
return associationAttribute.isLazy() ? FetchStyle.SELECT : FetchStyle.JOIN;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUnWrapProxy() {
|
||||
return associationAttribute.isUnWrapProxy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append( "ToOneAttributeSourceImpl" );
|
||||
sb.append( "{associationAttribute=" ).append( associationAttribute );
|
||||
sb.append( ", cascadeStyles=" ).append( cascadeStyles );
|
||||
sb.append( '}' );
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ForeignKeyDirection getForeignKeyDirection() {
|
||||
return getNature() == Nature.ONE_TO_ONE && !associationAttribute.isOptional() ?
|
||||
ForeignKeyDirection.FROM_PARENT :
|
||||
ForeignKeyDirection.TO_PARENT;
|
||||
}
|
||||
|
||||
public class AnnotationJoinColumnResolutionDelegate
|
||||
implements ForeignKeyContributingSource.JoinColumnResolutionDelegate {
|
||||
private final String logicalJoinTableName;
|
||||
|
||||
public AnnotationJoinColumnResolutionDelegate() {
|
||||
logicalJoinTableName = resolveLogicalJoinTableName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Value> getJoinColumns(JoinColumnResolutionContext context) {
|
||||
public List<? extends Value> getJoinColumns(JoinColumnResolutionContext context) {
|
||||
final List<Value> values = new ArrayList<Value>();
|
||||
for ( Column column : associationAttribute.getJoinColumnValues() ) {
|
||||
if ( column.getReferencedColumnName() == null ) {
|
||||
final List<Column> joinColumns =
|
||||
associationAttribute().getJoinTableAnnotation() == null ?
|
||||
associationAttribute().getJoinColumnValues() :
|
||||
associationAttribute().getInverseJoinColumnValues();
|
||||
for ( Column joinColumn : joinColumns ) {
|
||||
if ( joinColumn.getReferencedColumnName() == null ) {
|
||||
return context.resolveRelationalValuesForAttribute( null );
|
||||
}
|
||||
org.hibernate.metamodel.spi.relational.Column resolvedColumn = context.resolveColumn(
|
||||
column.getReferencedColumnName(),
|
||||
logicalJoinTableName,
|
||||
joinColumn.getReferencedColumnName(),
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
@ -290,7 +277,7 @@ public class ToOneAttributeSourceImpl extends SingularAttributeSourceImpl implem
|
|||
@Override
|
||||
public TableSpecification getReferencedTable(JoinColumnResolutionContext context) {
|
||||
return context.resolveTable(
|
||||
logicalJoinTableName,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
@ -304,7 +291,7 @@ public class ToOneAttributeSourceImpl extends SingularAttributeSourceImpl implem
|
|||
|
||||
private String resolveLogicalJoinTableName() {
|
||||
final AnnotationInstance joinTableAnnotation = JandexHelper.getSingleAnnotation(
|
||||
associationAttribute.annotations(),
|
||||
associationAttribute().annotations(),
|
||||
JPADotNames.JOIN_TABLE
|
||||
);
|
||||
|
||||
|
|
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* 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.annotations;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.metamodel.internal.Binder;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.MappedAttribute;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.SingularAssociationAttribute;
|
||||
import org.hibernate.metamodel.spi.binding.AttributeBinding;
|
||||
import org.hibernate.metamodel.spi.source.AttributeSourceResolutionContext;
|
||||
import org.hibernate.metamodel.spi.source.MappedByAssociationSource;
|
||||
import org.hibernate.metamodel.spi.source.RelationalValueSource;
|
||||
import org.hibernate.metamodel.spi.source.ToOneAttributeSource;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public class ToOneMappedByAttributeSourceImpl extends AbstractToOneAttributeSourceImpl implements MappedByAssociationSource {
|
||||
private ToOneAttributeSource owner;
|
||||
|
||||
public ToOneMappedByAttributeSourceImpl(SingularAssociationAttribute associationAttribute, String relativePath) {
|
||||
super( associationAttribute, relativePath);
|
||||
if ( associationAttribute.getMappedBy() == null ) {
|
||||
throw new IllegalArgumentException( "associationAttribute.getMappedBy() must be non-null" );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resolveToOneAttributeSource(AttributeSourceResolutionContext context) {
|
||||
if ( getNature() != null && owner != null) {
|
||||
return;
|
||||
}
|
||||
if ( owner == null ) {
|
||||
owner = (ToOneAttributeSource) context.resolveAttributeSource(
|
||||
associationAttribute().getReferencedEntityType(),
|
||||
associationAttribute().getMappedBy()
|
||||
);
|
||||
owner.addMappedByAssociationSource( this );
|
||||
}
|
||||
if ( getNature() == null ) {
|
||||
final Nature nature;
|
||||
if ( MappedAttribute.Nature.MANY_TO_ONE.equals( associationAttribute().getNature() ) ) {
|
||||
nature = Nature.MANY_TO_ONE;
|
||||
}
|
||||
else if ( MappedAttribute.Nature.ONE_TO_ONE.equals( associationAttribute().getNature() ) ) {
|
||||
if ( owner.getContainingTableName() != null ) {
|
||||
nature = Nature.MANY_TO_ONE;
|
||||
}
|
||||
else {
|
||||
nature = Nature.ONE_TO_ONE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new AssertionError(String.format(
|
||||
"Wrong attribute nature[%s] for toOne attribute: %s",
|
||||
associationAttribute().getNature(), associationAttribute().getRole()
|
||||
));
|
||||
}
|
||||
setNature( nature );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMappedBy() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMappedBy() {
|
||||
return associationAttribute().getMappedBy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RelationalValueSource> relationalValueSources() {
|
||||
throw new UnsupportedOperationException( "Not supported for a \"mappedBy\" association." );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContainingTableName() {
|
||||
throw new UnsupportedOperationException( "Not supported for a \"mappedBy\" association." );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getExplicitForeignKeyName() {
|
||||
throw new UnsupportedOperationException( "Not supported for a \"mappedBy\" association." );
|
||||
}
|
||||
|
||||
@Override
|
||||
public JoinColumnResolutionDelegate getForeignKeyTargetColumnResolutionDelegate() {
|
||||
throw new UnsupportedOperationException( "Not supported for a \"mappedBy\" association." );
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Binder.DefaultNamingStrategy> getDefaultNamingStrategies(String entityName, String tableName, AttributeBinding referencedAttributeBinding) {
|
||||
throw new UnsupportedOperationException( "Not supported for a \"mappedBy\" association." );
|
||||
}
|
||||
}
|
|
@ -38,13 +38,11 @@ import org.jboss.jandex.AnnotationTarget;
|
|||
import org.jboss.jandex.AnnotationValue;
|
||||
import org.jboss.jandex.ClassInfo;
|
||||
import org.jboss.jandex.DotName;
|
||||
import org.jboss.jandex.IndexView;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.annotations.FetchMode;
|
||||
import org.hibernate.annotations.LazyToOneOption;
|
||||
import org.hibernate.annotations.NotFoundAction;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.engine.FetchStyle;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
|
@ -65,6 +63,7 @@ import org.hibernate.metamodel.spi.source.MappingException;
|
|||
*
|
||||
* @author Hardy Ferentschik
|
||||
* @author Brett Meyer
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public class AssociationAttribute extends MappedAttribute {
|
||||
private static final CoreMessageLogger coreLogger = Logger.getMessageLogger(
|
||||
|
@ -76,7 +75,6 @@ public class AssociationAttribute extends MappedAttribute {
|
|||
private final String referencedEntityType;
|
||||
private final Class<?> referencedAttributeType;
|
||||
private final String mappedBy;
|
||||
private final boolean isJpaInverse;
|
||||
private final Set<CascadeType> cascadeTypes;
|
||||
private final Set<org.hibernate.annotations.CascadeType> hibernateCascadeTypes;
|
||||
private final boolean isOptional;
|
||||
|
@ -91,27 +89,6 @@ public class AssociationAttribute extends MappedAttribute {
|
|||
private final AnnotationInstance joinTableAnnotation;
|
||||
private AttributeTypeResolver resolver;
|
||||
|
||||
|
||||
static AssociationAttribute createAssociationAttribute(
|
||||
ClassInfo classInfo,
|
||||
String name,
|
||||
Class<?> attributeType,
|
||||
Nature attributeNature,
|
||||
String accessType,
|
||||
Map<DotName, List<AnnotationInstance>> annotations,
|
||||
EntityBindingContext context) {
|
||||
return new AssociationAttribute(
|
||||
classInfo,
|
||||
name,
|
||||
attributeType,
|
||||
attributeType,
|
||||
attributeNature,
|
||||
accessType,
|
||||
annotations,
|
||||
context
|
||||
);
|
||||
}
|
||||
|
||||
AssociationAttribute(
|
||||
ClassInfo classInfo,
|
||||
String name,
|
||||
|
@ -150,24 +127,27 @@ public class AssociationAttribute extends MappedAttribute {
|
|||
this.referencedEntityType = determineReferencedEntityType( associationAnnotation, referencedAttributeType );
|
||||
this.referencedAttributeType = referencedAttributeType;
|
||||
this.mappedBy = determineMappedByAttributeName( associationAnnotation );
|
||||
this.isJpaInverse = mappedBy != null;
|
||||
this.isOptional = determineOptionality( associationAnnotation );
|
||||
this.isLazy = determineIsLazy( associationAnnotation );
|
||||
this.isUnWrapProxy = determinIsUnwrapProxy();
|
||||
this.isOrphanRemoval = determineOrphanRemoval( associationAnnotation );
|
||||
this.cascadeTypes = determineCascadeTypes( associationAnnotation );
|
||||
this.hibernateCascadeTypes = determineHibernateCascadeTypes( annotations );
|
||||
|
||||
determineJoinColumnAnnotations( annotations );
|
||||
determineJoinTableAnnotations( annotations, referencedAttributeType );
|
||||
joinColumnValues.trimToSize();
|
||||
inverseJoinColumnValues.trimToSize();
|
||||
|
||||
if ( this.mappedBy == null ) {
|
||||
determineJoinColumnAnnotations( annotations );
|
||||
determineJoinTableAnnotations( annotations, referencedAttributeType );
|
||||
joinColumnValues.trimToSize();
|
||||
inverseJoinColumnValues.trimToSize();
|
||||
this.joinTableAnnotation = determineExplicitJoinTable( annotations );
|
||||
}
|
||||
else {
|
||||
this.joinTableAnnotation = null;
|
||||
}
|
||||
|
||||
this.fetchStyle = determineFetchStyle();
|
||||
this.referencedIdAttributeName = determineMapsId();
|
||||
this.mapsId = referencedIdAttributeName != null;
|
||||
|
||||
this.joinTableAnnotation = determineExplicitJoinTable( annotations );
|
||||
}
|
||||
|
||||
public boolean isIgnoreNotFound() {
|
||||
|
@ -211,14 +191,23 @@ public class AssociationAttribute extends MappedAttribute {
|
|||
}
|
||||
|
||||
public List<Column> getJoinColumnValues() {
|
||||
if ( mappedBy != null ) {
|
||||
throw new IllegalStateException( "Cannot determine join column information because assocation is not owner." );
|
||||
}
|
||||
return joinColumnValues;
|
||||
}
|
||||
|
||||
public List<Column> getInverseJoinColumnValues() {
|
||||
if ( mappedBy != null ) {
|
||||
throw new IllegalStateException( "Cannot determine inverse join column information because assocation is not owner." );
|
||||
}
|
||||
return inverseJoinColumnValues;
|
||||
}
|
||||
|
||||
public AnnotationInstance getJoinTableAnnotation() {
|
||||
if ( mappedBy != null ) {
|
||||
throw new IllegalStateException( "Cannot determine join table information because assocation is not owner." );
|
||||
}
|
||||
return joinTableAnnotation;
|
||||
}
|
||||
|
||||
|
@ -271,7 +260,6 @@ public class AssociationAttribute extends MappedAttribute {
|
|||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public PropertyGeneration getPropertyGeneration() {
|
||||
return PropertyGeneration.NEVER;
|
||||
|
@ -458,6 +446,12 @@ public class AssociationAttribute extends MappedAttribute {
|
|||
}
|
||||
|
||||
private void determineJoinColumnAnnotations(Map<DotName, List<AnnotationInstance>> annotations) {
|
||||
// If mappedBy is defined, then annotations for this association are on the
|
||||
// owning side of the association.
|
||||
if ( mappedBy != null ) {
|
||||
throw new IllegalStateException( "Cannot determine join column information because association is not the owner." );
|
||||
}
|
||||
|
||||
Collection<AnnotationInstance> joinColumnAnnotations = JandexHelper.getAnnotations(
|
||||
annotations,
|
||||
JPADotNames.JOIN_COLUMN,
|
||||
|
@ -468,7 +462,6 @@ public class AssociationAttribute extends MappedAttribute {
|
|||
joinColumnValues.add( new Column( joinColumnAnnotation ) );
|
||||
}
|
||||
|
||||
|
||||
// @JoinColumn as part of @CollectionTable
|
||||
AnnotationInstance collectionTableAnnotation = JandexHelper.getSingleAnnotation(
|
||||
annotations,
|
||||
|
@ -487,21 +480,13 @@ public class AssociationAttribute extends MappedAttribute {
|
|||
private void determineJoinTableAnnotations(
|
||||
Map<DotName, List<AnnotationInstance>> annotations,
|
||||
Class<?> referencedAttributeType ) {
|
||||
|
||||
|
||||
// If JPA and 'mappedBy' (inverse side), override the annotations
|
||||
// with the owning side.
|
||||
if ( isJpaInverse ) {
|
||||
// TODO: Pull some of this into JandexHelper.
|
||||
IndexView index = JandexHelper.indexForClass(
|
||||
getContext().getServiceRegistry().getService(
|
||||
ClassLoaderService.class ), referencedAttributeType );
|
||||
ClassInfo classInfo = index.getClassByName( DotName.createSimple(
|
||||
referencedAttributeType.getName() ) );
|
||||
annotations = JandexHelper.getMemberAnnotations(
|
||||
classInfo, getMappedBy(), getContext().getServiceRegistry() );
|
||||
// If mappedBy is defined, then annotations for this association are on the
|
||||
// owning side of the association.
|
||||
if ( mappedBy != null ) {
|
||||
throw new IllegalStateException( "Cannot determine join table information because association is not the owner." );
|
||||
}
|
||||
|
||||
|
||||
// @JoinColumn as part of @JoinTable
|
||||
AnnotationInstance joinTableAnnotation = JandexHelper.getSingleAnnotation(
|
||||
annotations,
|
||||
|
@ -515,25 +500,22 @@ public class AssociationAttribute extends MappedAttribute {
|
|||
JandexHelper.getValue( joinTableAnnotation, "inverseJoinColumns", AnnotationInstance[].class )
|
||||
);
|
||||
|
||||
// If the mappedBy inverse, flipped. Confused yet?
|
||||
for ( AnnotationInstance annotation : columnsList ) {
|
||||
if ( isJpaInverse ) {
|
||||
inverseJoinColumnValues.add( new Column( annotation ) );
|
||||
} else {
|
||||
joinColumnValues.add( new Column( annotation ) );
|
||||
}
|
||||
joinColumnValues.add( new Column( annotation ) );
|
||||
}
|
||||
for ( AnnotationInstance annotation : inverseColumnsList ) {
|
||||
if ( isJpaInverse ) {
|
||||
joinColumnValues.add( new Column( annotation ) );
|
||||
} else {
|
||||
inverseJoinColumnValues.add( new Column( annotation ) );
|
||||
}
|
||||
inverseJoinColumnValues.add( new Column( annotation ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private AnnotationInstance determineExplicitJoinTable(Map<DotName, List<AnnotationInstance>> annotations) {
|
||||
// If mappedBy is defined, then annotations for this association are on the
|
||||
// owning side of the association.
|
||||
if ( mappedBy != null ) {
|
||||
throw new IllegalStateException( "Cannot determine join table information because association is not the owner." );
|
||||
}
|
||||
|
||||
AnnotationInstance annotationInstance = null;
|
||||
AnnotationInstance collectionTableAnnotation = JandexHelper.getSingleAnnotation(
|
||||
annotations,
|
||||
|
@ -582,5 +564,3 @@ public class AssociationAttribute extends MappedAttribute {
|
|||
return annotationInstance;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
/**
|
||||
* 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.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.metamodel.spi.source.AssociationSource;
|
||||
import org.hibernate.metamodel.spi.source.AttributeSource;
|
||||
import org.hibernate.metamodel.spi.source.MappedByAssociationSource;
|
||||
import org.hibernate.metamodel.spi.source.PluralAttributeSource;
|
||||
|
||||
/**
|
||||
+ * @author Gail Badner
|
||||
+ */
|
||||
public abstract class AbstractPluralAssociationElementSourceImpl
|
||||
extends AbstractHbmSourceNode implements AssociationSource {
|
||||
|
||||
private final PluralAttributeSource pluralAttributeSource;
|
||||
private final Set<MappedByAssociationSource> ownedAssociationSources = new HashSet<MappedByAssociationSource>( );
|
||||
|
||||
public AbstractPluralAssociationElementSourceImpl(
|
||||
MappingDocument mappingDocument,
|
||||
PluralAttributeSource pluralAttributeSource) {
|
||||
super( mappingDocument );
|
||||
this.pluralAttributeSource = pluralAttributeSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AttributeSource getAttributeSource() {
|
||||
return pluralAttributeSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<MappedByAssociationSource> getOwnedAssociationSources() {
|
||||
return ownedAssociationSources;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addMappedByAssociationSource(MappedByAssociationSource attributeSource) {
|
||||
if ( attributeSource == null ) {
|
||||
throw new IllegalArgumentException( "attributeSource must be non-null." );
|
||||
}
|
||||
ownedAssociationSources.add( attributeSource );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMappedBy() {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -143,6 +143,7 @@ public abstract class AbstractPluralAttributeSourceImpl
|
|||
.getOneToMany().getClazz());
|
||||
return new OneToManyPluralAttributeElementSourceImpl(
|
||||
sourceMappingDocument(),
|
||||
this,
|
||||
pluralAttributeElement.getOneToMany(),
|
||||
pluralAttributeElement.getCascade()
|
||||
);
|
||||
|
@ -152,6 +153,7 @@ public abstract class AbstractPluralAttributeSourceImpl
|
|||
.getManyToMany().getClazz());
|
||||
return new ManyToManyPluralAttributeElementSourceImpl(
|
||||
sourceMappingDocument(),
|
||||
this,
|
||||
pluralAttributeElement.getManyToMany(),
|
||||
pluralAttributeElement.getCascade()
|
||||
);
|
||||
|
|
|
@ -24,7 +24,9 @@
|
|||
package org.hibernate.metamodel.internal.source.hbm;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.cfg.NamingStrategy;
|
||||
import org.hibernate.engine.FetchStyle;
|
||||
|
@ -36,7 +38,10 @@ import org.hibernate.metamodel.spi.binding.CompositeAttributeBinding;
|
|||
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.relational.TableSpecification;
|
||||
import org.hibernate.metamodel.spi.relational.Value;
|
||||
import org.hibernate.metamodel.spi.source.AttributeSource;
|
||||
import org.hibernate.metamodel.spi.source.AttributeSourceResolutionContext;
|
||||
import org.hibernate.metamodel.spi.source.HibernateTypeSource;
|
||||
import org.hibernate.metamodel.spi.source.MappedByAssociationSource;
|
||||
import org.hibernate.metamodel.spi.source.MappingException;
|
||||
import org.hibernate.metamodel.spi.source.ToOneAttributeSource;
|
||||
|
||||
|
@ -46,6 +51,7 @@ import org.hibernate.metamodel.spi.source.ToOneAttributeSource;
|
|||
public abstract class AbstractToOneAttributeSourceImpl extends AbstractHbmSourceNode implements ToOneAttributeSource{
|
||||
private final SingularAttributeBinding.NaturalIdMutability naturalIdMutability;
|
||||
private final String propertyRef;
|
||||
private final Set<MappedByAssociationSource> ownedAssociationSources = new HashSet<MappedByAssociationSource>( );
|
||||
|
||||
AbstractToOneAttributeSourceImpl(
|
||||
MappingDocument sourceMappingDocument,
|
||||
|
@ -201,6 +207,32 @@ public abstract class AbstractToOneAttributeSourceImpl extends AbstractHbmSource
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<MappedByAssociationSource> getOwnedAssociationSources() {
|
||||
return ownedAssociationSources;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addMappedByAssociationSource(MappedByAssociationSource attributeSource) {
|
||||
ownedAssociationSources.add( attributeSource );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMappedBy() {
|
||||
// only applies to annotations
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AttributeSource getAttributeSource() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resolveToOneAttributeSource(AttributeSourceResolutionContext context) {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public JoinColumnResolutionDelegate getForeignKeyTargetColumnResolutionDelegate() {
|
||||
return propertyRef == null
|
||||
|
@ -221,7 +253,7 @@ public abstract class AbstractToOneAttributeSourceImpl extends AbstractHbmSource
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<Value> getJoinColumns(JoinColumnResolutionContext context) {
|
||||
public List<? extends Value> getJoinColumns(JoinColumnResolutionContext context) {
|
||||
return context.resolveRelationalValuesForAttribute( propertyRef );
|
||||
}
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@ public class JoinedSubclassEntitySourceImpl extends SubclassEntitySourceImpl imp
|
|||
? null
|
||||
: new JoinColumnResolutionDelegate() {
|
||||
@Override
|
||||
public List<Value> getJoinColumns(JoinColumnResolutionContext context) {
|
||||
public List<? extends Value> getJoinColumns(JoinColumnResolutionContext context) {
|
||||
return context.resolveRelationalValuesForAttribute( key.getPropertyRef() );
|
||||
}
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@ import org.hibernate.internal.util.collections.CollectionHelper;
|
|||
import org.hibernate.jaxb.spi.hbm.JaxbColumnElement;
|
||||
import org.hibernate.jaxb.spi.hbm.JaxbKeyManyToOneElement;
|
||||
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.source.AttributeSourceResolutionContext;
|
||||
import org.hibernate.metamodel.spi.source.MetaAttributeSource;
|
||||
import org.hibernate.metamodel.spi.source.RelationalValueSource;
|
||||
import org.hibernate.metamodel.spi.source.SingularAttributeSource;
|
||||
|
@ -116,11 +117,6 @@ class KeyManyToOneSourceImpl
|
|||
return Nature.MANY_TO_ONE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Nature resolveToOneAttributeSourceNature(ToOneAttributeSourceNatureResolutionContext context) {
|
||||
return getNature();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVirtualAttribute() {
|
||||
return false;
|
||||
|
|
|
@ -23,8 +23,6 @@
|
|||
*/
|
||||
package org.hibernate.metamodel.internal.source.hbm;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
|
@ -38,6 +36,7 @@ import org.hibernate.metamodel.spi.relational.Value;
|
|||
import org.hibernate.metamodel.spi.source.FilterSource;
|
||||
import org.hibernate.metamodel.spi.source.ManyToManyPluralAttributeElementSource;
|
||||
import org.hibernate.metamodel.spi.source.MappingException;
|
||||
import org.hibernate.metamodel.spi.source.PluralAttributeSource;
|
||||
import org.hibernate.metamodel.spi.source.RelationalValueSource;
|
||||
|
||||
/**
|
||||
|
@ -45,7 +44,7 @@ import org.hibernate.metamodel.spi.source.RelationalValueSource;
|
|||
* @author Gail Badner
|
||||
*/
|
||||
public class ManyToManyPluralAttributeElementSourceImpl
|
||||
extends AbstractHbmSourceNode
|
||||
extends AbstractPluralAssociationElementSourceImpl
|
||||
implements ManyToManyPluralAttributeElementSource {
|
||||
private final JaxbManyToManyElement manyToManyElement;
|
||||
private final Iterable<CascadeStyle> cascadeStyles;
|
||||
|
@ -54,9 +53,10 @@ public class ManyToManyPluralAttributeElementSourceImpl
|
|||
private final FilterSource[] filterSources;
|
||||
public ManyToManyPluralAttributeElementSourceImpl(
|
||||
MappingDocument mappingDocument,
|
||||
final PluralAttributeSource pluralAttributeSource,
|
||||
final JaxbManyToManyElement manyToManyElement,
|
||||
String cascadeString) {
|
||||
super( mappingDocument );
|
||||
super( mappingDocument, pluralAttributeSource );
|
||||
this.manyToManyElement = manyToManyElement;
|
||||
this.cascadeStyles = Helper.interpretCascadeStyles( cascadeString, bindingContext() );
|
||||
|
||||
|
@ -133,12 +133,6 @@ public class ManyToManyPluralAttributeElementSourceImpl
|
|||
return manyToManyElement.getPropertyRef();
|
||||
}
|
||||
|
||||
@Override
|
||||
// used by JPA instead of referenced entity attribute
|
||||
public Collection<String> getReferencedColumnNames() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RelationalValueSource> relationalValueSources() {
|
||||
return valueSources;
|
||||
|
@ -248,7 +242,7 @@ public class ManyToManyPluralAttributeElementSourceImpl
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<Value> getJoinColumns(JoinColumnResolutionContext context) {
|
||||
public List<? extends Value> getJoinColumns(JoinColumnResolutionContext context) {
|
||||
return context.resolveRelationalValuesForAttribute( manyToManyElement.getPropertyRef() );
|
||||
}
|
||||
|
||||
|
|
|
@ -148,11 +148,6 @@ class ManyToOneAttributeSourceImpl extends AbstractToOneAttributeSourceImpl {
|
|||
return Nature.MANY_TO_ONE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Nature resolveToOneAttributeSourceNature(ToOneAttributeSourceNatureResolutionContext context) {
|
||||
return getNature();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areValuesIncludedInInsertByDefault() {
|
||||
return manyToOneElement.isInsert();
|
||||
|
|
|
@ -27,21 +27,23 @@ import org.hibernate.engine.spi.CascadeStyle;
|
|||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.jaxb.spi.hbm.JaxbOneToManyElement;
|
||||
import org.hibernate.metamodel.spi.source.OneToManyPluralAttributeElementSource;
|
||||
import org.hibernate.metamodel.spi.source.PluralAttributeSource;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class OneToManyPluralAttributeElementSourceImpl
|
||||
extends AbstractHbmSourceNode
|
||||
extends AbstractPluralAssociationElementSourceImpl
|
||||
implements OneToManyPluralAttributeElementSource {
|
||||
private final JaxbOneToManyElement oneToManyElement;
|
||||
private final Iterable<CascadeStyle> cascadeStyles;
|
||||
|
||||
public OneToManyPluralAttributeElementSourceImpl(
|
||||
MappingDocument mappingDocument,
|
||||
final PluralAttributeSource pluralAttributeSource,
|
||||
final JaxbOneToManyElement oneToManyElement,
|
||||
String cascadeString) {
|
||||
super( mappingDocument );
|
||||
super( mappingDocument, pluralAttributeSource );
|
||||
this.oneToManyElement = oneToManyElement;
|
||||
this.cascadeStyles = Helper.interpretCascadeStyles( cascadeString, bindingContext() );
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ import org.hibernate.engine.spi.CascadeStyle;
|
|||
import org.hibernate.jaxb.spi.hbm.JaxbColumnElement;
|
||||
import org.hibernate.jaxb.spi.hbm.JaxbOneToOneElement;
|
||||
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.source.AttributeSourceResolutionContext;
|
||||
import org.hibernate.metamodel.spi.source.MetaAttributeSource;
|
||||
import org.hibernate.metamodel.spi.source.RelationalValueSource;
|
||||
import org.hibernate.type.ForeignKeyDirection;
|
||||
|
@ -134,11 +135,6 @@ class OneToOneAttributeSourceImpl extends AbstractToOneAttributeSourceImpl {
|
|||
return Nature.ONE_TO_ONE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Nature resolveToOneAttributeSourceNature(ToOneAttributeSourceNatureResolutionContext context) {
|
||||
return getNature();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVirtualAttribute() {
|
||||
return false;
|
||||
|
|
|
@ -93,7 +93,7 @@ public class PluralAttributeKeySourceImpl
|
|||
? null
|
||||
: new JoinColumnResolutionDelegate() {
|
||||
@Override
|
||||
public List<Value> getJoinColumns(JoinColumnResolutionContext context) {
|
||||
public List<? extends Value> getJoinColumns(JoinColumnResolutionContext context) {
|
||||
return context.resolveRelationalValuesForAttribute( keyElement.getPropertyRef() );
|
||||
}
|
||||
|
||||
|
|
|
@ -176,7 +176,7 @@ class SecondaryTableSourceImpl extends AbstractHbmSourceNode implements Secondar
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<Value> getJoinColumns(JoinColumnResolutionContext context) {
|
||||
public List<? extends Value> getJoinColumns(JoinColumnResolutionContext context) {
|
||||
return context.resolveRelationalValuesForAttribute( getReferencedAttributeName() );
|
||||
}
|
||||
|
||||
|
|
|
@ -23,13 +23,13 @@
|
|||
*/
|
||||
package org.hibernate.metamodel.spi.binding;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.mapping.PropertyGeneration;
|
||||
import org.hibernate.metamodel.spi.domain.PluralAttribute;
|
||||
import org.hibernate.metamodel.spi.domain.SingularAttribute;
|
||||
import org.hibernate.metamodel.spi.relational.TableSpecification;
|
||||
import org.hibernate.metamodel.spi.relational.Value;
|
||||
import org.hibernate.metamodel.spi.source.MetaAttributeContext;
|
||||
|
||||
|
@ -46,25 +46,36 @@ public abstract class AbstractAttributeBindingContainer implements AttributeBind
|
|||
}
|
||||
|
||||
@Override
|
||||
public AttributeBinding locateAttributeBinding(List<Value> values) {
|
||||
public SingularAttributeBinding locateAttributeBinding(TableSpecification table, List<? extends Value> values) {
|
||||
for ( AttributeBinding attributeBinding : attributeBindingMapInternal().values() ) {
|
||||
if ( !attributeBinding.getAttribute().isSingular() ) {
|
||||
continue;
|
||||
}
|
||||
SingularAttributeBinding basicAttributeBinding = (SingularAttributeBinding) attributeBinding;
|
||||
|
||||
List<org.hibernate.metamodel.spi.relational.Value> attributeValues = new ArrayList<Value>();
|
||||
for ( RelationalValueBinding relationalBinding : basicAttributeBinding.getRelationalValueBindings() ) {
|
||||
attributeValues.add( relationalBinding.getValue() );
|
||||
}
|
||||
|
||||
if ( attributeValues.equals( values ) ) {
|
||||
return attributeBinding;
|
||||
SingularAttributeBinding singularAttributeBinding = (SingularAttributeBinding) attributeBinding;
|
||||
if ( hasEqualValues( table, values, singularAttributeBinding.getRelationalValueBindings() ) ) {
|
||||
return singularAttributeBinding;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean hasEqualValues(
|
||||
TableSpecification table,
|
||||
List<? extends Value> values,
|
||||
List<RelationalValueBinding> relationalValueBindings) {
|
||||
if ( values.size() != relationalValueBindings.size() ) {
|
||||
return false;
|
||||
}
|
||||
for ( int i = 0 ; i < values.size() ; i++ ) {
|
||||
final RelationalValueBinding relationalValueBinding = relationalValueBindings.get( i );
|
||||
if ( !table.equals( relationalValueBinding.getTable() ) ||
|
||||
!values.get( i ).equals( relationalValueBinding.getValue() ) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getClassReference() {
|
||||
return getAttributeContainer().getClassReference();
|
||||
|
@ -153,8 +164,7 @@ public abstract class AbstractAttributeBindingContainer implements AttributeBind
|
|||
MetaAttributeContext metaAttributeContext,
|
||||
EntityBinding referencedEntityBinding,
|
||||
SingularAttributeBinding referencedAttributeBinding,
|
||||
boolean isConstrained,
|
||||
List<RelationalValueBinding> valueBindings) {
|
||||
boolean isConstrained) {
|
||||
final OneToOneAttributeBinding binding = new OneToOneAttributeBinding(
|
||||
this,
|
||||
attribute,
|
||||
|
@ -165,8 +175,7 @@ public abstract class AbstractAttributeBindingContainer implements AttributeBind
|
|||
metaAttributeContext,
|
||||
referencedEntityBinding,
|
||||
referencedAttributeBinding,
|
||||
isConstrained,
|
||||
valueBindings
|
||||
isConstrained
|
||||
);
|
||||
registerAttributeBinding( binding );
|
||||
return binding;
|
||||
|
@ -182,8 +191,7 @@ public abstract class AbstractAttributeBindingContainer implements AttributeBind
|
|||
SingularAttributeBinding.NaturalIdMutability naturalIdMutability,
|
||||
MetaAttributeContext metaAttributeContext,
|
||||
EntityBinding referencedEntityBinding,
|
||||
SingularAttributeBinding referencedAttributeBinding,
|
||||
List<RelationalValueBinding> valueBindings) {
|
||||
SingularAttributeBinding referencedAttributeBinding) {
|
||||
final ManyToOneAttributeBinding binding = new ManyToOneAttributeBinding(
|
||||
this,
|
||||
attribute,
|
||||
|
@ -194,8 +202,7 @@ public abstract class AbstractAttributeBindingContainer implements AttributeBind
|
|||
naturalIdMutability,
|
||||
metaAttributeContext,
|
||||
referencedEntityBinding,
|
||||
referencedAttributeBinding,
|
||||
valueBindings
|
||||
referencedAttributeBinding
|
||||
);
|
||||
registerAttributeBinding( binding );
|
||||
return binding;
|
||||
|
|
|
@ -163,8 +163,7 @@ public abstract class AbstractCompositeAttributeBindingContainer
|
|||
MetaAttributeContext metaAttributeContext,
|
||||
EntityBinding referencedEntityBinding,
|
||||
SingularAttributeBinding referencedAttributeBinding,
|
||||
boolean isConstrained,
|
||||
List<RelationalValueBinding> valueBindings) {
|
||||
boolean isConstrained) {
|
||||
if ( !isModifiable() ) {
|
||||
throw new UnsupportedOperationException( "Attribute bindings are read-only and cannot be modified." );
|
||||
}
|
||||
|
@ -177,8 +176,7 @@ public abstract class AbstractCompositeAttributeBindingContainer
|
|||
metaAttributeContext,
|
||||
referencedEntityBinding,
|
||||
referencedAttributeBinding,
|
||||
isConstrained,
|
||||
valueBindings
|
||||
isConstrained
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -192,8 +190,7 @@ public abstract class AbstractCompositeAttributeBindingContainer
|
|||
SingularAttributeBinding.NaturalIdMutability naturalIdMutability,
|
||||
MetaAttributeContext metaAttributeContext,
|
||||
EntityBinding referencedEntityBinding,
|
||||
SingularAttributeBinding referencedAttributeBinding,
|
||||
List<RelationalValueBinding> valueBindings) {
|
||||
SingularAttributeBinding referencedAttributeBinding) {
|
||||
if ( !isModifiable() ) {
|
||||
throw new UnsupportedOperationException( "Attribute bindings are read-only and cannot be modified." );
|
||||
}
|
||||
|
@ -206,8 +203,7 @@ public abstract class AbstractCompositeAttributeBindingContainer
|
|||
naturalIdMutability,
|
||||
metaAttributeContext,
|
||||
referencedEntityBinding,
|
||||
referencedAttributeBinding,
|
||||
valueBindings
|
||||
referencedAttributeBinding
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -31,6 +31,9 @@ import org.hibernate.engine.FetchStyle;
|
|||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.engine.spi.CascadeStyle;
|
||||
import org.hibernate.metamodel.spi.domain.SingularAttribute;
|
||||
import org.hibernate.metamodel.spi.relational.ForeignKey;
|
||||
import org.hibernate.metamodel.spi.relational.TableSpecification;
|
||||
import org.hibernate.metamodel.spi.relational.Value;
|
||||
import org.hibernate.metamodel.spi.source.MetaAttributeContext;
|
||||
|
||||
/**
|
||||
|
@ -38,9 +41,9 @@ import org.hibernate.metamodel.spi.source.MetaAttributeContext;
|
|||
*/
|
||||
public abstract class AbstractSingularAssociationAttributeBinding extends AbstractSingularAttributeBinding
|
||||
implements SingularAssociationAttributeBinding {
|
||||
protected final EntityBinding referencedEntityBinding;
|
||||
protected final SingularAttributeBinding referencedAttributeBinding;
|
||||
protected final RelationalValueBindingContainer relationalValueBindingContainer;
|
||||
private final EntityBinding referencedEntityBinding;
|
||||
private final SingularAttributeBinding referencedAttributeBinding;
|
||||
private JoinRelationalValueBindingContainer relationalValueBindingContainer;
|
||||
private CascadeStyle cascadeStyle;
|
||||
private FetchTiming fetchTiming;
|
||||
private FetchStyle fetchStyle;
|
||||
|
@ -57,7 +60,6 @@ public abstract class AbstractSingularAssociationAttributeBinding extends Abstra
|
|||
NaturalIdMutability naturalIdMutability,
|
||||
MetaAttributeContext metaAttributeContext,
|
||||
EntityBinding referencedEntityBinding,
|
||||
List<RelationalValueBinding> relationalValueBindings,
|
||||
SingularAttributeBinding referencedAttributeBinding) {
|
||||
super(
|
||||
container,
|
||||
|
@ -75,7 +77,6 @@ public abstract class AbstractSingularAssociationAttributeBinding extends Abstra
|
|||
throw new IllegalArgumentException( "referencedAttributeBinding must be non-null." );
|
||||
}
|
||||
this.referencedEntityBinding = referencedEntityBinding;
|
||||
this.relationalValueBindingContainer = new RelationalValueBindingContainer( relationalValueBindings );
|
||||
this.referencedAttributeBinding = referencedAttributeBinding;
|
||||
this.isNotFoundAnException = isNotFoundAnException;
|
||||
}
|
||||
|
@ -153,6 +154,28 @@ public abstract class AbstractSingularAssociationAttributeBinding extends Abstra
|
|||
return referencedAttributeBinding;
|
||||
}
|
||||
|
||||
public void setJoinRelationalValueBindings(
|
||||
List<RelationalValueBinding> relationalValueBindings,
|
||||
ForeignKey foreignKey) {
|
||||
this.relationalValueBindingContainer =
|
||||
new JoinRelationalValueBindingContainer( relationalValueBindings, foreignKey );
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableSpecification getTable() {
|
||||
return relationalValueBindingContainer.getTable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ForeignKey getForeignKey() {
|
||||
return relationalValueBindingContainer.getForeignKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Value> getValues() {
|
||||
return getRelationalValueBindingContainer().values();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RelationalValueBindingContainer getRelationalValueBindingContainer() {
|
||||
return relationalValueBindingContainer;
|
||||
|
|
|
@ -27,6 +27,7 @@ import java.util.List;
|
|||
|
||||
import org.hibernate.metamodel.spi.domain.SingularAttribute;
|
||||
import org.hibernate.metamodel.spi.relational.TableSpecification;
|
||||
import org.hibernate.metamodel.spi.relational.Value;
|
||||
import org.hibernate.metamodel.spi.source.MetaAttributeContext;
|
||||
|
||||
/**
|
||||
|
@ -59,6 +60,11 @@ public abstract class AbstractSingularAttributeBinding
|
|||
return getRelationalValueBindingContainer().relationalValueBindings();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Value> getValues() {
|
||||
return getRelationalValueBindingContainer().values();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasDerivedValue() {
|
||||
return getRelationalValueBindingContainer().hasDerivedValue();
|
||||
|
|
|
@ -89,11 +89,12 @@ public interface AttributeBindingContainer {
|
|||
/**
|
||||
* Locate a specific attribute binding, by its values.
|
||||
*
|
||||
* @param table The table containing the values
|
||||
* @param values The list of values
|
||||
*
|
||||
* @return The attribute binding or {@code null} if none could be found.
|
||||
*/
|
||||
AttributeBinding locateAttributeBinding(List<Value> values);
|
||||
SingularAttributeBinding locateAttributeBinding(TableSpecification table, List<? extends Value> values);
|
||||
|
||||
/**
|
||||
* Seeks out the entity binding that is the root of this component path.
|
||||
|
@ -192,8 +193,7 @@ public interface AttributeBindingContainer {
|
|||
MetaAttributeContext metaAttributeContext,
|
||||
EntityBinding referencedEntityBinding,
|
||||
SingularAttributeBinding referencedAttributeBinding,
|
||||
boolean isConstrained,
|
||||
List<RelationalValueBinding> valueBindings);
|
||||
boolean isConstrained);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -207,7 +207,6 @@ public interface AttributeBindingContainer {
|
|||
* @param metaAttributeContext
|
||||
* @param referencedEntityBinding
|
||||
* @param referencedAttributeBinding
|
||||
* @param valueBindings
|
||||
*
|
||||
* @return The attribute binding instance.
|
||||
*/
|
||||
|
@ -220,8 +219,7 @@ public interface AttributeBindingContainer {
|
|||
SingularAttributeBinding.NaturalIdMutability naturalIdMutability,
|
||||
MetaAttributeContext metaAttributeContext,
|
||||
EntityBinding referencedEntityBinding,
|
||||
SingularAttributeBinding referencedAttributeBinding,
|
||||
List<RelationalValueBinding> valueBindings);
|
||||
SingularAttributeBinding referencedAttributeBinding);
|
||||
|
||||
/**
|
||||
* Factory method for bag attribute bindings.
|
||||
|
|
|
@ -25,12 +25,14 @@ package org.hibernate.metamodel.spi.binding;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class BasicPluralAttributeIndexBinding extends AbstractPluralAttributeIndexBinding {
|
||||
|
||||
private List<RelationalValueBinding> relationalValueBindings;
|
||||
private RelationalValueBindingContainer relationalValueBindingContainer;
|
||||
|
||||
public BasicPluralAttributeIndexBinding(
|
||||
IndexedPluralAttributeBinding pluralAttributeBinding) {
|
||||
|
@ -39,11 +41,18 @@ public class BasicPluralAttributeIndexBinding extends AbstractPluralAttributeInd
|
|||
|
||||
@Override
|
||||
public List<RelationalValueBinding> getRelationalValueBindings() {
|
||||
return relationalValueBindings;
|
||||
return relationalValueBindingContainer.relationalValueBindings();
|
||||
}
|
||||
|
||||
public void setRelationalValueBindings(List<RelationalValueBinding> relationalValueBindings) {
|
||||
this.relationalValueBindings = relationalValueBindings;
|
||||
if ( relationalValueBindings == null || relationalValueBindings.isEmpty() ) {
|
||||
throw new AssertionFailure( "relationalValueBindings argument must be non-null and non-empty." );
|
||||
}
|
||||
if ( this.relationalValueBindingContainer != null ) {
|
||||
throw new AssertionFailure( "Relational value bindings have already initialized" );
|
||||
}
|
||||
this.relationalValueBindingContainer =
|
||||
new RelationalValueBindingContainer( relationalValueBindings );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -29,6 +29,11 @@ import org.hibernate.engine.spi.CascadeStyle;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface Cascadeable {
|
||||
/**
|
||||
* Obtain the cascade style to be applied to this association.
|
||||
*
|
||||
* @return The cascade style.
|
||||
*/
|
||||
public CascadeStyle getCascadeStyle();
|
||||
|
||||
public void setCascadeStyle(CascadeStyle cascadeStyle);
|
||||
|
|
|
@ -346,8 +346,10 @@ public class CompositeAttributeBinding
|
|||
}
|
||||
|
||||
@Override
|
||||
public AttributeBinding locateAttributeBinding(List<Value> values) {
|
||||
return compositeAttributeBindingContainer.locateAttributeBinding( values );
|
||||
public SingularAttributeBinding locateAttributeBinding(
|
||||
TableSpecification table,
|
||||
List<? extends Value> values) {
|
||||
return compositeAttributeBindingContainer.locateAttributeBinding( table, values );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -419,8 +421,7 @@ public class CompositeAttributeBinding
|
|||
MetaAttributeContext metaAttributeContext,
|
||||
EntityBinding referencedEntityBinding,
|
||||
SingularAttributeBinding referencedAttributeBinding,
|
||||
boolean isConstrained,
|
||||
List<RelationalValueBinding> valueBindings) {
|
||||
boolean isConstrained) {
|
||||
return compositeAttributeBindingContainer.makeOneToOneAttributeBinding(
|
||||
attribute,
|
||||
propertyAccessorName,
|
||||
|
@ -430,8 +431,7 @@ public class CompositeAttributeBinding
|
|||
metaAttributeContext,
|
||||
referencedEntityBinding,
|
||||
referencedAttributeBinding,
|
||||
isConstrained,
|
||||
valueBindings
|
||||
isConstrained
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -445,8 +445,7 @@ public class CompositeAttributeBinding
|
|||
NaturalIdMutability naturalIdMutability,
|
||||
MetaAttributeContext metaAttributeContext,
|
||||
EntityBinding referencedEntityBinding,
|
||||
SingularAttributeBinding referencedAttributeBinding,
|
||||
List<RelationalValueBinding> valueBindings) {
|
||||
SingularAttributeBinding referencedAttributeBinding) {
|
||||
return compositeAttributeBindingContainer.makeManyToOneAttributeBinding(
|
||||
attribute,
|
||||
propertyAccessorName,
|
||||
|
@ -456,8 +455,7 @@ public class CompositeAttributeBinding
|
|||
naturalIdMutability,
|
||||
metaAttributeContext,
|
||||
referencedEntityBinding,
|
||||
referencedAttributeBinding,
|
||||
valueBindings
|
||||
referencedAttributeBinding
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -131,6 +131,8 @@ public class EntityBinding extends AbstractAttributeBindingContainer implements
|
|||
public EntityBinding(EntityBinding superEntityBinding) {
|
||||
this.superEntityBinding = superEntityBinding;
|
||||
this.superEntityBinding.subEntityBindings.add( this );
|
||||
// TODO: the ID attribute binding needs to be recreated for this EntityBinding
|
||||
// otherwise, this != hierarchyDetails.getEntityIdentifier().getAttributeBinding().getContainer()
|
||||
this.hierarchyDetails = superEntityBinding.getHierarchyDetails();
|
||||
this.subEntityBindingId = superEntityBinding.nextSubEntityBindingId();
|
||||
}
|
||||
|
@ -216,14 +218,22 @@ public class EntityBinding extends AbstractAttributeBindingContainer implements
|
|||
}
|
||||
}
|
||||
|
||||
public AttributeBinding locateAttributeBinding(List<Value> values, boolean searchParent) {
|
||||
AttributeBinding attributeBinding = locateAttributeBinding( values );
|
||||
public SingularAttributeBinding locateAttributeBinding(
|
||||
TableSpecification table,
|
||||
List<? extends Value> values,
|
||||
boolean searchParent) {
|
||||
SingularAttributeBinding attributeBinding = null;
|
||||
SingularAttributeBinding idAttributeBinding = hierarchyDetails.getEntityIdentifier().getAttributeBinding();
|
||||
if ( primaryTable.equals( table ) && idAttributeBinding.getValues().equals( values ) ) {
|
||||
attributeBinding = hierarchyDetails.getEntityIdentifier().getAttributeBinding();
|
||||
}
|
||||
if ( attributeBinding == null ) {
|
||||
attributeBinding = locateAttributeBinding( table, values );
|
||||
}
|
||||
if ( attributeBinding == null && searchParent && getSuperEntityBinding() != null ) {
|
||||
return getSuperEntityBinding().locateAttributeBinding( values, searchParent );
|
||||
}
|
||||
else {
|
||||
return attributeBinding;
|
||||
attributeBinding = getSuperEntityBinding().locateAttributeBinding( table, values, searchParent );
|
||||
}
|
||||
return attributeBinding;
|
||||
}
|
||||
|
||||
public AttributeBinding locateAttributeBindingByPath(String path, boolean searchParent) {
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* 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.binding;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.metamodel.spi.relational.ForeignKey;
|
||||
import org.hibernate.metamodel.spi.relational.TableSpecification;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public class JoinRelationalValueBindingContainer extends RelationalValueBindingContainer {
|
||||
private final TableSpecification table;
|
||||
private final ForeignKey foreignKey;
|
||||
|
||||
public JoinRelationalValueBindingContainer(
|
||||
List<RelationalValueBinding> relationalValueBindings,
|
||||
ForeignKey foreignKey) {
|
||||
super( relationalValueBindings );
|
||||
if ( relationalValueBindings.isEmpty() ) {
|
||||
table = null;
|
||||
}
|
||||
else {
|
||||
table = relationalValueBindings.get( 0 ).getTable();
|
||||
for ( int i = 1; i< relationalValueBindings.size(); i++ ) {
|
||||
if ( !table.equals( relationalValueBindings.get( i ).getTable() ) ) {
|
||||
throw new AssertionFailure(
|
||||
String.format(
|
||||
"Multiple tables found in a %s: %s, %s",
|
||||
getClass().getName(),
|
||||
table.getLogicalName(),
|
||||
relationalValueBindings.get( i ).getTable()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( table != null && foreignKey != null && !table.equals( foreignKey.getSourceTable() ) ) {
|
||||
throw new IllegalStateException(
|
||||
String.format(
|
||||
"Unexpected source table for foreign key: %s; expected %s.",
|
||||
foreignKey.getSourceTable(),
|
||||
table
|
||||
)
|
||||
);
|
||||
}
|
||||
this.foreignKey = foreignKey;
|
||||
}
|
||||
|
||||
public TableSpecification getTable() {
|
||||
return table;
|
||||
}
|
||||
|
||||
public ForeignKey getForeignKey() {
|
||||
return foreignKey;
|
||||
}
|
||||
}
|
|
@ -28,6 +28,7 @@ import java.util.List;
|
|||
|
||||
import org.hibernate.FetchMode;
|
||||
import org.hibernate.internal.FilterConfiguration;
|
||||
import org.hibernate.metamodel.spi.relational.ForeignKey;
|
||||
|
||||
/**
|
||||
* Describes plural attributes of {@link org.hibernate.metamodel.spi.binding.PluralAttributeElementBinding.Nature#MANY_TO_MANY} elements
|
||||
|
@ -40,8 +41,7 @@ public class ManyToManyPluralAttributeElementBinding extends AbstractPluralAttri
|
|||
private String manyToManyWhere;
|
||||
private String manyToManyOrderBy;
|
||||
private FetchMode fetchMode;
|
||||
// TODO: really should have value defined (which defines table), but may not know
|
||||
private RelationalValueBindingContainer relationalValueBindingContainer;
|
||||
private JoinRelationalValueBindingContainer relationalValueBindingContainer;
|
||||
|
||||
ManyToManyPluralAttributeElementBinding(AbstractPluralAttributeBinding binding) {
|
||||
super( binding );
|
||||
|
@ -57,8 +57,17 @@ public class ManyToManyPluralAttributeElementBinding extends AbstractPluralAttri
|
|||
return Nature.MANY_TO_MANY;
|
||||
}
|
||||
|
||||
public void setRelationalValueBindings(List<RelationalValueBinding> relationalValueBindings) {
|
||||
this.relationalValueBindingContainer = new RelationalValueBindingContainer( relationalValueBindings );
|
||||
public void setJoinRelationalValueBindings(
|
||||
List<RelationalValueBinding> relationalValueBindings,
|
||||
ForeignKey foreignKey) {
|
||||
this.relationalValueBindingContainer = new JoinRelationalValueBindingContainer(
|
||||
relationalValueBindings,
|
||||
foreignKey
|
||||
);
|
||||
}
|
||||
|
||||
public ForeignKey getForeignKey() {
|
||||
return relationalValueBindingContainer.getForeignKey();
|
||||
}
|
||||
|
||||
public String getManyToManyWhere() {
|
||||
|
|
|
@ -47,8 +47,7 @@ public class ManyToOneAttributeBinding
|
|||
NaturalIdMutability naturalIdMutability,
|
||||
MetaAttributeContext metaAttributeContext,
|
||||
EntityBinding referencedEntityBinding,
|
||||
SingularAttributeBinding referencedAttributeBinding,
|
||||
List<RelationalValueBinding> relationalValueBindings) {
|
||||
SingularAttributeBinding referencedAttributeBinding) {
|
||||
super(
|
||||
container,
|
||||
attribute,
|
||||
|
@ -58,7 +57,8 @@ public class ManyToOneAttributeBinding
|
|||
isNotFoundAnException,
|
||||
naturalIdMutability,
|
||||
metaAttributeContext,
|
||||
referencedEntityBinding, relationalValueBindings, referencedAttributeBinding
|
||||
referencedEntityBinding,
|
||||
referencedAttributeBinding
|
||||
);
|
||||
}
|
||||
}
|
|
@ -47,8 +47,7 @@ public class OneToOneAttributeBinding
|
|||
MetaAttributeContext metaAttributeContext,
|
||||
EntityBinding referencedEntityBinding,
|
||||
SingularAttributeBinding referencedAttributeBinding,
|
||||
boolean isConstrained,
|
||||
List<RelationalValueBinding> valueBindings) {
|
||||
boolean isConstrained) {
|
||||
super(
|
||||
container,
|
||||
attribute,
|
||||
|
@ -59,7 +58,6 @@ public class OneToOneAttributeBinding
|
|||
naturalIdMutability,
|
||||
metaAttributeContext,
|
||||
referencedEntityBinding,
|
||||
valueBindings,
|
||||
referencedAttributeBinding
|
||||
);
|
||||
this.isConstrained = isConstrained;
|
||||
|
|
|
@ -27,18 +27,20 @@ import java.util.List;
|
|||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.cfg.NotYetImplementedException;
|
||||
import org.hibernate.metamodel.spi.relational.ForeignKey;
|
||||
import org.hibernate.metamodel.spi.relational.TableSpecification;
|
||||
import org.hibernate.metamodel.spi.relational.Value;
|
||||
|
||||
/**
|
||||
* Describes the binding information pertaining to the plural attribute foreign key.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public class PluralAttributeKeyBinding {
|
||||
private final AbstractPluralAttributeBinding pluralAttributeBinding;
|
||||
private final SingularAttributeBinding referencedAttributeBinding;
|
||||
private RelationalValueBindingContainer relationalValueBindingContainer;
|
||||
private boolean isCascadeDeleteEnabled;
|
||||
private JoinRelationalValueBindingContainer relationalValueBindingContainer;
|
||||
private boolean inverse;
|
||||
|
||||
// this knowledge can be implicitly resolved based on the typing information on the referenced owner attribute
|
||||
|
@ -70,8 +72,7 @@ public class PluralAttributeKeyBinding {
|
|||
}
|
||||
|
||||
public TableSpecification getCollectionTable() {
|
||||
// TODO: get table directly from relationalValueBindingContainer
|
||||
return relationalValueBindingContainer.relationalValueBindings().get( 0 ).getTable();
|
||||
return relationalValueBindingContainer.getTable();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -101,14 +102,25 @@ public class PluralAttributeKeyBinding {
|
|||
return relationalValueBindingContainer.relationalValueBindings();
|
||||
}
|
||||
|
||||
public void setRelationalValueBindings(List<RelationalValueBinding> relationalValueBindings) {
|
||||
public List<Value> getValues() {
|
||||
return relationalValueBindingContainer.values();
|
||||
}
|
||||
public ForeignKey getForeignKey() {
|
||||
return relationalValueBindingContainer.getForeignKey();
|
||||
}
|
||||
public void setJoinRelationalValueBindings(
|
||||
List<RelationalValueBinding> relationalValueBindings,
|
||||
ForeignKey foreignKey) {
|
||||
if ( relationalValueBindings == null || relationalValueBindings.isEmpty() ) {
|
||||
throw new AssertionFailure( "relationalValueBindings argument must be non-null and non-empty." );
|
||||
}
|
||||
if ( this.relationalValueBindingContainer != null ) {
|
||||
throw new AssertionFailure( "Relational value bindings have already initialized" );
|
||||
}
|
||||
this.relationalValueBindingContainer = new RelationalValueBindingContainer( relationalValueBindings );
|
||||
this.relationalValueBindingContainer = new JoinRelationalValueBindingContainer(
|
||||
relationalValueBindings,
|
||||
foreignKey
|
||||
);
|
||||
if ( this.relationalValueBindingContainer.hasDerivedValue() ) {
|
||||
throw new NotYetImplementedException(
|
||||
"Derived values are not supported when creating a foreign key that targets columns."
|
||||
|
@ -117,11 +129,7 @@ public class PluralAttributeKeyBinding {
|
|||
}
|
||||
|
||||
public boolean isCascadeDeleteEnabled() {
|
||||
return isCascadeDeleteEnabled;
|
||||
}
|
||||
|
||||
public void setCascadeDeleteEnabled(boolean isCascadeDeleteEnabled) {
|
||||
this.isCascadeDeleteEnabled = isCascadeDeleteEnabled;
|
||||
return relationalValueBindingContainer.getForeignKey().getDeleteRule() == ForeignKey.ReferentialAction.CASCADE;
|
||||
}
|
||||
|
||||
public boolean isNullable() {
|
||||
|
|
|
@ -23,6 +23,9 @@
|
|||
*/
|
||||
package org.hibernate.metamodel.spi.binding;
|
||||
|
||||
import org.hibernate.metamodel.spi.relational.ForeignKey;
|
||||
import org.hibernate.metamodel.spi.relational.TableSpecification;
|
||||
|
||||
/**
|
||||
* Contract describing the attribute binding for singular associations ({@code many-to-one}, {@code one-to-one}).
|
||||
*
|
||||
|
@ -43,4 +46,8 @@ public interface SingularAssociationAttributeBinding extends SingularAttributeBi
|
|||
public SingularAttributeBinding getReferencedAttributeBinding();
|
||||
|
||||
public boolean isNotFoundAnException();
|
||||
|
||||
public TableSpecification getTable();
|
||||
|
||||
public ForeignKey getForeignKey();
|
||||
}
|
|
@ -26,6 +26,7 @@ package org.hibernate.metamodel.spi.binding;
|
|||
import java.util.List;
|
||||
|
||||
import org.hibernate.metamodel.spi.domain.SingularAttribute;
|
||||
import org.hibernate.metamodel.spi.relational.Value;
|
||||
|
||||
/**
|
||||
* Specialized binding contract for singular (non-collection) attributes
|
||||
|
@ -39,6 +40,7 @@ public interface SingularAttributeBinding extends AttributeBinding {
|
|||
|
||||
public List<RelationalValueBinding> getRelationalValueBindings();
|
||||
|
||||
public List<Value> getValues();
|
||||
/**
|
||||
* Convenience method to determine if any {@link RelationalValueBinding simple value bindings} are derived values
|
||||
* (formula mappings).
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
+ * @author Gail Badner
|
||||
+ */
|
||||
public interface AssociationPluralAttributeElementSource extends PluralAttributeElementSource, AssociationSource {
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* 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 java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public interface AssociationSource extends CascadeStyleSource {
|
||||
|
||||
public AttributeSource getAttributeSource();
|
||||
|
||||
/**
|
||||
* Obtain the name of the referenced entity.
|
||||
*
|
||||
* @return The name of the referenced entity
|
||||
*/
|
||||
public String getReferencedEntityName();
|
||||
|
||||
public boolean isNotFoundAnException();
|
||||
|
||||
/**
|
||||
* Returns the attribute source that is owned by this {@link AssociationSource},
|
||||
* if there is one.
|
||||
* <p/>
|
||||
* Specifically, this method returns the {@link AttributeSource} that is
|
||||
* "mappedBy" this {@link AssociationSource}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Set<MappedByAssociationSource> getOwnedAssociationSources();
|
||||
|
||||
public void addMappedByAssociationSource(MappedByAssociationSource attributeSource);
|
||||
|
||||
public boolean isMappedBy();
|
||||
}
|
|
@ -23,6 +23,10 @@
|
|||
*/
|
||||
package org.hibernate.metamodel.spi.source;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.metamodel.spi.relational.Column;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Gail Badner
|
||||
|
@ -30,4 +34,5 @@ package org.hibernate.metamodel.spi.source;
|
|||
public interface AttributeSourceResolutionContext {
|
||||
public IdentifierSource resolveIdentifierSource(String entityName);
|
||||
public AttributeSource resolveAttributeSource(String entityName, String attributeName);
|
||||
public List<Column> resolveIdentifierColumns();
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ public interface ForeignKeyContributingSource {
|
|||
*
|
||||
* @return The resolved target columns.
|
||||
*/
|
||||
public List<Value> getJoinColumns(JoinColumnResolutionContext context);
|
||||
public List<? extends Value> getJoinColumns(JoinColumnResolutionContext context);
|
||||
|
||||
public TableSpecification getReferencedTable(JoinColumnResolutionContext context);
|
||||
|
||||
|
@ -90,7 +90,7 @@ public interface ForeignKeyContributingSource {
|
|||
*
|
||||
* @return The corresponding referenced columns
|
||||
*/
|
||||
public List<Value> resolveRelationalValuesForAttribute(String attributeName);
|
||||
public List<? extends Value> resolveRelationalValuesForAttribute(String attributeName);
|
||||
|
||||
public TableSpecification resolveTableForAttribute(String attributeName);
|
||||
|
||||
|
|
|
@ -27,5 +27,5 @@ package org.hibernate.metamodel.spi.source;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface ManyToAnyPluralAttributeElementSource
|
||||
extends PluralAttributeElementSource, CascadeStyleSource {
|
||||
extends PluralAttributeElementSource, AssociationSource {
|
||||
}
|
||||
|
|
|
@ -31,13 +31,11 @@ import org.hibernate.engine.FetchTiming;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface ManyToManyPluralAttributeElementSource
|
||||
extends PluralAttributeElementSource, CascadeStyleSource, RelationalValueSourceContainer, ForeignKeyContributingSource, Orderable {
|
||||
extends PluralAttributeElementSource, AssociationSource, RelationalValueSourceContainer, ForeignKeyContributingSource, Orderable {
|
||||
public String getReferencedEntityName();
|
||||
|
||||
public String getReferencedEntityAttributeName();
|
||||
|
||||
public Collection<String> getReferencedColumnNames();
|
||||
|
||||
public boolean isNotFoundAnException();
|
||||
|
||||
public String getExplicitForeignKeyName();
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||
* 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.
|
||||
|
@ -23,32 +23,10 @@
|
|||
*/
|
||||
package org.hibernate.metamodel.spi.source;
|
||||
|
||||
import org.hibernate.FetchMode;
|
||||
import org.hibernate.engine.FetchStyle;
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.engine.spi.CascadeStyle;
|
||||
|
||||
/**
|
||||
* Contract describing sources for attributes which model associations.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public interface AssociationAttributeSource extends AttributeSource {
|
||||
/**
|
||||
* Obtain the cascade styles to be applied to this association.
|
||||
*
|
||||
* @return The cascade styles.
|
||||
*/
|
||||
public Iterable<CascadeStyle> getCascadeStyles();
|
||||
public interface MappedByAssociationSource extends AssociationSource {
|
||||
|
||||
/**
|
||||
* Obtain the fetch mode to be applied to this association.
|
||||
*
|
||||
* @return The fetch mode.
|
||||
*/
|
||||
public FetchMode getFetchMode();
|
||||
|
||||
public FetchTiming getFetchTiming();
|
||||
|
||||
public FetchStyle getFetchStyle();
|
||||
String getMappedBy();
|
||||
}
|
|
@ -26,7 +26,7 @@ package org.hibernate.metamodel.spi.source;
|
|||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface OneToManyPluralAttributeElementSource extends PluralAttributeElementSource, CascadeStyleSource {
|
||||
public interface OneToManyPluralAttributeElementSource extends PluralAttributeElementSource, AssociationSource {
|
||||
public String getReferencedEntityName();
|
||||
|
||||
public boolean isNotFoundAnException();
|
||||
|
|
|
@ -25,6 +25,7 @@ package org.hibernate.metamodel.spi.source;
|
|||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public interface PluralAttributeElementSource {
|
||||
public Nature getNature();
|
||||
|
@ -35,10 +36,20 @@ public interface PluralAttributeElementSource {
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
enum Nature {
|
||||
BASIC,
|
||||
AGGREGATE,
|
||||
ONE_TO_MANY,
|
||||
MANY_TO_MANY,
|
||||
MANY_TO_ANY
|
||||
BASIC( false ),
|
||||
AGGREGATE( false ),
|
||||
ONE_TO_MANY( true ),
|
||||
MANY_TO_MANY( true ),
|
||||
MANY_TO_ANY( true );
|
||||
|
||||
private final boolean isAssociation;
|
||||
|
||||
private Nature(boolean isAssociation) {
|
||||
this.isAssociation = isAssociation;
|
||||
}
|
||||
|
||||
public boolean isAssociation() {
|
||||
return isAssociation;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,16 +35,13 @@ import org.hibernate.type.ForeignKeyDirection;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface ToOneAttributeSource
|
||||
extends SingularAttributeSource, ToOneAttributeSourceNatureResolver, ForeignKeyContributingSource, FetchableAttributeSource, CascadeStyleSource {
|
||||
extends SingularAttributeSource,
|
||||
ToOneAttributeSourceNatureResolver,
|
||||
ForeignKeyContributingSource,
|
||||
FetchableAttributeSource,
|
||||
AssociationSource {
|
||||
|
||||
/**
|
||||
* Obtain the name of the referenced entity.
|
||||
*
|
||||
* @return The name of the referenced entity
|
||||
*/
|
||||
public String getReferencedEntityName();
|
||||
public boolean isUnique();
|
||||
public boolean isNotFoundAnException();
|
||||
public boolean isUnWrapProxy();
|
||||
ForeignKeyDirection getForeignKeyDirection();
|
||||
public List<Binder.DefaultNamingStrategy> getDefaultNamingStrategies(final String entityName, final String tableName, final AttributeBinding referencedAttributeBinding);
|
||||
|
|
|
@ -33,10 +33,14 @@ import org.hibernate.metamodel.spi.relational.Column;
|
|||
*/
|
||||
public interface ToOneAttributeSourceNatureResolver {
|
||||
|
||||
SingularAttributeSource.Nature resolveToOneAttributeSourceNature(ToOneAttributeSourceNatureResolutionContext context);
|
||||
|
||||
public static interface ToOneAttributeSourceNatureResolutionContext {
|
||||
boolean areIdentifierColumnsDefined();
|
||||
List<org.hibernate.metamodel.spi.relational.Column> getIdentifierColumns();
|
||||
}
|
||||
/**
|
||||
* Perform any steps to completely resolve this attribute source.
|
||||
*
|
||||
* If this is a {@link MappedByAssociationSource}, resolution must
|
||||
* resolve the association owner, and this association must be added
|
||||
* to the owner's "owned" associations.
|
||||
*
|
||||
* @param context
|
||||
*/
|
||||
void resolveToOneAttributeSource(AttributeSourceResolutionContext context);
|
||||
}
|
||||
|
|
|
@ -844,14 +844,14 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
//#3
|
||||
System.arraycopy(
|
||||
naturalOrderTableNames,
|
||||
tableSpan - coreTableSpan,
|
||||
coreTableSpan,
|
||||
naturalOrderSubclassTableNameClosure,
|
||||
coreTableSpan + subclassSpan,
|
||||
secondaryTableSpan
|
||||
);
|
||||
System.arraycopy(
|
||||
naturalOrderTableKeyColumns,
|
||||
tableSpan - coreTableSpan,
|
||||
coreTableSpan,
|
||||
naturalOrderSubclassTableKeyColumnClosure,
|
||||
coreTableSpan + subclassSpan,
|
||||
secondaryTableSpan
|
||||
|
@ -929,7 +929,16 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
else {
|
||||
valueBindings = Collections.EMPTY_LIST;
|
||||
}
|
||||
TableSpecification table = attributeBinding.getContainer().seekEntityBinding().getPrimaryTable();// valueBinding.getValue().getTable();
|
||||
final TableSpecification table;
|
||||
if ( valueBindings.isEmpty() ) {
|
||||
table = attributeBinding.getContainer().seekEntityBinding().getPrimaryTable();
|
||||
}
|
||||
else {
|
||||
// TODO: Can relational value bindings for an attribute binding be in more than one table?
|
||||
// For now, just get the table from the first one.
|
||||
table = valueBindings.get( 0 ).getTable();
|
||||
}
|
||||
|
||||
final String tableName = table.getQualifiedName( factory.getDialect() );
|
||||
if ( i < hydrateSpan ) {
|
||||
propertyTableNumbers[i] = getTableId( tableName, tableNames );
|
||||
|
|
|
@ -28,6 +28,7 @@ import static junit.framework.Assert.assertEquals;
|
|||
import static junit.framework.Assert.assertNotNull;
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.CollectionTable;
|
||||
|
@ -108,7 +109,8 @@ public class UniqueConstraintBindingTest extends BaseAnnotationBindingTestCase {
|
|||
@ElementCollection
|
||||
@CollectionTable(name = "CollectionTable", joinColumns = @JoinColumn(name = "element"), uniqueConstraints = @UniqueConstraint(columnNames = "element", name = "u4"))
|
||||
@OrderColumn(name = "element_index")
|
||||
public int[] elements;
|
||||
public List<Integer> elements;
|
||||
// TODO: int[] is not completely supported using the new metamodel yet, so I changed int[] to List<Integer>
|
||||
}
|
||||
|
||||
@Entity
|
||||
|
|
|
@ -30,7 +30,6 @@ import org.hibernate.metamodel.MetadataSources;
|
|||
import org.hibernate.metamodel.internal.MetadataImpl;
|
||||
import org.hibernate.metamodel.spi.binding.EntityBinding;
|
||||
import org.hibernate.metamodel.spi.source.MappingException;
|
||||
import org.hibernate.testing.FailureExpectedWithNewMetamodel;
|
||||
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||
|
||||
import static junit.framework.Assert.assertNotNull;
|
||||
|
|
|
@ -48,7 +48,6 @@ import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
|
|||
import org.hibernate.metamodel.spi.relational.Column;
|
||||
import org.hibernate.metamodel.spi.relational.Identifier;
|
||||
import org.hibernate.metamodel.spi.relational.Value;
|
||||
import org.hibernate.testing.FailureExpectedWithNewMetamodel;
|
||||
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||
import org.hibernate.type.BagType;
|
||||
import org.hibernate.type.CollectionType;
|
||||
|
|
|
@ -30,7 +30,6 @@ import org.junit.Test;
|
|||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.Transaction;
|
||||
import org.hibernate.testing.FailureExpectedWithNewMetamodel;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
|
||||
import static org.junit.Assert.fail;
|
||||
|
|
|
@ -27,7 +27,6 @@ import org.junit.Test;
|
|||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.testing.DialectChecks;
|
||||
import org.hibernate.testing.FailureExpectedWithNewMetamodel;
|
||||
import org.hibernate.testing.RequiresDialectFeature;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
|
|
|
@ -27,7 +27,6 @@ import org.junit.Test;
|
|||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.testing.DialectChecks;
|
||||
import org.hibernate.testing.FailureExpectedWithNewMetamodel;
|
||||
import org.hibernate.testing.RequiresDialectFeature;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
|
|
|
@ -57,7 +57,6 @@ import org.junit.Test;
|
|||
/**
|
||||
* @author Emmanuel Bernard
|
||||
*/
|
||||
@FailureExpectedWithNewMetamodel( message = "@OneToOne with mappedBy specified is not supported yet" )
|
||||
public class BasicHibernateAnnotationsTest extends BaseCoreFunctionalTestCase {
|
||||
@Override
|
||||
protected boolean isCleanupTestDataRequired() {
|
||||
|
@ -103,6 +102,7 @@ public class BasicHibernateAnnotationsTest extends BaseCoreFunctionalTestCase {
|
|||
|
||||
@Test
|
||||
@RequiresDialectFeature( DialectChecks.SupportsExpectedLobUsagePattern.class )
|
||||
@FailureExpectedWithNewMetamodel
|
||||
public void testVersioning() throws Exception {
|
||||
Forest forest = new Forest();
|
||||
forest.setName( "Fontainebleau" );
|
||||
|
@ -329,6 +329,7 @@ public class BasicHibernateAnnotationsTest extends BaseCoreFunctionalTestCase {
|
|||
}
|
||||
|
||||
@Test
|
||||
@FailureExpectedWithNewMetamodel
|
||||
public void testCascadedDeleteOfChildEntitiesBug2() {
|
||||
// Relationship is one SoccerTeam to many Players.
|
||||
// Create a SoccerTeam (parent) and three Players (child).
|
||||
|
@ -379,6 +380,7 @@ public class BasicHibernateAnnotationsTest extends BaseCoreFunctionalTestCase {
|
|||
}
|
||||
|
||||
@Test
|
||||
@FailureExpectedWithNewMetamodel
|
||||
public void testCascadedDeleteOfChildOneToOne() {
|
||||
// create two single player teams (for one versus one match of soccer)
|
||||
// and associate teams with players via the special OneVOne methods.
|
||||
|
@ -465,6 +467,7 @@ public class BasicHibernateAnnotationsTest extends BaseCoreFunctionalTestCase {
|
|||
* defined on a parent MappedSuperclass(s)
|
||||
*/
|
||||
@Test
|
||||
@FailureExpectedWithNewMetamodel
|
||||
public void testInheritFiltersFromMappedSuperclass() throws Exception {
|
||||
Session s;
|
||||
Transaction tx;
|
||||
|
@ -670,7 +673,7 @@ public class BasicHibernateAnnotationsTest extends BaseCoreFunctionalTestCase {
|
|||
}
|
||||
catch( AnnotationException ex ) {
|
||||
assertEquals(
|
||||
"Either name or defaultForType (or both) attribute should be set in TypeDefinition having typeClass org.hibernate.test.annotations.entity.PhoneNumberType",
|
||||
"Either name or defaultForType (or both) must be set on TypeDefinition [org.hibernate.test.annotations.entity.PhoneNumberType]",
|
||||
ex.getMessage());
|
||||
} finally {
|
||||
if( sf != null){
|
||||
|
|
|
@ -26,7 +26,6 @@ package org.hibernate.test.annotations.enumerated.mapkey;
|
|||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.testing.FailureExpectedWithNewMetamodel;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
|
||||
/**
|
||||
|
|
|
@ -31,7 +31,6 @@ import org.junit.Test;
|
|||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.Transaction;
|
||||
import org.hibernate.testing.FailureExpectedWithNewMetamodel;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
|
||||
|
@ -44,7 +43,6 @@ import static org.junit.Assert.fail;
|
|||
/**
|
||||
* @author Emmanuel Bernard
|
||||
*/
|
||||
@FailureExpectedWithNewMetamodel
|
||||
public class JoinedSubclassTest extends BaseCoreFunctionalTestCase {
|
||||
@Test
|
||||
public void testDefault() throws Exception {
|
||||
|
|
|
@ -27,7 +27,6 @@ import org.junit.Test;
|
|||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.Transaction;
|
||||
import org.hibernate.testing.FailureExpectedWithNewMetamodel;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
@ -36,7 +35,6 @@ import static org.junit.Assert.assertNotNull;
|
|||
/**
|
||||
* @author Emmanuel Bernard
|
||||
*/
|
||||
@FailureExpectedWithNewMetamodel
|
||||
public class ManyToOneJoinTest extends BaseCoreFunctionalTestCase {
|
||||
@Test
|
||||
public void testManyToOneJoinTable() throws Exception {
|
||||
|
|
|
@ -33,7 +33,6 @@ import org.hibernate.cfg.Configuration;
|
|||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.criterion.Restrictions;
|
||||
import org.hibernate.sql.JoinType;
|
||||
import org.hibernate.testing.FailureExpectedWithNewMetamodel;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
import org.junit.Assert;
|
||||
|
@ -42,7 +41,6 @@ import org.junit.Test;
|
|||
/**
|
||||
* @author Guenther Demetz
|
||||
*/
|
||||
@FailureExpectedWithNewMetamodel( message = "@OneToOne with mappedBy specified is not supported yet" )
|
||||
public class ImmutableNaturalKeyLookupTest extends BaseCoreFunctionalTestCase {
|
||||
|
||||
@TestForIssue(jiraKey = "HHH-4838")
|
||||
|
|
|
@ -51,7 +51,7 @@ import static org.junit.Assert.assertTrue;
|
|||
/**
|
||||
* @author Emmanuel Bernard
|
||||
*/
|
||||
@FailureExpectedWithNewMetamodel( message = "requires support for @OneToOne with mappedBy" )
|
||||
@FailureExpectedWithNewMetamodel (message = "@Embeddable not detected on class used for @EmbeddedId" )
|
||||
public class OneToOneTest extends BaseCoreFunctionalTestCase {
|
||||
@Test
|
||||
public void testEagerFetching() throws Exception {
|
||||
|
|
|
@ -41,11 +41,11 @@ import static org.junit.Assert.fail;
|
|||
* @author Emmanuel Bernard
|
||||
* @author Gail Badner
|
||||
*/
|
||||
@FailureExpectedWithNewMetamodel( message = "requires support for @OneToOne with mappedBy" )
|
||||
public class OptionalOneToOneMappedByTest extends BaseCoreFunctionalTestCase {
|
||||
|
||||
// @OneToOne(mappedBy="address") with foreign generator
|
||||
@Test
|
||||
@FailureExpectedWithNewMetamodel ( message = "mappedBy @OneToOne with foreign generator" )
|
||||
public void testBidirForeignIdGenerator() {
|
||||
Session s = openSession();
|
||||
Transaction tx = s.beginTransaction();
|
||||
|
|
|
@ -29,7 +29,6 @@ import org.hibernate.Session;
|
|||
import org.hibernate.Transaction;
|
||||
import org.hibernate.criterion.Restrictions;
|
||||
import org.hibernate.id.IdentifierGenerationException;
|
||||
import org.hibernate.testing.FailureExpectedWithNewMetamodel;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
|
||||
|
@ -42,7 +41,6 @@ import static org.junit.Assert.fail;
|
|||
* @author Emmanuel Bernard
|
||||
* @author Gail Badner
|
||||
*/
|
||||
@FailureExpectedWithNewMetamodel( message = "requires support for @OneToOne with mappedBy" )
|
||||
public class OptionalOneToOnePKJCTest extends BaseCoreFunctionalTestCase {
|
||||
|
||||
@Test
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
package org.hibernate.test.annotations.onetoone;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.EmbeddedId;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
|
||||
|
@ -28,7 +29,7 @@ public class SerialNumber {
|
|||
return id.hashCode();
|
||||
}
|
||||
|
||||
@Id
|
||||
@EmbeddedId
|
||||
public SerialNumberPk getId() {
|
||||
return id;
|
||||
}
|
||||
|
|
|
@ -40,7 +40,6 @@ import org.junit.Test;
|
|||
* @author Emmanuel Bernard
|
||||
*/
|
||||
@TestForIssue( jiraKey = "HHH-4851" )
|
||||
@FailureExpectedWithNewMetamodel( message = "requires support for @OneToOne with mappedBy" )
|
||||
public class HHH4851Test extends BaseCoreFunctionalTestCase {
|
||||
@Test
|
||||
public void testHHH4851() throws Exception {
|
||||
|
|
Loading…
Reference in New Issue