public Class<? extends EntityPersister> getEntityPersisterClass(EntityBinding metadata) { if (metadata.isRoot()) { Iterator<EntityBinding> subEntityBindingIterator = metadata.getDirectSubEntityBindings().iterator(); if (subEntityBindingIterator.hasNext()) { // If the class has children, we need to find of which kind metadata = subEntityBindingIterator.next(); } else { return singleTableEntityPersister(); } } switch (metadata.getHierarchyDetails().getInheritanceType()) { case JOINED: { return joinedSubclassEntityPersister(); } case SINGLE_TABLE: { return singleTableEntityPersister(); } case TABLE_PER_CLASS: { return unionSubclassEntityPersister(); } default: { throw new UnknownPersisterException( "Could not determine persister implementation for entity [" + metadata.getEntity().getName() + "]"); } } }
@Override public void bindMappingMetadata(MetadataSources sources, List<String> processedEntityNames) { AnnotationBindingContext context = new AnnotationBindingContext(index, metadata.getServiceRegistry()); // need to order our annotated entities into an order we can process Set<ConfiguredClassHierarchy<EntityClass>> hierarchies = ConfiguredClassHierarchyBuilder.createEntityHierarchies(context); // now we process each hierarchy one at the time Hierarchical parent = null; for (ConfiguredClassHierarchy<EntityClass> hierarchy : hierarchies) { for (EntityClass entityClass : hierarchy) { // for classes annotated w/ @Entity we create a EntityBinding if (ConfiguredClassType.ENTITY.equals(entityClass.getConfiguredClassType())) { LOG.bindingEntityFromAnnotatedClass(entityClass.getName()); EntityBinder entityBinder = new EntityBinder(metadata, entityClass, parent); EntityBinding binding = entityBinder.bind(); parent = binding.getEntity(); } // for classes annotated w/ @MappedSuperclass we just create the domain instance // the attribute bindings will be part of the first entity subclass else if (ConfiguredClassType.MAPPED_SUPERCLASS.equals( entityClass.getConfiguredClassType())) { parent = new Superclass(entityClass.getName(), parent); } // for classes which are not annotated at all we create the NonEntity domain class // todo - not sure whether this is needed. It might be that we don't need this information // (HF) else { parent = new NonEntity(entityClass.getName(), parent); } } } }
public static Callback[] resolveCallbacks( Class<?> entityClass, Class<?> callbackClass, ClassLoaderService classLoaderService, EntityBinding binding) { List<Callback> callbacks = new ArrayList<Callback>(); for (JpaCallbackClass jpaCallbackClass : binding.getJpaCallbackClasses()) { Object listener = classLoaderService.classForName(jpaCallbackClass.getName()); String methodName = jpaCallbackClass.getCallbackMethod(callbackClass); Callback callback = jpaCallbackClass.isListener() ? createListenerCallback(entityClass, callbackClass, listener, methodName) : createBeanCallback(callbackClass, methodName); LOG.debugf( "Adding %s as %s callback for entity %s", methodName, callbackClass.getName(), entityClass.getName()); assert callback != null; callbacks.add(callback); } return callbacks.toArray(new Callback[callbacks.size()]); }
public EntityMetamodel(EntityBinding entityBinding, SessionFactoryImplementor sessionFactory) { this.sessionFactory = sessionFactory; name = entityBinding.getEntity().getName(); rootName = entityBinding.getHierarchyDetails().getRootEntityBinding().getEntity().getName(); entityType = sessionFactory.getTypeResolver().getTypeFactory().manyToOne(name); identifierProperty = PropertyFactory.buildIdentifierProperty( entityBinding, sessionFactory.getIdentifierGenerator(rootName)); versioned = entityBinding.isVersioned(); boolean hasPojoRepresentation = false; Class<?> mappedClass = null; Class<?> proxyInterfaceClass = null; if (entityBinding.getEntity().getClassReferenceUnresolved() != null) { hasPojoRepresentation = true; mappedClass = entityBinding.getEntity().getClassReference(); proxyInterfaceClass = entityBinding.getProxyInterfaceType().getValue(); } instrumentationMetadata = Environment.getBytecodeProvider().getEntityInstrumentationMetadata(mappedClass); boolean hasLazy = false; // TODO: Fix after HHH-6337 is fixed; for now assume entityBinding is the root binding BasicAttributeBinding rootEntityIdentifier = entityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding(); // entityBinding.getAttributeClosureSpan() includes the identifier binding; // "properties" here excludes the ID, so subtract 1 if the identifier binding is non-null propertySpan = rootEntityIdentifier == null ? entityBinding.getAttributeBindingClosureSpan() : entityBinding.getAttributeBindingClosureSpan() - 1; properties = new StandardProperty[propertySpan]; List naturalIdNumbers = new ArrayList(); // temporary ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ propertyNames = new String[propertySpan]; propertyTypes = new Type[propertySpan]; propertyUpdateability = new boolean[propertySpan]; propertyInsertability = new boolean[propertySpan]; insertInclusions = new ValueInclusion[propertySpan]; updateInclusions = new ValueInclusion[propertySpan]; nonlazyPropertyUpdateability = new boolean[propertySpan]; propertyCheckability = new boolean[propertySpan]; propertyNullability = new boolean[propertySpan]; propertyVersionability = new boolean[propertySpan]; propertyLaziness = new boolean[propertySpan]; cascadeStyles = new CascadeStyle[propertySpan]; // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int i = 0; int tempVersionProperty = NO_VERSION_INDX; boolean foundCascade = false; boolean foundCollection = false; boolean foundMutable = false; boolean foundNonIdentifierPropertyNamedId = false; boolean foundInsertGeneratedValue = false; boolean foundUpdateGeneratedValue = false; boolean foundUpdateableNaturalIdProperty = false; for (AttributeBinding attributeBinding : entityBinding.getAttributeBindingClosure()) { if (attributeBinding == rootEntityIdentifier) { // skip the identifier attribute binding continue; } if (attributeBinding == entityBinding.getHierarchyDetails().getVersioningAttributeBinding()) { tempVersionProperty = i; properties[i] = PropertyFactory.buildVersionProperty( entityBinding.getHierarchyDetails().getVersioningAttributeBinding(), instrumentationMetadata.isInstrumented()); } else { properties[i] = PropertyFactory.buildStandardProperty( attributeBinding, instrumentationMetadata.isInstrumented()); } // TODO: fix when natural IDs are added (HHH-6354) // if ( attributeBinding.isNaturalIdentifier() ) { // naturalIdNumbers.add( i ); // if ( attributeBinding.isUpdateable() ) { // foundUpdateableNaturalIdProperty = true; // } // } if ("id".equals(attributeBinding.getAttribute().getName())) { foundNonIdentifierPropertyNamedId = true; } // temporary ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ boolean lazy = attributeBinding.isLazy() && instrumentationMetadata.isInstrumented(); if (lazy) hasLazy = true; propertyLaziness[i] = lazy; propertyNames[i] = properties[i].getName(); propertyTypes[i] = properties[i].getType(); propertyNullability[i] = properties[i].isNullable(); propertyUpdateability[i] = properties[i].isUpdateable(); propertyInsertability[i] = properties[i].isInsertable(); insertInclusions[i] = determineInsertValueGenerationType(attributeBinding, properties[i]); updateInclusions[i] = determineUpdateValueGenerationType(attributeBinding, properties[i]); propertyVersionability[i] = properties[i].isVersionable(); nonlazyPropertyUpdateability[i] = properties[i].isUpdateable() && !lazy; propertyCheckability[i] = propertyUpdateability[i] || (propertyTypes[i].isAssociationType() && ((AssociationType) propertyTypes[i]).isAlwaysDirtyChecked()); cascadeStyles[i] = properties[i].getCascadeStyle(); // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (properties[i].isLazy()) { hasLazy = true; } if (properties[i].getCascadeStyle() != CascadeStyles.NONE) { foundCascade = true; } if (indicatesCollection(properties[i].getType())) { foundCollection = true; } if (propertyTypes[i].isMutable() && propertyCheckability[i]) { foundMutable = true; } if (insertInclusions[i] != ValueInclusion.NONE) { foundInsertGeneratedValue = true; } if (updateInclusions[i] != ValueInclusion.NONE) { foundUpdateGeneratedValue = true; } mapPropertyToIndex(attributeBinding.getAttribute(), i); i++; } if (naturalIdNumbers.size() == 0) { naturalIdPropertyNumbers = null; hasImmutableNaturalId = false; hasCacheableNaturalId = false; } else { naturalIdPropertyNumbers = ArrayHelper.toIntArray(naturalIdNumbers); hasImmutableNaturalId = !foundUpdateableNaturalIdProperty; hasCacheableNaturalId = false; // See previous TODO and HHH-6354 } hasInsertGeneratedValues = foundInsertGeneratedValue; hasUpdateGeneratedValues = foundUpdateGeneratedValue; hasCascades = foundCascade; hasNonIdentifierPropertyNamedId = foundNonIdentifierPropertyNamedId; versionPropertyIndex = tempVersionProperty; hasLazyProperties = hasLazy; if (hasLazyProperties) { LOG.lazyPropertyFetchingAvailable(name); } lazy = entityBinding.isLazy() && ( // TODO: this disables laziness even in non-pojo entity modes: !hasPojoRepresentation || !ReflectHelper.isFinalClass(proxyInterfaceClass)); mutable = entityBinding.isMutable(); if (entityBinding.isAbstract() == null) { // legacy behavior (with no abstract attribute specified) isAbstract = hasPojoRepresentation && ReflectHelper.isAbstractClass(mappedClass); } else { isAbstract = entityBinding.isAbstract().booleanValue(); if (!isAbstract && hasPojoRepresentation && ReflectHelper.isAbstractClass(mappedClass)) { LOG.entityMappedAsNonAbstract(name); } } selectBeforeUpdate = entityBinding.isSelectBeforeUpdate(); dynamicUpdate = entityBinding.isDynamicUpdate(); dynamicInsert = entityBinding.isDynamicInsert(); hasSubclasses = entityBinding.hasSubEntityBindings(); polymorphic = entityBinding.isPolymorphic(); explicitPolymorphism = entityBinding.getHierarchyDetails().isExplicitPolymorphism(); inherited = !entityBinding.isRoot(); superclass = inherited ? entityBinding.getEntity().getSuperType().getName() : null; optimisticLockStyle = entityBinding.getHierarchyDetails().getOptimisticLockStyle(); final boolean isAllOrDirty = optimisticLockStyle == OptimisticLockStyle.ALL || optimisticLockStyle == OptimisticLockStyle.DIRTY; if (isAllOrDirty && !dynamicUpdate) { throw new MappingException( "optimistic-lock=all|dirty requires dynamic-update=\"true\": " + name); } if (versionPropertyIndex != NO_VERSION_INDX && isAllOrDirty) { throw new MappingException( "version and optimistic-lock=all|dirty are not a valid combination : " + name); } hasCollections = foundCollection; hasMutableProperties = foundMutable; for (EntityBinding subEntityBinding : entityBinding.getPostOrderSubEntityBindingClosure()) { subclassEntityNames.add(subEntityBinding.getEntity().getName()); if (subEntityBinding.getEntity().getClassReference() != null) { entityNameByInheritenceClassMap.put( subEntityBinding.getEntity().getClassReference(), subEntityBinding.getEntity().getName()); } } subclassEntityNames.add(name); if (mappedClass != null) { entityNameByInheritenceClassMap.put(mappedClass, name); } entityMode = hasPojoRepresentation ? EntityMode.POJO : EntityMode.MAP; final EntityTuplizerFactory entityTuplizerFactory = sessionFactory.getSettings().getEntityTuplizerFactory(); Class<? extends EntityTuplizer> tuplizerClass = entityBinding.getCustomEntityTuplizerClass(); if (tuplizerClass == null) { entityTuplizer = entityTuplizerFactory.constructDefaultTuplizer(entityMode, this, entityBinding); } else { entityTuplizer = entityTuplizerFactory.constructTuplizer(tuplizerClass, this, entityBinding); } }
@Test @Resources(annotatedClasses = RowIdEntity.class) public void testRowId() { EntityBinding binding = getEntityBinding(RowIdEntity.class); assertEquals("Wrong row id", "rowid", binding.getRowId()); }