/** build join formula */ public static Ejb3JoinColumn buildJoinFormula( JoinFormula ann, String mappedBy, Map<String, Join> joins, PropertyHolder propertyHolder, String propertyName, MetadataBuildingContext buildingContext) { Ejb3JoinColumn formulaColumn = new Ejb3JoinColumn(); formulaColumn.setFormula(ann.value()); formulaColumn.setReferencedColumn(ann.referencedColumnName()); formulaColumn.setBuildingContext(buildingContext); formulaColumn.setPropertyHolder(propertyHolder); formulaColumn.setJoins(joins); formulaColumn.setPropertyName(BinderHelper.getRelativePath(propertyHolder, propertyName)); formulaColumn.bind(); return formulaColumn; }
@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<String, Ejb3JoinColumn>(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(), joinColumn); } // try default column orientation int index = 0; if (columnByReferencedName.isEmpty()) { isExplicitReference = false; for (Ejb3JoinColumn joinColumn : joinColumns) { columnByReferencedName.put("" + index, joinColumn); index++; } index = 0; } while (properties.hasNext()) { Property referencedProperty = properties.next(); if (referencedProperty.isComposite()) { throw new AssertionFailure( "Unexpected nested component on the referenced entity when mapping a @MapsId: " + referencedEntityName); } else { Property property = new Property(); property.setName(referencedProperty.getName()); property.setNodeName(referencedProperty.getNodeName()); // FIXME set optional? // property.setOptional( property.isOptional() ); property.setPersistentClass(component.getOwner()); property.setPropertyAccessorName(referencedProperty.getPropertyAccessorName()); SimpleValue value = new SimpleValue(mappings, component.getTable()); property.setValue(value); final SimpleValue referencedValue = (SimpleValue) referencedProperty.getValue(); value.setTypeName(referencedValue.getTypeName()); value.setTypeParameters(referencedValue.getTypeParameters()); final Iterator<Column> columns = referencedValue.getColumnIterator(); if (joinColumns[0].isNameDeferred()) { joinColumns[0].copyReferencedStructureAndCreateDefaultJoinColumns( referencedPersistentClass, columns, value); } else { // FIXME take care of Formula while (columns.hasNext()) { Column column = columns.next(); final Ejb3JoinColumn joinColumn; String logicalColumnName = null; if (isExplicitReference) { final String columnName = column.getName(); logicalColumnName = mappings.getLogicalColumnName(columnName, referencedPersistentClass.getTable()); // JPA 2 requires referencedColumnNames to be case insensitive joinColumn = columnByReferencedName.get(logicalColumnName.toLowerCase()); } else { joinColumn = columnByReferencedName.get("" + index); index++; } if (joinColumn == null && !joinColumns[0].isNameDeferred()) { throw new AnnotationException( isExplicitReference ? "Unable to find column reference in the @MapsId mapping: " + logicalColumnName : "Implicit column reference in the @MapsId mapping fails, try to use explicit referenceColumnNames: " + referencedEntityName); } final String columnName = joinColumn == null || joinColumn.isNameDeferred() ? "tata_" + column.getName() : joinColumn.getName(); value.addColumn(new Column(columnName)); column.setValue(value); } } component.addProperty(property); } } }
public static Ejb3JoinColumn[] buildJoinTableJoinColumns( JoinColumn[] annJoins, Map<String, Join> secondaryTables, PropertyHolder propertyHolder, String propertyName, String mappedBy, MetadataBuildingContext buildingContext) { Ejb3JoinColumn[] joinColumns; if (annJoins == null) { Ejb3JoinColumn currentJoinColumn = new Ejb3JoinColumn(); currentJoinColumn.setImplicit(true); currentJoinColumn.setNullable(false); // I break the spec, but it's for good currentJoinColumn.setPropertyHolder(propertyHolder); currentJoinColumn.setJoins(secondaryTables); currentJoinColumn.setBuildingContext(buildingContext); currentJoinColumn.setPropertyName(BinderHelper.getRelativePath(propertyHolder, propertyName)); currentJoinColumn.setMappedBy(mappedBy); currentJoinColumn.bind(); joinColumns = new Ejb3JoinColumn[] {currentJoinColumn}; } else { joinColumns = new Ejb3JoinColumn[annJoins.length]; JoinColumn annJoin; int length = annJoins.length; for (int index = 0; index < length; index++) { annJoin = annJoins[index]; Ejb3JoinColumn currentJoinColumn = new Ejb3JoinColumn(); currentJoinColumn.setImplicit(true); currentJoinColumn.setPropertyHolder(propertyHolder); currentJoinColumn.setJoins(secondaryTables); currentJoinColumn.setBuildingContext(buildingContext); currentJoinColumn.setPropertyName( BinderHelper.getRelativePath(propertyHolder, propertyName)); currentJoinColumn.setMappedBy(mappedBy); currentJoinColumn.setJoinAnnotation(annJoin, propertyName); currentJoinColumn.setNullable(false); // I break the spec, but it's for good // done afterQuery the annotation to override it currentJoinColumn.bind(); joinColumns[index] = currentJoinColumn; } } return joinColumns; }
public static int checkReferencedColumnsType( Ejb3JoinColumn[] columns, PersistentClass referencedEntity, MetadataBuildingContext context) { // convenient container to find whether a column is an id one or not Set<Column> idColumns = new HashSet<Column>(); Iterator idColumnsIt = referencedEntity.getKey().getColumnIterator(); while (idColumnsIt.hasNext()) { idColumns.add((Column) idColumnsIt.next()); } boolean isFkReferencedColumnName = false; boolean noReferencedColumn = true; // build the list of potential tables if (columns.length == 0) return NO_REFERENCE; // shortcut Object columnOwner = BinderHelper.findColumnOwner(referencedEntity, columns[0].getReferencedColumn(), context); if (columnOwner == null) { try { throw new MappingException( "Unable to find column with logical name: " + columns[0].getReferencedColumn() + " in " + referencedEntity.getTable() + " and its related " + "supertables and secondary tables"); } catch (MappingException e) { throw new RecoverableException(e.getMessage(), e); } } Table matchingTable = columnOwner instanceof PersistentClass ? ((PersistentClass) columnOwner).getTable() : ((Join) columnOwner).getTable(); // check each referenced column for (Ejb3JoinColumn ejb3Column : columns) { String logicalReferencedColumnName = ejb3Column.getReferencedColumn(); if (StringHelper.isNotEmpty(logicalReferencedColumnName)) { String referencedColumnName; try { referencedColumnName = context .getMetadataCollector() .getPhysicalColumnName(matchingTable, logicalReferencedColumnName); } catch (MappingException me) { // rewrite the exception throw new MappingException( "Unable to find column with logical name: " + logicalReferencedColumnName + " in " + matchingTable.getName()); } noReferencedColumn = false; Column refCol = new Column(referencedColumnName); boolean contains = idColumns.contains(refCol); if (!contains) { isFkReferencedColumnName = true; break; // we know the state } } } if (isFkReferencedColumnName) { return NON_PK_REFERENCE; } else if (noReferencedColumn) { return NO_REFERENCE; } else if (idColumns.size() != columns.length) { // reference use PK but is a subset or a superset return NON_PK_REFERENCE; } else { return PK_REFERENCE; } }
/** build join column for SecondaryTables */ private static Ejb3JoinColumn buildJoinColumn( JoinColumn ann, String mappedBy, Map<String, Join> joins, PropertyHolder propertyHolder, String propertyName, String suffixForDefaultColumnName, MetadataBuildingContext buildingContext) { if (ann != null) { if (BinderHelper.isEmptyAnnotationValue(mappedBy)) { throw new AnnotationException( "Illegal attempt to define a @JoinColumn with a mappedBy association: " + BinderHelper.getRelativePath(propertyHolder, propertyName)); } Ejb3JoinColumn joinColumn = new Ejb3JoinColumn(); joinColumn.setBuildingContext(buildingContext); joinColumn.setJoinAnnotation(ann, null); if (StringHelper.isEmpty(joinColumn.getLogicalColumnName()) && !StringHelper.isEmpty(suffixForDefaultColumnName)) { joinColumn.setLogicalColumnName(propertyName + suffixForDefaultColumnName); } joinColumn.setJoins(joins); joinColumn.setPropertyHolder(propertyHolder); joinColumn.setPropertyName(BinderHelper.getRelativePath(propertyHolder, propertyName)); joinColumn.setImplicit(false); joinColumn.bind(); return joinColumn; } else { Ejb3JoinColumn joinColumn = new Ejb3JoinColumn(); joinColumn.setMappedBy(mappedBy); joinColumn.setJoins(joins); joinColumn.setPropertyHolder(propertyHolder); joinColumn.setPropertyName(BinderHelper.getRelativePath(propertyHolder, propertyName)); // property name + suffix is an "explicit" column name if (!StringHelper.isEmpty(suffixForDefaultColumnName)) { joinColumn.setLogicalColumnName(propertyName + suffixForDefaultColumnName); joinColumn.setImplicit(false); } else { joinColumn.setImplicit(true); } joinColumn.setBuildingContext(buildingContext); joinColumn.bind(); return joinColumn; } }