use of org.hibernate.AnnotationException in project hibernate-orm by hibernate.
the class CollectionBinder method bindManyToManySecondPass.
private void bindManyToManySecondPass(Collection collValue, Map persistentClasses, Ejb3JoinColumn[] joinColumns, Ejb3JoinColumn[] inverseJoinColumns, Ejb3Column[] elementColumns, boolean isEmbedded, XClass collType, boolean ignoreNotFound, boolean unique, boolean cascadeDeleteEnabled, TableBinder associationTableBinder, XProperty property, PropertyHolder parentPropertyHolder, MetadataBuildingContext buildingContext) throws MappingException {
if (property == null) {
throw new IllegalArgumentException("null was passed for argument property");
}
final PersistentClass collectionEntity = (PersistentClass) persistentClasses.get(collType.getName());
final String hqlOrderBy = extractHqlOrderBy(jpaOrderBy);
boolean isCollectionOfEntities = collectionEntity != null;
ManyToAny anyAnn = property.getAnnotation(ManyToAny.class);
if (LOG.isDebugEnabled()) {
String path = collValue.getOwnerEntityName() + "." + joinColumns[0].getPropertyName();
if (isCollectionOfEntities && unique) {
LOG.debugf("Binding a OneToMany: %s through an association table", path);
} else if (isCollectionOfEntities) {
LOG.debugf("Binding as ManyToMany: %s", path);
} else if (anyAnn != null) {
LOG.debugf("Binding a ManyToAny: %s", path);
} else {
LOG.debugf("Binding a collection of element: %s", path);
}
}
// check for user error
if (!isCollectionOfEntities) {
if (property.isAnnotationPresent(ManyToMany.class) || property.isAnnotationPresent(OneToMany.class)) {
String path = collValue.getOwnerEntityName() + "." + joinColumns[0].getPropertyName();
throw new AnnotationException("Use of @OneToMany or @ManyToMany targeting an unmapped class: " + path + "[" + collType + "]");
} else if (anyAnn != null) {
if (parentPropertyHolder.getJoinTable(property) == null) {
String path = collValue.getOwnerEntityName() + "." + joinColumns[0].getPropertyName();
throw new AnnotationException("@JoinTable is mandatory when @ManyToAny is used: " + path);
}
} else {
JoinTable joinTableAnn = parentPropertyHolder.getJoinTable(property);
if (joinTableAnn != null && joinTableAnn.inverseJoinColumns().length > 0) {
String path = collValue.getOwnerEntityName() + "." + joinColumns[0].getPropertyName();
throw new AnnotationException("Use of @JoinTable.inverseJoinColumns targeting an unmapped class: " + path + "[" + collType + "]");
}
}
}
boolean mappedBy = !BinderHelper.isEmptyAnnotationValue(joinColumns[0].getMappedBy());
if (mappedBy) {
if (!isCollectionOfEntities) {
throw new AnnotationException("Collection of elements must not have mappedBy or association reference an unmapped entity: " + collValue.getOwnerEntityName() + "." + joinColumns[0].getPropertyName());
}
Property otherSideProperty;
try {
otherSideProperty = collectionEntity.getRecursiveProperty(joinColumns[0].getMappedBy());
} catch (MappingException e) {
throw new AnnotationException("mappedBy reference an unknown target entity property: " + collType + "." + joinColumns[0].getMappedBy() + " in " + collValue.getOwnerEntityName() + "." + joinColumns[0].getPropertyName());
}
Table table;
if (otherSideProperty.getValue() instanceof Collection) {
// this is a collection on the other side
table = ((Collection) otherSideProperty.getValue()).getCollectionTable();
} else {
// This is a ToOne with a @JoinTable or a regular property
table = otherSideProperty.getValue().getTable();
}
collValue.setCollectionTable(table);
String entityName = collectionEntity.getEntityName();
for (Ejb3JoinColumn column : joinColumns) {
// column.setDefaultColumnHeader( joinColumns[0].getMappedBy() ); //seems not to be used, make sense
column.setManyToManyOwnerSideEntityName(entityName);
}
} else {
// FIXME NamingStrategy
for (Ejb3JoinColumn column : joinColumns) {
String mappedByProperty = buildingContext.getMetadataCollector().getFromMappedBy(collValue.getOwnerEntityName(), column.getPropertyName());
Table ownerTable = collValue.getOwner().getTable();
column.setMappedBy(collValue.getOwner().getEntityName(), collValue.getOwner().getJpaEntityName(), buildingContext.getMetadataCollector().getLogicalTableName(ownerTable), mappedByProperty);
// String header = ( mappedByProperty == null ) ? mappings.getLogicalTableName( ownerTable ) : mappedByProperty;
// column.setDefaultColumnHeader( header );
}
if (StringHelper.isEmpty(associationTableBinder.getName())) {
// default value
associationTableBinder.setDefaultName(collValue.getOwner().getClassName(), collValue.getOwner().getEntityName(), collValue.getOwner().getJpaEntityName(), buildingContext.getMetadataCollector().getLogicalTableName(collValue.getOwner().getTable()), collectionEntity != null ? collectionEntity.getClassName() : null, collectionEntity != null ? collectionEntity.getEntityName() : null, collectionEntity != null ? collectionEntity.getJpaEntityName() : null, collectionEntity != null ? buildingContext.getMetadataCollector().getLogicalTableName(collectionEntity.getTable()) : null, joinColumns[0].getPropertyName());
}
associationTableBinder.setJPA2ElementCollection(!isCollectionOfEntities && property.isAnnotationPresent(ElementCollection.class));
collValue.setCollectionTable(associationTableBinder.bind());
}
bindFilters(isCollectionOfEntities);
bindCollectionSecondPass(collValue, collectionEntity, joinColumns, cascadeDeleteEnabled, property, propertyHolder, buildingContext);
ManyToOne element = null;
if (isCollectionOfEntities) {
element = new ManyToOne(buildingContext, collValue.getCollectionTable());
collValue.setElement(element);
element.setReferencedEntityName(collType.getName());
// element.setFetchMode( fetchMode );
// element.setLazy( fetchMode != FetchMode.JOIN );
// make the second join non lazy
element.setFetchMode(FetchMode.JOIN);
element.setLazy(false);
element.setIgnoreNotFound(ignoreNotFound);
// as per 11.1.38 of JPA 2.0 spec, default to primary key if no column is specified by @OrderBy.
if (hqlOrderBy != null) {
collValue.setManyToManyOrdering(buildOrderByClauseFromHql(hqlOrderBy, collectionEntity, collValue.getRole()));
}
final ForeignKey fk = property.getAnnotation(ForeignKey.class);
if (fk != null && !BinderHelper.isEmptyAnnotationValue(fk.name())) {
element.setForeignKeyName(fk.name());
} else {
final JoinTable joinTableAnn = property.getAnnotation(JoinTable.class);
if (joinTableAnn != null) {
String foreignKeyName = joinTableAnn.inverseForeignKey().name();
String foreignKeyDefinition = joinTableAnn.inverseForeignKey().foreignKeyDefinition();
ConstraintMode foreignKeyValue = joinTableAnn.inverseForeignKey().value();
if (joinTableAnn.inverseJoinColumns().length != 0) {
final JoinColumn joinColumnAnn = joinTableAnn.inverseJoinColumns()[0];
if ("".equals(foreignKeyName)) {
foreignKeyName = joinColumnAnn.foreignKey().name();
foreignKeyDefinition = joinColumnAnn.foreignKey().foreignKeyDefinition();
}
if (foreignKeyValue != ConstraintMode.NO_CONSTRAINT) {
foreignKeyValue = joinColumnAnn.foreignKey().value();
}
}
if (joinTableAnn.inverseForeignKey().value() == ConstraintMode.NO_CONSTRAINT) {
element.setForeignKeyName("none");
} else {
element.setForeignKeyName(StringHelper.nullIfEmpty(foreignKeyName));
element.setForeignKeyDefinition(StringHelper.nullIfEmpty(foreignKeyDefinition));
}
}
}
} else if (anyAnn != null) {
// @ManyToAny
// Make sure that collTyp is never used during the @ManyToAny branch: it will be set to void.class
PropertyData inferredData = new PropertyInferredData(null, property, "unsupported", buildingContext.getBootstrapContext().getReflectionManager());
// override the table
for (Ejb3Column column : inverseJoinColumns) {
column.setTable(collValue.getCollectionTable());
}
Any any = BinderHelper.buildAnyValue(anyAnn.metaDef(), inverseJoinColumns, anyAnn.metaColumn(), inferredData, cascadeDeleteEnabled, Nullability.NO_CONSTRAINT, propertyHolder, new EntityBinder(), true, buildingContext);
collValue.setElement(any);
} else {
XClass elementClass;
AnnotatedClassType classType;
CollectionPropertyHolder holder;
if (BinderHelper.PRIMITIVE_NAMES.contains(collType.getName())) {
classType = AnnotatedClassType.NONE;
elementClass = null;
holder = PropertyHolderBuilder.buildPropertyHolder(collValue, collValue.getRole(), null, property, parentPropertyHolder, buildingContext);
} else {
elementClass = collType;
classType = buildingContext.getMetadataCollector().getClassType(elementClass);
holder = PropertyHolderBuilder.buildPropertyHolder(collValue, collValue.getRole(), elementClass, property, parentPropertyHolder, buildingContext);
// 'parentPropertyHolder' is the PropertyHolder for the owner of the collection
// 'holder' is the CollectionPropertyHolder.
// 'property' is the collection XProperty
parentPropertyHolder.startingProperty(property);
// force in case of attribute override
boolean attributeOverride = property.isAnnotationPresent(AttributeOverride.class) || property.isAnnotationPresent(AttributeOverrides.class);
// todo : force in the case of Convert annotation(s) with embedded paths (beyond key/value prefixes)?
if (isEmbedded || attributeOverride) {
classType = AnnotatedClassType.EMBEDDABLE;
}
}
if (AnnotatedClassType.EMBEDDABLE.equals(classType)) {
holder.prepare(property);
EntityBinder entityBinder = new EntityBinder();
PersistentClass owner = collValue.getOwner();
boolean isPropertyAnnotated;
// String accessType = access != null ? access.value() : null;
if (owner.getIdentifierProperty() != null) {
isPropertyAnnotated = owner.getIdentifierProperty().getPropertyAccessorName().equals("property");
} else if (owner.getIdentifierMapper() != null && owner.getIdentifierMapper().getPropertySpan() > 0) {
Property prop = (Property) owner.getIdentifierMapper().getPropertyIterator().next();
isPropertyAnnotated = prop.getPropertyAccessorName().equals("property");
} else {
throw new AssertionFailure("Unable to guess collection property accessor name");
}
PropertyData inferredData;
if (isMap()) {
// "value" is the JPA 2 prefix for map values (used to be "element")
if (isHibernateExtensionMapping()) {
inferredData = new PropertyPreloadedData(AccessType.PROPERTY, "element", elementClass);
} else {
inferredData = new PropertyPreloadedData(AccessType.PROPERTY, "value", elementClass);
}
} else {
if (isHibernateExtensionMapping()) {
inferredData = new PropertyPreloadedData(AccessType.PROPERTY, "element", elementClass);
} else {
// "collection&&element" is not a valid property name => placeholder
inferredData = new PropertyPreloadedData(AccessType.PROPERTY, "collection&&element", elementClass);
}
}
// TODO be smart with isNullable
boolean isNullable = true;
Component component = AnnotationBinder.fillComponent(holder, inferredData, isPropertyAnnotated ? AccessType.PROPERTY : AccessType.FIELD, isNullable, entityBinder, false, false, true, buildingContext, inheritanceStatePerClass);
collValue.setElement(component);
if (StringHelper.isNotEmpty(hqlOrderBy)) {
String orderBy = adjustUserSuppliedValueCollectionOrderingFragment(hqlOrderBy);
if (orderBy != null) {
collValue.setOrderBy(orderBy);
}
}
} else {
holder.prepare(property);
SimpleValueBinder elementBinder = new SimpleValueBinder();
elementBinder.setBuildingContext(buildingContext);
elementBinder.setReturnedClassName(collType.getName());
if (elementColumns == null || elementColumns.length == 0) {
elementColumns = new Ejb3Column[1];
Ejb3Column column = new Ejb3Column();
column.setImplicit(false);
// not following the spec but more clean
column.setNullable(true);
column.setLength(Ejb3Column.DEFAULT_COLUMN_LENGTH);
column.setLogicalColumnName(Collection.DEFAULT_ELEMENT_COLUMN_NAME);
// TODO create an EMPTY_JOINS collection
column.setJoins(new HashMap<>());
column.setBuildingContext(buildingContext);
column.bind();
elementColumns[0] = column;
}
// override the table
for (Ejb3Column column : elementColumns) {
column.setTable(collValue.getCollectionTable());
}
elementBinder.setColumns(elementColumns);
elementBinder.setType(property, elementClass, collValue.getOwnerEntityName(), holder.resolveElementAttributeConverterDescriptor(property, elementClass));
elementBinder.setPersistentClassName(propertyHolder.getEntityName());
elementBinder.setAccessType(accessType);
collValue.setElement(elementBinder.make());
String orderBy = adjustUserSuppliedValueCollectionOrderingFragment(hqlOrderBy);
if (orderBy != null) {
collValue.setOrderBy(orderBy);
}
}
}
checkFilterConditions(collValue);
// FIXME: do optional = false
if (isCollectionOfEntities) {
bindManytoManyInverseFk(collectionEntity, inverseJoinColumns, element, unique, buildingContext);
}
}
use of org.hibernate.AnnotationException in project hibernate-orm by hibernate.
the class PropertyBinder method getValueGenerationFromAnnotation.
/**
* In case the given annotation is a value generator annotation, the corresponding value generation strategy to be
* applied to the given property is returned, {@code null} otherwise.
*/
private <A extends Annotation> AnnotationValueGeneration<A> getValueGenerationFromAnnotation(XProperty property, A annotation) {
ValueGenerationType generatorAnnotation = annotation.annotationType().getAnnotation(ValueGenerationType.class);
if (generatorAnnotation == null) {
return null;
}
Class<? extends AnnotationValueGeneration<?>> generationType = generatorAnnotation.generatedBy();
AnnotationValueGeneration<A> valueGeneration = instantiateAndInitializeValueGeneration(annotation, generationType, property);
if (annotation.annotationType() == Generated.class && property.isAnnotationPresent(javax.persistence.Version.class) && valueGeneration.getGenerationTiming() == GenerationTiming.INSERT) {
throw new AnnotationException("@Generated(INSERT) on a @Version property not allowed, use ALWAYS (or NEVER): " + StringHelper.qualify(holder.getPath(), name));
}
return valueGeneration;
}
use of org.hibernate.AnnotationException in project hibernate-orm by hibernate.
the class PropertyBinder method makeProperty.
// used when the value is provided and the binding is done elsewhere
public Property makeProperty() {
validateMake();
LOG.debugf("Building property %s", name);
Property prop = new Property();
prop.setName(name);
prop.setValue(value);
prop.setLazy(lazy);
prop.setLazyGroup(lazyGroup);
prop.setCascade(cascade);
prop.setPropertyAccessorName(accessType.getType());
if (property != null) {
prop.setValueGenerationStrategy(determineValueGenerationStrategy(property));
if (property.isAnnotationPresent(AttributeAccessor.class)) {
final AttributeAccessor accessor = property.getAnnotation(AttributeAccessor.class);
prop.setPropertyAccessorName(accessor.value());
}
}
NaturalId naturalId = property != null ? property.getAnnotation(NaturalId.class) : null;
if (naturalId != null) {
if (!entityBinder.isRootEntity()) {
throw new AnnotationException("@NaturalId only valid on root entity (or its @MappedSuperclasses)");
}
if (!naturalId.mutable()) {
updatable = false;
}
prop.setNaturalIdentifier(true);
}
// HHH-4635 -- needed for dialect-specific property ordering
Lob lob = property != null ? property.getAnnotation(Lob.class) : null;
prop.setLob(lob != null);
prop.setInsertable(insertable);
prop.setUpdateable(updatable);
// this is already handled for collections in CollectionBinder...
if (Collection.class.isInstance(value)) {
prop.setOptimisticLocked(((Collection) value).isOptimisticLocked());
} else {
final OptimisticLock lockAnn = property != null ? property.getAnnotation(OptimisticLock.class) : null;
if (lockAnn != null) {
// TODO this should go to the core as a mapping validation checking
if (lockAnn.excluded() && (property.isAnnotationPresent(javax.persistence.Version.class) || property.isAnnotationPresent(Id.class) || property.isAnnotationPresent(EmbeddedId.class))) {
throw new AnnotationException("@OptimisticLock.exclude=true incompatible with @Id, @EmbeddedId and @Version: " + StringHelper.qualify(holder.getPath(), name));
}
}
// && updatable as well???
final boolean isOwnedValue = !isToOneValue(value) || insertable;
final boolean includeInOptimisticLockChecks = (lockAnn != null) ? !lockAnn.excluded() : isOwnedValue;
prop.setOptimisticLocked(includeInOptimisticLockChecks);
}
LOG.tracev("Cascading {0} with {1}", name, cascade);
this.mappingProperty = prop;
return prop;
}
use of org.hibernate.AnnotationException in project hibernate-orm by hibernate.
the class TableBinder method bindFk.
public static void bindFk(PersistentClass referencedEntity, PersistentClass destinationEntity, Ejb3JoinColumn[] columns, SimpleValue value, boolean unique, MetadataBuildingContext buildingContext) {
PersistentClass associatedClass;
if (destinationEntity != null) {
// overridden destination
associatedClass = destinationEntity;
} else {
associatedClass = columns[0].getPropertyHolder() == null ? null : columns[0].getPropertyHolder().getPersistentClass();
}
final String mappedByProperty = columns[0].getMappedBy();
if (StringHelper.isNotEmpty(mappedByProperty)) {
/**
* Get the columns of the mapped-by property
* copy them and link the copy to the actual value
*/
LOG.debugf("Retrieving property %s.%s", associatedClass.getEntityName(), mappedByProperty);
final Property property = associatedClass.getRecursiveProperty(columns[0].getMappedBy());
Iterator mappedByColumns;
if (property.getValue() instanceof Collection) {
Collection collection = ((Collection) property.getValue());
Value element = collection.getElement();
if (element == null) {
throw new AnnotationException("Illegal use of mappedBy on both sides of the relationship: " + associatedClass.getEntityName() + "." + mappedByProperty);
}
mappedByColumns = element.getColumnIterator();
} else {
mappedByColumns = property.getValue().getColumnIterator();
}
while (mappedByColumns.hasNext()) {
Column column = (Column) mappedByColumns.next();
columns[0].overrideFromReferencedColumnIfNecessary(column);
columns[0].linkValueUsingAColumnCopy(column, value);
}
} else if (columns[0].isImplicit()) {
/**
* if columns are implicit, then create the columns based on the
* referenced entity id columns
*/
Iterator idColumns;
if (referencedEntity instanceof JoinedSubclass) {
idColumns = referencedEntity.getKey().getColumnIterator();
} else {
idColumns = referencedEntity.getIdentifier().getColumnIterator();
}
while (idColumns.hasNext()) {
Column column = (Column) idColumns.next();
columns[0].linkValueUsingDefaultColumnNaming(column, referencedEntity, value);
columns[0].overrideFromReferencedColumnIfNecessary(column);
}
} else {
int fkEnum = Ejb3JoinColumn.checkReferencedColumnsType(columns, referencedEntity, buildingContext);
if (Ejb3JoinColumn.NON_PK_REFERENCE == fkEnum) {
String referencedPropertyName;
if (value instanceof ToOne) {
referencedPropertyName = ((ToOne) value).getReferencedPropertyName();
} else if (value instanceof DependantValue) {
String propertyName = columns[0].getPropertyName();
if (propertyName != null) {
Collection collection = (Collection) referencedEntity.getRecursiveProperty(propertyName).getValue();
referencedPropertyName = collection.getReferencedPropertyName();
} else {
throw new AnnotationException("SecondaryTable JoinColumn cannot reference a non primary key");
}
} else {
throw new AssertionFailure("Do a property ref on an unexpected Value type: " + value.getClass().getName());
}
if (referencedPropertyName == null) {
throw new AssertionFailure("No property ref found while expected");
}
Property synthProp = referencedEntity.getReferencedProperty(referencedPropertyName);
if (synthProp == null) {
throw new AssertionFailure("Cannot find synthProp: " + referencedEntity.getEntityName() + "." + referencedPropertyName);
}
linkJoinColumnWithValueOverridingNameIfImplicit(referencedEntity, synthProp.getColumnIterator(), columns, value);
} else {
if (Ejb3JoinColumn.NO_REFERENCE == fkEnum) {
// implicit case, we hope PK and FK columns are in the same order
if (columns.length != referencedEntity.getIdentifier().getColumnSpan()) {
throw new AnnotationException("A Foreign key refering " + referencedEntity.getEntityName() + " from " + associatedClass.getEntityName() + " has the wrong number of column. should be " + referencedEntity.getIdentifier().getColumnSpan());
}
linkJoinColumnWithValueOverridingNameIfImplicit(referencedEntity, referencedEntity.getIdentifier().getColumnIterator(), columns, value);
} else {
// explicit referencedColumnName
Iterator idColItr = referencedEntity.getKey().getColumnIterator();
org.hibernate.mapping.Column col;
// works cause the pk has to be on the primary table
Table table = referencedEntity.getTable();
if (!idColItr.hasNext()) {
LOG.debug("No column in the identifier!");
}
while (idColItr.hasNext()) {
boolean match = false;
// for each PK column, find the associated FK column.
col = (org.hibernate.mapping.Column) idColItr.next();
for (Ejb3JoinColumn joinCol : columns) {
String referencedColumn = joinCol.getReferencedColumn();
referencedColumn = buildingContext.getMetadataCollector().getPhysicalColumnName(table, referencedColumn);
// In JPA 2 referencedColumnName is case insensitive
if (referencedColumn.equalsIgnoreCase(col.getQuotedName(buildingContext.getMetadataCollector().getDatabase().getJdbcEnvironment().getDialect()))) {
// proper join column
if (joinCol.isNameDeferred()) {
joinCol.linkValueUsingDefaultColumnNaming(col, referencedEntity, value);
} else {
joinCol.linkWithValue(value);
}
joinCol.overrideFromReferencedColumnIfNecessary(col);
match = true;
break;
}
}
if (!match) {
throw new AnnotationException("Column name " + col.getName() + " of " + referencedEntity.getEntityName() + " not found in JoinColumns.referencedColumnName");
}
}
}
}
}
value.createForeignKey();
if (unique) {
createUniqueConstraint(value);
}
}
use of org.hibernate.AnnotationException in project hibernate-orm by hibernate.
the class CopyIdentifierComponentSecondPass method doSecondPass.
@SuppressWarnings({ "unchecked" })
public void doSecondPass(Map persistentClasses) throws MappingException {
PersistentClass referencedPersistentClass = (PersistentClass) persistentClasses.get(referencedEntityName);
// TODO better error names
if (referencedPersistentClass == null) {
throw new AnnotationException("Unknown entity name: " + referencedEntityName);
}
if (!(referencedPersistentClass.getIdentifier() instanceof Component)) {
throw new AssertionFailure("Unexpected identifier type on the referenced entity when mapping a @MapsId: " + referencedEntityName);
}
Component referencedComponent = (Component) referencedPersistentClass.getIdentifier();
Iterator<Property> properties = referencedComponent.getPropertyIterator();
// prepare column name structure
boolean isExplicitReference = true;
Map<String, Ejb3JoinColumn> columnByReferencedName = new HashMap<>(joinColumns.length);
for (Ejb3JoinColumn joinColumn : joinColumns) {
final String referencedColumnName = joinColumn.getReferencedColumn();
if (referencedColumnName == null || BinderHelper.isEmptyAnnotationValue(referencedColumnName)) {
break;
}
// JPA 2 requires referencedColumnNames to be case insensitive
columnByReferencedName.put(referencedColumnName.toLowerCase(Locale.ROOT), joinColumn);
}
// try default column orientation
AtomicInteger index = new AtomicInteger(0);
if (columnByReferencedName.isEmpty()) {
isExplicitReference = false;
for (Ejb3JoinColumn joinColumn : joinColumns) {
columnByReferencedName.put("" + index.get(), joinColumn);
index.getAndIncrement();
}
index.set(0);
}
while (properties.hasNext()) {
Property referencedProperty = properties.next();
if (referencedProperty.isComposite()) {
Property property = createComponentProperty(referencedPersistentClass, isExplicitReference, columnByReferencedName, index, referencedProperty);
component.addProperty(property);
} else {
Property property = createSimpleProperty(referencedPersistentClass, isExplicitReference, columnByReferencedName, index, referencedProperty);
component.addProperty(property);
}
}
}
Aggregations