use of jakarta.persistence.JoinColumns in project hibernate-orm by hibernate.
the class Ejb3XmlOneToManyTest method testMultipleJoinColumns.
@Test
public void testMultipleJoinColumns() throws Exception {
reader = getReader(Entity2.class, "field1", "one-to-many.orm19.xml");
assertAnnotationPresent(OneToMany.class);
assertAnnotationNotPresent(JoinColumn.class);
assertAnnotationPresent(JoinColumns.class);
assertAnnotationNotPresent(JoinTable.class);
JoinColumns joinColumnsAnno = reader.getAnnotation(JoinColumns.class);
JoinColumn[] joinColumns = joinColumnsAnno.value();
assertEquals(2, joinColumns.length);
assertEquals("", joinColumns[0].name());
assertEquals("", joinColumns[0].referencedColumnName());
assertEquals("", joinColumns[0].table());
assertEquals("", joinColumns[0].columnDefinition());
assertTrue(joinColumns[0].insertable());
assertTrue(joinColumns[0].updatable());
assertTrue(joinColumns[0].nullable());
assertFalse(joinColumns[0].unique());
assertEquals("col1", joinColumns[1].name());
assertEquals("col2", joinColumns[1].referencedColumnName());
assertEquals("table1", joinColumns[1].table());
assertEquals("int", joinColumns[1].columnDefinition());
assertFalse(joinColumns[1].insertable());
assertFalse(joinColumns[1].updatable());
assertFalse(joinColumns[1].nullable());
assertTrue(joinColumns[1].unique());
}
use of jakarta.persistence.JoinColumns in project hibernate-orm by hibernate.
the class Ejb3XmlOneToOneTest method testMultipleJoinColumns.
@Test
public void testMultipleJoinColumns() throws Exception {
reader = getReader(Entity1.class, "field1", "one-to-one.orm5.xml");
assertAnnotationPresent(OneToOne.class);
assertAnnotationNotPresent(PrimaryKeyJoinColumn.class);
assertAnnotationNotPresent(PrimaryKeyJoinColumns.class);
assertAnnotationNotPresent(JoinColumn.class);
assertAnnotationPresent(JoinColumns.class);
assertAnnotationNotPresent(JoinTable.class);
JoinColumns joinColumnsAnno = reader.getAnnotation(JoinColumns.class);
JoinColumn[] joinColumns = joinColumnsAnno.value();
assertEquals(2, joinColumns.length);
assertEquals("", joinColumns[0].name());
assertEquals("", joinColumns[0].referencedColumnName());
assertEquals("", joinColumns[0].table());
assertEquals("", joinColumns[0].columnDefinition());
assertTrue(joinColumns[0].insertable());
assertTrue(joinColumns[0].updatable());
assertTrue(joinColumns[0].nullable());
assertFalse(joinColumns[0].unique());
assertEquals("col1", joinColumns[1].name());
assertEquals("col2", joinColumns[1].referencedColumnName());
assertEquals("table1", joinColumns[1].table());
assertEquals("int", joinColumns[1].columnDefinition());
assertFalse(joinColumns[1].insertable());
assertFalse(joinColumns[1].updatable());
assertFalse(joinColumns[1].nullable());
assertTrue(joinColumns[1].unique());
}
use of jakarta.persistence.JoinColumns in project hibernate-orm by hibernate.
the class AnnotationBinder method addProperty.
private static int addProperty(PropertyContainer propertyContainer, XProperty property, List<PropertyData> inFlightPropertyDataList, MetadataBuildingContext context) {
// and if so, skip it..
for (PropertyData propertyData : inFlightPropertyDataList) {
if (propertyData.getPropertyName().equals(property.getName())) {
Id incomingIdProperty = property.getAnnotation(Id.class);
Id existingIdProperty = propertyData.getProperty().getAnnotation(Id.class);
if (incomingIdProperty != null && existingIdProperty == null) {
throw new MappingException(String.format("You cannot override the [%s] non-identifier property from the [%s] base class or @MappedSuperclass and make it an identifier in the [%s] subclass!", propertyData.getProperty().getName(), propertyData.getProperty().getDeclaringClass().getName(), property.getDeclaringClass().getName()));
}
// EARLY EXIT!!!
return 0;
}
}
final XClass declaringClass = propertyContainer.getDeclaringClass();
final XClass entity = propertyContainer.getEntityAtStake();
int idPropertyCounter = 0;
PropertyData propertyAnnotatedElement = new PropertyInferredData(declaringClass, property, propertyContainer.getClassLevelAccessType().getType(), context.getBootstrapContext().getReflectionManager());
/*
* put element annotated by @Id in front
* since it has to be parsed before any association by Hibernate
*/
final XAnnotatedElement element = propertyAnnotatedElement.getProperty();
if (hasIdAnnotation(element)) {
inFlightPropertyDataList.add(0, propertyAnnotatedElement);
/*
* The property must be put in hibernate.properties as it's a system wide property. Fixable?
* TODO support true/false/default on the property instead of present / not present
* TODO is @Column mandatory?
* TODO add method support
*/
if (context.getBuildingOptions().isSpecjProprietarySyntaxEnabled()) {
if (element.isAnnotationPresent(Id.class) && element.isAnnotationPresent(Column.class)) {
String columnName = element.getAnnotation(Column.class).name();
for (XProperty prop : declaringClass.getDeclaredProperties(AccessType.FIELD.getType())) {
if (!prop.isAnnotationPresent(MapsId.class)) {
/*
* The detection of a configured individual JoinColumn differs between Annotation
* and XML configuration processing.
*/
boolean isRequiredAnnotationPresent = false;
JoinColumns groupAnnotation = prop.getAnnotation(JoinColumns.class);
if ((prop.isAnnotationPresent(JoinColumn.class) && prop.getAnnotation(JoinColumn.class).name().equals(columnName))) {
isRequiredAnnotationPresent = true;
} else if (prop.isAnnotationPresent(JoinColumns.class)) {
for (JoinColumn columnAnnotation : groupAnnotation.value()) {
if (columnName.equals(columnAnnotation.name())) {
isRequiredAnnotationPresent = true;
break;
}
}
}
if (isRequiredAnnotationPresent) {
// create a PropertyData for the specJ property holding the mapping
PropertyData specJPropertyData = new PropertyInferredData(declaringClass, // same dec
prop, // the actual @XToOne property
propertyContainer.getClassLevelAccessType().getType(), // TODO we should get the right accessor but the same as id would do
context.getBootstrapContext().getReflectionManager());
context.getMetadataCollector().addPropertyAnnotatedWithMapsIdSpecj(entity, specJPropertyData, element.toString());
}
}
}
}
}
if (hasToOneAnnotation(element)) {
context.getMetadataCollector().addToOneAndIdProperty(entity, propertyAnnotatedElement);
}
idPropertyCounter++;
} else {
inFlightPropertyDataList.add(propertyAnnotatedElement);
}
if (element.isAnnotationPresent(MapsId.class)) {
context.getMetadataCollector().addPropertyAnnotatedWithMapsId(entity, propertyAnnotatedElement);
}
return idPropertyCounter;
}
use of jakarta.persistence.JoinColumns 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);
boolean ignoreNotFound = notFound != null && notFound.action() == NotFoundAction.IGNORE;
// 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) && !ignoreNotFound;
matchIgnoreNotFoundWithFetchType(propertyHolder.getEntityName(), property.getName(), ignoreNotFound, 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());
}
}
bindOneToOne(getCascadeStrategy(ann.cascade(), hibernateCascade, ann.orphanRemoval(), forcePersist), joinColumns, !mandatory, getFetchMode(ann.fetch()), ignoreNotFound, onDeleteAnn != null && OnDeleteAction.CASCADE == onDeleteAnn.action(), ToOneBinder.getTargetEntity(inferredData, context), propertyHolder, inferredData, ann.mappedBy(), trueOneToOne, isIdentifierMapper, inSecondPass, propertyBinder, context);
}
use of jakarta.persistence.JoinColumns in project hibernate-orm by hibernate.
the class AnnotationBinder method bindManyToOne.
private static void bindManyToOne(String cascadeStrategy, AnnotatedJoinColumn[] columns, boolean optional, boolean ignoreNotFound, boolean cascadeOnDelete, XClass targetEntity, PropertyHolder propertyHolder, PropertyData inferredData, boolean unique, boolean isIdentifierMapper, boolean inSecondPass, PropertyBinder propertyBinder, MetadataBuildingContext context) {
// All FK columns should be in the same table
org.hibernate.mapping.ManyToOne value = new org.hibernate.mapping.ManyToOne(context, columns[0].getTable());
// This is a @OneToOne mapped to a physical o.h.mapping.ManyToOne
if (unique) {
value.markAsLogicalOneToOne();
}
value.setReferencedEntityName(ToOneBinder.getReferenceEntityName(inferredData, targetEntity, context));
final XProperty property = inferredData.getProperty();
defineFetchingStrategy(value, property);
// value.setFetchMode( fetchMode );
value.setIgnoreNotFound(ignoreNotFound);
value.setCascadeDeleteEnabled(cascadeOnDelete);
// value.setLazy( fetchMode != FetchMode.JOIN );
if (!optional) {
for (AnnotatedJoinColumn column : columns) {
column.setNullable(false);
}
}
if (property.isAnnotationPresent(MapsId.class)) {
// read only
for (AnnotatedJoinColumn column : columns) {
column.setInsertable(false);
column.setUpdatable(false);
}
}
final JoinColumn joinColumn = property.getAnnotation(JoinColumn.class);
final JoinColumns joinColumns = property.getAnnotation(JoinColumns.class);
// Make sure that JPA1 key-many-to-one columns are read only too
boolean hasSpecjManyToOne = false;
if (context.getBuildingOptions().isSpecjProprietarySyntaxEnabled()) {
String columnName = "";
for (XProperty prop : inferredData.getDeclaringClass().getDeclaredProperties(AccessType.FIELD.getType())) {
if (prop.isAnnotationPresent(Id.class) && prop.isAnnotationPresent(Column.class)) {
columnName = prop.getAnnotation(Column.class).name();
}
if (property.isAnnotationPresent(ManyToOne.class) && joinColumn != null && !BinderHelper.isEmptyAnnotationValue(joinColumn.name()) && joinColumn.name().equals(columnName) && !property.isAnnotationPresent(MapsId.class)) {
hasSpecjManyToOne = true;
for (AnnotatedJoinColumn column : columns) {
column.setInsertable(false);
column.setUpdatable(false);
}
}
}
}
value.setTypeName(inferredData.getClassOrElementName());
final String propertyName = inferredData.getPropertyName();
value.setTypeUsingReflection(propertyHolder.getClassName(), propertyName);
bindForeignKeyNameAndDefinition(value, property, propertyHolder.getOverriddenForeignKey(StringHelper.qualify(propertyHolder.getPath(), propertyName)), joinColumn, joinColumns, context);
String path = propertyHolder.getPath() + "." + propertyName;
FkSecondPass secondPass = new ToOneFkSecondPass(value, columns, // cannot have nullable and unique on certain DBs like Derby
!optional && unique, propertyHolder.getEntityOwnerClassName(), path, context);
if (inSecondPass) {
secondPass.doSecondPass(context.getMetadataCollector().getEntityBindingMap());
} else {
context.getMetadataCollector().addSecondPass(secondPass);
}
AnnotatedColumn.checkPropertyConsistency(columns, propertyHolder.getEntityName() + "." + propertyName);
// PropertyBinder binder = new PropertyBinder();
propertyBinder.setName(propertyName);
propertyBinder.setValue(value);
// binder.setCascade(cascadeStrategy);
if (isIdentifierMapper) {
propertyBinder.setInsertable(false);
propertyBinder.setUpdatable(false);
} else if (hasSpecjManyToOne) {
propertyBinder.setInsertable(false);
propertyBinder.setUpdatable(false);
} else {
propertyBinder.setInsertable(columns[0].isInsertable());
propertyBinder.setUpdatable(columns[0].isUpdatable());
}
propertyBinder.setColumns(columns);
propertyBinder.setAccessType(inferredData.getDefaultAccess());
propertyBinder.setCascade(cascadeStrategy);
propertyBinder.setProperty(property);
propertyBinder.setXToMany(true);
final Property boundProperty = propertyBinder.makePropertyAndBind();
if (joinColumn != null) {
boundProperty.setOptional(joinColumn.nullable() && optional);
} else {
boundProperty.setOptional(optional);
}
}
Aggregations