org.hibernate.mapping.Property Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of hibernate-core Show documentation
Show all versions of hibernate-core Show documentation
Hibernate's core ORM functionality
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or .
*/
package org.hibernate.mapping;
import java.io.Serializable;
import java.util.Comparator;
import java.util.List;
import java.util.StringTokenizer;
import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.PropertyNotFoundException;
import org.hibernate.boot.model.domain.BasicValueMapping;
import org.hibernate.boot.model.domain.EntityMapping;
import org.hibernate.boot.model.domain.ManagedTypeMapping;
import org.hibernate.boot.model.domain.PersistentAttributeMapping;
import org.hibernate.boot.model.domain.ValueMapping;
import org.hibernate.boot.model.relational.MappedColumn;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.collection.internal.StandardArraySemantics;
import org.hibernate.collection.internal.StandardBagSemantics;
import org.hibernate.collection.internal.StandardIdentifierBagSemantics;
import org.hibernate.collection.internal.StandardListSemantics;
import org.hibernate.collection.internal.StandardMapSemantics;
import org.hibernate.collection.internal.StandardOrderedMapSemantics;
import org.hibernate.collection.internal.StandardOrderedSetSemantics;
import org.hibernate.collection.internal.StandardSetSemantics;
import org.hibernate.collection.internal.StandardSortedMapSemantics;
import org.hibernate.collection.internal.StandardSortedSetSemantics;
import org.hibernate.collection.spi.CollectionSemantics;
import org.hibernate.engine.spi.CascadeStyle;
import org.hibernate.engine.spi.CascadeStyles;
import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.metamodel.model.creation.spi.RuntimeModelCreationContext;
import org.hibernate.metamodel.model.domain.internal.SingularPersistentAttributeBasic;
import org.hibernate.metamodel.model.domain.internal.SingularPersistentAttributeEmbedded;
import org.hibernate.metamodel.model.domain.internal.SingularPersistentAttributeEntity;
import org.hibernate.metamodel.model.domain.spi.ManagedTypeDescriptor;
import org.hibernate.metamodel.model.domain.spi.PersistentAttributeDescriptor;
import org.hibernate.metamodel.model.domain.spi.PersistentCollectionDescriptor;
import org.hibernate.metamodel.model.domain.spi.PluralPersistentAttribute;
import org.hibernate.metamodel.model.domain.spi.SingularPersistentAttribute;
import org.hibernate.metamodel.model.domain.spi.SingularPersistentAttribute.SingularAttributeClassification;
import org.hibernate.property.access.spi.Getter;
import org.hibernate.property.access.spi.PropertyAccess;
import org.hibernate.property.access.spi.PropertyAccessStrategy;
import org.hibernate.property.access.spi.PropertyAccessStrategyResolver;
import org.hibernate.property.access.spi.Setter;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.tuple.ValueGeneration;
/**
* Represents a property as part of an entity or a component.
*
* @author Gavin King
*/
public class Property implements Serializable, PersistentAttributeMapping {
private final MetadataBuildingContext context;
private String name;
private Value value;
private String cascade;
private boolean updateable = true;
private boolean insertable = true;
private boolean selectable = true;
private boolean optimisticLocked = true;
private ValueGeneration valueGenerationStrategy;
private String propertyAccessorName;
private boolean lazy;
private String lazyGroup;
private boolean optional;
private java.util.Map metaAttributes;
private PersistentClass persistentClass;
private boolean naturalIdentifier;
private boolean lob;
@Override
public String getMappedBy() {
return mappedBy;
}
public void setMappedBy(String mappedBy) {
this.mappedBy = mappedBy;
}
private String mappedBy;
public Property(MetadataBuildingContext context) {
this.context = context;
}
@Override
public ValueMapping getValueMapping() {
return value;
}
@Override
public boolean isBackRef() {
return false;
}
/**
* Does this property represent a synthetic property? A synthetic property is one we create during
* metamodel binding to represent a collection of columns but which does not represent a property
* physically available on the entity.
*
* @return True if synthetic; false otherwise.
*/
public boolean isSynthetic() {
return false;
}
public int getColumnSpan() {
return value.getColumnSpan();
}
@SuppressWarnings("unchecked")
public List getMappedColumns(){
return value.getMappedColumns();
}
@Override
public String getName() {
return name;
}
public boolean isComposite() {
return value instanceof Component;
}
public Value getValue() {
return value;
}
public boolean isPrimitive(Class clazz) {
return getGetter(clazz).getReturnType().isPrimitive();
}
//
// public CascadeStyle getCascadeStyle() throws MappingException {
// Type type = value.getType();
// if ( type.isComponentType() ) {
// return getCompositeCascadeStyle( (EmbeddedType) type, cascade );
// }
// else if ( type.getClassification().equals( Type.Classification.COLLECTION ) ) {
// return getCollectionCascadeStyle( ( (Collection) value ).getElement().getType(), cascade );
// }
// else {
// return getCascadeStyle( cascade );
// }
// }
//
// private static CascadeStyle getCompositeCascadeStyle(EmbeddedType compositeType, String cascade) {
// if ( compositeType.getClassification().equals( Type.Classification.ANY ) ) {
// return getCascadeStyle( cascade );
// }
// int length = compositeType.getSubtypes().length;
// for ( int i=0; i PersistentAttributeDescriptor makeRuntimeAttribute(
ManagedTypeDescriptor runtimeContainer,
ManagedTypeMapping bootContainer,
SingularPersistentAttribute.Disposition singularAttributeDisposition,
RuntimeModelCreationContext context) {
assert value != null;
// todo (7.0) : better served through polymorphism though Value?
// todo (6.0) : how to handle synthetic/virtual properties?
assert !Backref.class.isInstance( this );
assert !IndexBackref.class.isInstance( this );
assert !SyntheticProperty.class.isInstance( this );
if ( value instanceof Collection ) {
return buildCollectionAttribute( runtimeContainer, bootContainer, context );
}
else {
return buildSingularAttribute( runtimeContainer, bootContainer, singularAttributeDisposition, context );
}
}
@SuppressWarnings("unchecked")
private PluralPersistentAttribute buildCollectionAttribute(
ManagedTypeDescriptor runtimeContainer,
ManagedTypeMapping bootContainer,
RuntimeModelCreationContext context) {
final PersistentCollectionDescriptor descriptor = context.getRuntimeModelDescriptorFactory().createPersistentCollectionDescriptor(
this,
runtimeContainer,
context
);
context.registerCollectionDescriptor( descriptor, (Collection) value );
return descriptor.getDescribedAttribute();
}
@SuppressWarnings("unchecked")
private CollectionSemantics resolveCollectionSemantics() {
// todo (6.0) : re-use CollectionSemantics from boot resolution
// the decision that a property is a persistent-collection (value instanceof Collection)
// should already have used CollectionSemanticsResolver to make that determination
//
// this is what would allow plugging in non-java.util.Collection collections (Celyon)
//
// for now create it here
if ( value instanceof Array ) {
return (CollectionSemantics) StandardArraySemantics.INSTANCE;
}
else if ( value instanceof Bag ) {
return (CollectionSemantics) StandardBagSemantics.INSTANCE;
}
else if ( value instanceof IdentifierBag ) {
return (CollectionSemantics) StandardIdentifierBagSemantics.INSTANCE;
}
else if ( value instanceof org.hibernate.mapping.List ) {
return (CollectionSemantics) StandardListSemantics.INSTANCE;
}
else if ( value instanceof Set ) {
final Set set = (Set) this.value;
final Comparator comparator = set.getComparator();
if ( comparator != null ) {
return (CollectionSemantics) StandardSortedSetSemantics.INSTANCE;
}
if ( set.hasOrder() ) {
return (CollectionSemantics) StandardOrderedSetSemantics.INSTANCE;
}
return (CollectionSemantics) StandardSetSemantics.INSTANCE;
}
else if ( value instanceof Map ) {
final Map map = (Map) value;
final Comparator comparator = map.getComparator();
if ( comparator != null ) {
return (CollectionSemantics) StandardSortedMapSemantics.INSTANCE;
}
if ( map.hasOrder() ) {
return (CollectionSemantics) StandardOrderedMapSemantics.INSTANCE;
}
return (CollectionSemantics) StandardMapSemantics.INSTANCE;
}
throw new HibernateException(
"Unable to determine collection semantics - `" +
getEntity().getEntityName() + '#' +
getName() + " : " +
value.getJavaTypeMapping().getTypeName()
);
}
@SuppressWarnings("unchecked")
private SingularPersistentAttribute buildSingularAttribute(
ManagedTypeDescriptor runtimeContainer,
ManagedTypeMapping bootContainer,
SingularPersistentAttribute.Disposition singularAttributeDisposition,
RuntimeModelCreationContext context) {
final PropertyAccess propertyAccess = runtimeContainer.getRepresentationStrategy().generatePropertyAccess(
bootContainer,
this,
runtimeContainer,
context.getSessionFactory().getSessionFactoryOptions().getBytecodeProvider()
);
if ( value instanceof BasicValueMapping ) {
return new SingularPersistentAttributeBasic(
runtimeContainer,
this,
propertyAccess,
singularAttributeDisposition,
context
);
}
else if ( value instanceof ToOne ) {
return new SingularPersistentAttributeEntity(
runtimeContainer,
this,
propertyAccess,
singularAttributeDisposition,
isManyToOne( (ToOne) value )
? SingularAttributeClassification.MANY_TO_ONE
: SingularAttributeClassification.ONE_TO_ONE,
context
);
}
else if ( value instanceof Component ) {
return new SingularPersistentAttributeEmbedded(
runtimeContainer,
this,
propertyAccess,
singularAttributeDisposition,
context
);
}
else if ( value instanceof Any ) {
throw new NotYetImplementedFor6Exception();
}
throw new MappingException( "Unrecognized ValueMapping type for conversion to runtime model : " + value );
}
private boolean isManyToOne(ToOne value) {
return ManyToOne.class.isInstance( value );
}
public Property shallowCopy() {
Property clone = new Property( context );
clone.setCascade( getCascade() );
clone.setInsertable( isInsertable() );
clone.setLazy( isLazy() );
clone.setName( getName() );
clone.setNaturalIdentifier( isNaturalIdentifier() );
clone.setOptimisticLocked( isOptimisticLocked() );
clone.setOptional( isOptional() );
clone.setPersistentClass( (PersistentClass) getEntity() );
clone.setPropertyAccessorName( getPropertyAccessorName() );
clone.setSelectable( isSelectable() );
clone.setUpdateable( isUpdateable() );
clone.setValue( getValue() );
return clone;
}
}