use of org.hibernate.annotations.NotFoundAction in project hibernate-orm by hibernate.
the class AnnotationBinder method bindManyToOne.
private static void bindManyToOne(PropertyHolder propertyHolder, PropertyData inferredData, boolean isIdentifierMapper, boolean inSecondPass, MetadataBuildingContext context, XProperty property, AnnotatedJoinColumn[] joinColumns, PropertyBinder propertyBinder, boolean forcePersist) {
ManyToOne ann = property.getAnnotation(ManyToOne.class);
// check validity
if (property.isAnnotationPresent(Column.class) || property.isAnnotationPresent(Columns.class)) {
throw new AnnotationException("@Column(s) not allowed on a @ManyToOne property: " + BinderHelper.getPath(propertyHolder, inferredData));
}
Cascade hibernateCascade = property.getAnnotation(Cascade.class);
NotFound notFound = property.getAnnotation(NotFound.class);
NotFoundAction notFoundAction = notFound == null ? null : notFound.action();
matchIgnoreNotFoundWithFetchType(propertyHolder.getEntityName(), property.getName(), notFoundAction, ann.fetch());
OnDelete onDeleteAnn = property.getAnnotation(OnDelete.class);
JoinTable assocTable = propertyHolder.getJoinTable(property);
if (assocTable != null) {
Join join = propertyHolder.addJoin(assocTable, false);
for (AnnotatedJoinColumn joinColumn : joinColumns) {
joinColumn.setExplicitTableName(join.getTable().getName());
}
}
// MapsId means the columns belong to the pk;
// A @MapsId association (obviously) must be non-null when the entity is first persisted.
// If a @MapsId association is not mapped with @NotFound(IGNORE), then the association
// is mandatory (even if the association has optional=true).
// If a @MapsId association has optional=true and is mapped with @NotFound(IGNORE) then
// the association is optional.
final boolean mandatory = !ann.optional() || property.isAnnotationPresent(Id.class) || property.isAnnotationPresent(MapsId.class) && notFoundAction != null;
bindManyToOne(getCascadeStrategy(ann.cascade(), hibernateCascade, false, forcePersist), joinColumns, !mandatory, notFoundAction, onDeleteAnn != null && OnDeleteAction.CASCADE == onDeleteAnn.action(), ToOneBinder.getTargetEntity(inferredData, context), propertyHolder, inferredData, false, isIdentifierMapper, inSecondPass, propertyBinder, context);
}
use of org.hibernate.annotations.NotFoundAction in project hibernate-orm by hibernate.
the class CollectionBinderTest method testAssociatedClassException.
@Test
@TestForIssue(jiraKey = "HHH-10106")
public void testAssociatedClassException() throws SQLException {
final Collection collection = mock(Collection.class);
final XClass collectionType = mock(XClass.class);
final MetadataBuildingContext buildingContext = mock(MetadataBuildingContext.class);
final InFlightMetadataCollector inFly = mock(InFlightMetadataCollector.class);
final PersistentClass persistentClass = mock(PersistentClass.class);
final Table table = mock(Table.class);
when(buildingContext.getMetadataCollector()).thenReturn(inFly);
when(collection.getOwner()).thenReturn(persistentClass);
when(collectionType.getName()).thenReturn("List");
when(persistentClass.getTable()).thenReturn(table);
when(table.getName()).thenReturn("Hibernate");
String expectMessage = "Association [abc] for entity [CollectionBinderTest] references unmapped class [List]";
try {
new CollectionBinder(null, false, buildingContext) {
{
final PropertyHolder propertyHolder = Mockito.mock(PropertyHolder.class);
when(propertyHolder.getClassName()).thenReturn(CollectionBinderTest.class.getSimpleName());
this.propertyName = "abc";
setPropertyHolder(propertyHolder);
}
@Override
protected Collection createCollection(PersistentClass persistentClass) {
return null;
}
@Override
public void bindOneToManySecondPass(Collection collection, Map<String, PersistentClass> persistentClasses, AnnotatedJoinColumn[] fkJoinColumns, XClass collectionType, boolean cascadeDeleteEnabled, NotFoundAction notFoundAction, MetadataBuildingContext buildingContext, Map<XClass, InheritanceState> inheritanceStatePerClass) {
super.bindOneToManySecondPass(collection, persistentClasses, fkJoinColumns, collectionType, cascadeDeleteEnabled, notFoundAction, buildingContext, inheritanceStatePerClass);
}
}.bindOneToManySecondPass(collection, new HashMap(), null, collectionType, false, null, buildingContext, null);
} catch (MappingException e) {
assertEquals(expectMessage, e.getMessage());
}
}
use of org.hibernate.annotations.NotFoundAction in project hibernate-orm by hibernate.
the class MappingModelCreationHelper method interpretElement.
private static CollectionPart interpretElement(Collection bootDescriptor, String tableExpression, CollectionPersister collectionDescriptor, String sqlAliasStem, Dialect dialect, MappingModelCreationProcess creationProcess) {
final Value element = bootDescriptor.getElement();
if (element instanceof BasicValue) {
final BasicValue basicElement = (BasicValue) element;
final SelectableMapping selectableMapping = SelectableMappingImpl.from(tableExpression, basicElement.getSelectables().get(0), basicElement.resolve().getJdbcMapping(), creationProcess.getCreationContext().getTypeConfiguration(), dialect, creationProcess.getSqmFunctionRegistry());
return new BasicValuedCollectionPart(collectionDescriptor, CollectionPart.Nature.ELEMENT, basicElement.resolve().getValueConverter(), selectableMapping);
}
if (element instanceof Component) {
final Component component = (Component) element;
final CompositeType compositeType = (CompositeType) collectionDescriptor.getElementType();
final EmbeddableMappingTypeImpl mappingType = EmbeddableMappingTypeImpl.from(component, compositeType, embeddableMappingType -> new EmbeddedCollectionPart(collectionDescriptor, CollectionPart.Nature.ELEMENT, embeddableMappingType, // parent-injection
component.getParentProperty(), tableExpression, sqlAliasStem), creationProcess);
return (CollectionPart) mappingType.getEmbeddedValueMapping();
}
if (element instanceof Any) {
final Any anyBootMapping = (Any) element;
final SessionFactoryImplementor sessionFactory = creationProcess.getCreationContext().getSessionFactory();
final TypeConfiguration typeConfiguration = sessionFactory.getTypeConfiguration();
final JavaTypeRegistry jtdRegistry = typeConfiguration.getJavaTypeRegistry();
final JavaType<Object> baseJtd = jtdRegistry.getDescriptor(Object.class);
return new DiscriminatedCollectionPart(CollectionPart.Nature.ELEMENT, collectionDescriptor, baseJtd, anyBootMapping, anyBootMapping.getType(), creationProcess);
}
if (element instanceof OneToMany || element instanceof ToOne) {
final EntityType elementEntityType = (EntityType) collectionDescriptor.getElementType();
final EntityPersister associatedEntity = creationProcess.getEntityPersister(elementEntityType.getAssociatedEntityName());
final NotFoundAction notFoundAction;
if (element instanceof ManyToOne) {
notFoundAction = ((ManyToOne) element).getNotFoundAction();
} else if (element instanceof OneToMany) {
notFoundAction = ((OneToMany) element).getNotFoundAction();
} else {
throw new IllegalArgumentException("Just seeing if this happens");
}
final EntityCollectionPart elementDescriptor = new EntityCollectionPart(collectionDescriptor, CollectionPart.Nature.ELEMENT, bootDescriptor.getElement(), notFoundAction, associatedEntity, creationProcess);
creationProcess.registerInitializationCallback("PluralAttributeMapping( " + elementDescriptor.getNavigableRole() + ") - index descriptor", () -> {
elementDescriptor.finishInitialization(collectionDescriptor, bootDescriptor, elementEntityType.getRHSUniqueKeyPropertyName(), creationProcess);
return true;
});
return elementDescriptor;
}
throw new NotYetImplementedFor6Exception("Support for plural attributes with element type [" + element + "] not yet implemented");
}
use of org.hibernate.annotations.NotFoundAction in project hibernate-orm by hibernate.
the class AnnotationBinder method bindOneToOne.
private static void bindOneToOne(PropertyHolder propertyHolder, PropertyData inferredData, boolean isIdentifierMapper, boolean inSecondPass, MetadataBuildingContext context, XProperty property, AnnotatedJoinColumn[] joinColumns, PropertyBinder propertyBinder, boolean forcePersist) {
OneToOne ann = property.getAnnotation(OneToOne.class);
// check validity
if (property.isAnnotationPresent(Column.class) || property.isAnnotationPresent(Columns.class)) {
throw new AnnotationException("@Column(s) not allowed on a @OneToOne property: " + BinderHelper.getPath(propertyHolder, inferredData));
}
// FIXME support a proper PKJCs
boolean trueOneToOne = property.isAnnotationPresent(PrimaryKeyJoinColumn.class) || property.isAnnotationPresent(PrimaryKeyJoinColumns.class);
Cascade hibernateCascade = property.getAnnotation(Cascade.class);
NotFound notFound = property.getAnnotation(NotFound.class);
NotFoundAction notFoundAction = notFound == null ? null : notFound.action();
final boolean hasNotFoundAction = notFoundAction != null;
// MapsId means the columns belong to the pk;
// A @MapsId association (obviously) must be non-null when the entity is first persisted.
// If a @MapsId association is not mapped with @NotFound(IGNORE), then the association
// is mandatory (even if the association has optional=true).
// If a @MapsId association has optional=true and is mapped with @NotFound(IGNORE) then
// the association is optional.
// @OneToOne(optional = true) with @PKJC makes the association optional.
final boolean mandatory = !ann.optional() || property.isAnnotationPresent(Id.class) || property.isAnnotationPresent(MapsId.class) && !hasNotFoundAction;
matchIgnoreNotFoundWithFetchType(propertyHolder.getEntityName(), property.getName(), notFoundAction, ann.fetch());
OnDelete onDeleteAnn = property.getAnnotation(OnDelete.class);
JoinTable assocTable = propertyHolder.getJoinTable(property);
if (assocTable != null) {
Join join = propertyHolder.addJoin(assocTable, false);
if (hasNotFoundAction) {
join.disableForeignKeyCreation();
}
for (AnnotatedJoinColumn joinColumn : joinColumns) {
joinColumn.setExplicitTableName(join.getTable().getName());
}
}
bindOneToOne(getCascadeStrategy(ann.cascade(), hibernateCascade, ann.orphanRemoval(), forcePersist), joinColumns, !mandatory, getFetchMode(ann.fetch()), notFoundAction, onDeleteAnn != null && OnDeleteAction.CASCADE == onDeleteAnn.action(), ToOneBinder.getTargetEntity(inferredData, context), propertyHolder, inferredData, ann.mappedBy(), trueOneToOne, isIdentifierMapper, inSecondPass, propertyBinder, context);
}
Aggregations