From 953aec40adaf5e172eb6c936df71395868732b5d Mon Sep 17 00:00:00 2001 From: brmeyer Date: Tue, 11 Dec 2012 10:36:21 -0500 Subject: [PATCH] HHH-7797 UniqueDelegate & DefaultUniqueDelegate --- .../java/org/hibernate/dialect/Dialect.java | 46 +++------- .../dialect/unique/DefaultUniqueDelegate.java | 89 +++++++++++++++++++ .../dialect/unique/UniqueDelegate.java | 45 ++++++++++ .../java/org/hibernate/mapping/Table.java | 42 +-------- 4 files changed, 147 insertions(+), 75 deletions(-) create mode 100644 hibernate-core/src/main/java/org/hibernate/dialect/unique/DefaultUniqueDelegate.java create mode 100644 hibernate-core/src/main/java/org/hibernate/dialect/unique/UniqueDelegate.java diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java index dab857b72c..bc869b59bd 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java @@ -58,6 +58,8 @@ import org.hibernate.dialect.lock.PessimisticWriteSelectLockingStrategy; import org.hibernate.dialect.lock.SelectLockingStrategy; import org.hibernate.dialect.pagination.LegacyLimitHandler; import org.hibernate.dialect.pagination.LimitHandler; +import org.hibernate.dialect.unique.DefaultUniqueDelegate; +import org.hibernate.dialect.unique.UniqueDelegate; import org.hibernate.engine.jdbc.LobCreator; import org.hibernate.engine.spi.RowSelection; import org.hibernate.engine.spi.SessionImplementor; @@ -115,6 +117,8 @@ public abstract class Dialect implements ConversionContext { private final Properties properties = new Properties(); private final Map sqlFunctions = new HashMap(); private final Set sqlKeywords = new HashSet(); + + private final UniqueDelegate uniqueDelegate; // constructors and factory methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -203,6 +207,8 @@ public abstract class Dialect implements ConversionContext { registerHibernateType( Types.BLOB, StandardBasicTypes.BLOB.getName() ); registerHibernateType( Types.CLOB, StandardBasicTypes.CLOB.getName() ); registerHibernateType( Types.REAL, StandardBasicTypes.FLOAT.getName() ); + + uniqueDelegate = new DefaultUniqueDelegate( this ); } /** @@ -1907,23 +1913,6 @@ public abstract class Dialect implements ConversionContext { return true; } - /** - * Does this dialect support the UNIQUE column syntax? - * - * @return boolean - */ - public boolean supportsUnique() { - return true; - } - - /** - * Does this dialect support adding Unique constraints via create and alter table ? - * @return boolean - */ - public boolean supportsUniqueConstraintInCreateAlterTable() { - return true; - } - /** * The syntax used to add a column to a table (optional). * @@ -1989,16 +1978,6 @@ public abstract class Dialect implements ConversionContext { return " add constraint " + constraintName + " primary key "; } - /** - * The syntax used to add a unique constraint to a table. - * - * @param constraintName The name of the unique constraint. - * @return The "add unique" fragment - */ - public String getAddUniqueConstraintString(String constraintName) { - return " add constraint " + constraintName + " unique "; - } - public boolean hasSelfReferentialForeignKeyBug() { return false; } @@ -2056,15 +2035,6 @@ public abstract class Dialect implements ConversionContext { return true; } - /** - * Does this dialect support columns that are both unique and not null. - * - * @return True if supported, false otherwise. - */ - public boolean supportsNotNullUnique() { - return true; - } - /** * Completely optional cascading drop clause * @@ -2416,4 +2386,8 @@ public abstract class Dialect implements ConversionContext { public boolean useFollowOnLocking() { return false; } + + public UniqueDelegate getUniqueDelegate() { + return uniqueDelegate; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/unique/DefaultUniqueDelegate.java b/hibernate-core/src/main/java/org/hibernate/dialect/unique/DefaultUniqueDelegate.java new file mode 100644 index 0000000000..dfcc88ae65 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/unique/DefaultUniqueDelegate.java @@ -0,0 +1,89 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2012 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package org.hibernate.dialect.unique; + +import java.util.Iterator; +import java.util.List; + +import org.hibernate.dialect.Dialect; +import org.hibernate.mapping.Column; +import org.hibernate.mapping.Table; +import org.hibernate.mapping.UniqueKey; + +/** + * The default UniqueDelegate implementation for most dialects. Uses + * separate create/alter statements to apply uniqueness to a column. + * + * @author Brett Meyer + */ +public class DefaultUniqueDelegate implements UniqueDelegate { + + private final Dialect dialect; + + public DefaultUniqueDelegate( Dialect dialect ) { + this.dialect = dialect; + } + + @Override + public void applyUnique( Table table, Column column, StringBuilder sb ) { +// if ( column.isUnique() +// && ( column.isNullable() +// || dialect.supportsNotNullUnique() ) ) { +// if ( dialect.supportsUniqueConstraintInCreateAlterTable() ) { +// // If the constraint is supported, do not add to the column syntax. +// UniqueKey uk = getOrCreateUniqueKey( column.getQuotedName( dialect ) + '_' ); +// uk.addColumn( column ); +// } +// else if ( dialect.supportsUnique() ) { +// // Otherwise, add to the column syntax if supported. +// sb.append( " unique" ); +// } +// } + + UniqueKey uk = table.getOrCreateUniqueKey( + column.getQuotedName( dialect ) + '_' ); + uk.addColumn( column ); + } + + @Override + public void createUniqueConstraint( Table table, StringBuilder sb ) { +// if ( dialect.supportsUniqueConstraintInCreateAlterTable() ) { +// Iterator ukiter = getUniqueKeyIterator(); +// while ( ukiter.hasNext() ) { +// UniqueKey uk = (UniqueKey) ukiter.next(); +// String constraint = uk.sqlConstraintString( dialect ); +// if ( constraint != null ) { +// buf.append( ", " ).append( constraint ); +// } +// } +// } + + Iterator ukiter = table.getUniqueKeyIterator(); + while ( ukiter.hasNext() ) { + UniqueKey uk = (UniqueKey) ukiter.next(); + String constraint = uk.sqlConstraintString( dialect ); + if ( constraint != null ) { + sb.append( ", " ).append( constraint ); + } + } + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/unique/UniqueDelegate.java b/hibernate-core/src/main/java/org/hibernate/dialect/unique/UniqueDelegate.java new file mode 100644 index 0000000000..a173c22c8c --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/unique/UniqueDelegate.java @@ -0,0 +1,45 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2012 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package org.hibernate.dialect.unique; + +import org.hibernate.mapping.Column; +import org.hibernate.mapping.Table; + +/** + * Dialect-level delegate in charge of applying "uniqueness" to a column. + * Uniqueness can be defined in 1 of 3 ways: + * + * 1.) Add a unique constraint via separate create/alter table statements. + * 2.) Add a unique constraint via dialect-specific syntax in table create statement. + * 3.) Add "unique" syntax to the column itself. + * + * #1 & #2 are preferred, if possible -- #3 should be solely a fall-back. + * + * See HHH-7797. + * + * @author Brett Meyer + */ +public interface UniqueDelegate { + + public void applyUnique( Table table, Column column, StringBuilder sb ); + + public void createUniqueConstraint( Table table, StringBuilder sb ); +} diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/Table.java b/hibernate-core/src/main/java/org/hibernate/mapping/Table.java index cbcbe436ef..87c2148821 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/Table.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/Table.java @@ -422,15 +422,7 @@ public class Table implements RelationalModel, Serializable { alter.append( " not null" ); } - // If the column is 1.) unique, 2.) the dialect supports the - // unique syntax, 3.) the column is nullable or supports - // "not null unique", and 4.) a constraint will not be created - if ( column.isUnique() && dialect.supportsUnique() - && ( column.isNullable() - || dialect.supportsNotNullUnique() ) - && !dialect.supportsUniqueConstraintInCreateAlterTable() ) { - alter.append( " unique" ); - } + dialect.getUniqueDelegate().applyUnique( this, column, alter ); if ( column.hasCheckConstraint() && dialect.supportsColumnCheck() ) { alter.append( " check(" ) @@ -527,21 +519,7 @@ public class Table implements RelationalModel, Serializable { } - // If the column is 1.) unique and nullable or 2.) unique, - // not null, and the dialect supports unique not null - if ( col.isUnique() - && ( col.isNullable() - || dialect.supportsNotNullUnique() ) ) { - if ( dialect.supportsUniqueConstraintInCreateAlterTable() ) { - // If the constraint is supported, do not add to the column syntax. - UniqueKey uk = getOrCreateUniqueKey( col.getQuotedName( dialect ) + '_' ); - uk.addColumn( col ); - } - else if ( dialect.supportsUnique() ) { - // Otherwise, add to the column syntax if supported. - buf.append( " unique" ); - } - } + dialect.getUniqueDelegate().applyUnique( this, col, buf ); if ( col.hasCheckConstraint() && dialect.supportsColumnCheck() ) { buf.append( " check (" ) @@ -564,21 +542,7 @@ public class Table implements RelationalModel, Serializable { .append( getPrimaryKey().sqlConstraintString( dialect ) ); } - if ( dialect.supportsUniqueConstraintInCreateAlterTable() ) { - Iterator ukiter = getUniqueKeyIterator(); - while ( ukiter.hasNext() ) { - UniqueKey uk = (UniqueKey) ukiter.next(); - String constraint = uk.sqlConstraintString( dialect ); - if ( constraint != null ) { - buf.append( ", " ).append( constraint ); - } - } - } - /*Iterator idxiter = getIndexIterator(); - while ( idxiter.hasNext() ) { - Index idx = (Index) idxiter.next(); - buf.append(',').append( idx.sqlConstraintString(dialect) ); - }*/ + dialect.getUniqueDelegate().createUniqueConstraint( this, buf ); if ( dialect.supportsTableCheck() ) { Iterator chiter = checkConstraints.iterator();