Java tutorial
/* * Hibernate, Relational Persistence for Idiomatic Java * * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. */ package org.hibernate.mapping; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.hibernate.MappingException; import org.hibernate.dialect.Dialect; import org.hibernate.internal.util.StringHelper; /** * A foreign key constraint * * @author Gavin King */ public class ForeignKey extends Constraint { private Table referencedTable; private String referencedEntityName; private String keyDefinition; private boolean cascadeDeleteEnabled; private List<Column> referencedColumns = new ArrayList<Column>(); private boolean creationEnabled = true; public ForeignKey() { } @Override public String getExportIdentifier() { // NOt sure name is always set. Might need some implicit naming return StringHelper.qualify(getTable().getExportIdentifier(), "FK-" + getName()); } public void disableCreation() { creationEnabled = false; } public boolean isCreationEnabled() { return creationEnabled; } @Override public void setName(String name) { super.setName(name); // the FK name "none" is a magic value in the hbm.xml binding that indicated to // not create a FK. if ("none".equals(name)) { disableCreation(); } } public String sqlConstraintString(Dialect dialect, String constraintName, String defaultCatalog, String defaultSchema) { String[] columnNames = new String[getColumnSpan()]; String[] referencedColumnNames = new String[getColumnSpan()]; final Iterator<Column> referencedColumnItr; if (isReferenceToPrimaryKey()) { referencedColumnItr = referencedTable.getPrimaryKey().getColumnIterator(); } else { referencedColumnItr = referencedColumns.iterator(); } Iterator columnItr = getColumnIterator(); int i = 0; while (columnItr.hasNext()) { columnNames[i] = ((Column) columnItr.next()).getQuotedName(dialect); referencedColumnNames[i] = referencedColumnItr.next().getQuotedName(dialect); i++; } final String result = keyDefinition != null ? dialect.getAddForeignKeyConstraintString(constraintName, keyDefinition) : dialect.getAddForeignKeyConstraintString(constraintName, columnNames, referencedTable.getQualifiedName(dialect, defaultCatalog, defaultSchema), referencedColumnNames, isReferenceToPrimaryKey()); return cascadeDeleteEnabled && dialect.supportsCascadeDelete() ? result + " on delete cascade" : result; } public Table getReferencedTable() { return referencedTable; } private void appendColumns(StringBuilder buf, Iterator columns) { while (columns.hasNext()) { Column column = (Column) columns.next(); buf.append(column.getName()); if (columns.hasNext()) { buf.append(","); } } } public void setReferencedTable(Table referencedTable) throws MappingException { //if( isReferenceToPrimaryKey() ) alignColumns(referencedTable); // TODO: possibly remove to allow more piecemal building of a foreignkey. this.referencedTable = referencedTable; } /** * Validates that columnspan of the foreignkey and the primarykey is the same. * <p/> * Furthermore it aligns the length of the underlying tables columns. */ public void alignColumns() { if (isReferenceToPrimaryKey()) { alignColumns(referencedTable); } } private void alignColumns(Table referencedTable) { final int referencedPkColumnSpan = referencedTable.getPrimaryKey().getColumnSpan(); if (referencedPkColumnSpan != getColumnSpan()) { StringBuilder sb = new StringBuilder(); sb.append("Foreign key (").append(getName()).append(":").append(getTable().getName()).append(" ["); appendColumns(sb, getColumnIterator()); sb.append("])").append(") must have same number of columns as the referenced primary key (") .append(referencedTable.getName()).append(" ["); appendColumns(sb, referencedTable.getPrimaryKey().getColumnIterator()); sb.append("])"); throw new MappingException(sb.toString()); } Iterator fkCols = getColumnIterator(); Iterator pkCols = referencedTable.getPrimaryKey().getColumnIterator(); while (pkCols.hasNext()) { ((Column) fkCols.next()).setLength(((Column) pkCols.next()).getLength()); } } public String getReferencedEntityName() { return referencedEntityName; } public void setReferencedEntityName(String referencedEntityName) { this.referencedEntityName = referencedEntityName; } public String getKeyDefinition() { return keyDefinition; } public void setKeyDefinition(String keyDefinition) { this.keyDefinition = keyDefinition; } public String sqlDropString(Dialect dialect, String defaultCatalog, String defaultSchema) { String tableName = getTable().getQualifiedName(dialect, defaultCatalog, defaultSchema); final StringBuilder buf = new StringBuilder(dialect.getAlterTableString(tableName)); buf.append(dialect.getDropForeignKeyString()); if (dialect.supportsIfExistsBeforeConstraintName()) { buf.append("if exists "); } buf.append(dialect.quote(getName())); if (dialect.supportsIfExistsAfterConstraintName()) { buf.append(" if exists"); } return buf.toString(); } public boolean isCascadeDeleteEnabled() { return cascadeDeleteEnabled; } public void setCascadeDeleteEnabled(boolean cascadeDeleteEnabled) { this.cascadeDeleteEnabled = cascadeDeleteEnabled; } public boolean isPhysicalConstraint() { return referencedTable.isPhysicalTable() && getTable().isPhysicalTable() && !referencedTable.hasDenormalizedTables(); } /** * Returns the referenced columns if the foreignkey does not refer to the primary key */ public List getReferencedColumns() { return referencedColumns; } /** * Does this foreignkey reference the primary key of the reference table */ public boolean isReferenceToPrimaryKey() { return referencedColumns.isEmpty(); } public void addReferencedColumns(Iterator referencedColumnsIterator) { while (referencedColumnsIterator.hasNext()) { Selectable col = (Selectable) referencedColumnsIterator.next(); if (!col.isFormula()) { addReferencedColumn((Column) col); } } } private void addReferencedColumn(Column column) { if (!referencedColumns.contains(column)) { referencedColumns.add(column); } } public String toString() { if (!isReferenceToPrimaryKey()) { return getClass().getName() + '(' + getTable().getName() + getColumns() + " ref-columns:" + '(' + getReferencedColumns() + ") as " + getName() + ")"; } else { return super.toString(); } } public String generatedConstraintNamePrefix() { return "FK_"; } }