@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 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; } }