HHH-7797 UniqueDelegate & DefaultUniqueDelegate

This commit is contained in:
brmeyer 2012-12-11 10:36:21 -05:00
parent 3a995f574d
commit 953aec40ad
4 changed files with 147 additions and 75 deletions

View File

@ -58,6 +58,8 @@ import org.hibernate.dialect.lock.PessimisticWriteSelectLockingStrategy;
import org.hibernate.dialect.lock.SelectLockingStrategy; import org.hibernate.dialect.lock.SelectLockingStrategy;
import org.hibernate.dialect.pagination.LegacyLimitHandler; import org.hibernate.dialect.pagination.LegacyLimitHandler;
import org.hibernate.dialect.pagination.LimitHandler; 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.jdbc.LobCreator;
import org.hibernate.engine.spi.RowSelection; import org.hibernate.engine.spi.RowSelection;
import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.engine.spi.SessionImplementor;
@ -115,6 +117,8 @@ public abstract class Dialect implements ConversionContext {
private final Properties properties = new Properties(); private final Properties properties = new Properties();
private final Map<String, SQLFunction> sqlFunctions = new HashMap<String, SQLFunction>(); private final Map<String, SQLFunction> sqlFunctions = new HashMap<String, SQLFunction>();
private final Set<String> sqlKeywords = new HashSet<String>(); private final Set<String> sqlKeywords = new HashSet<String>();
private final UniqueDelegate uniqueDelegate;
// constructors and factory methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // constructors and factory methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -203,6 +207,8 @@ public abstract class Dialect implements ConversionContext {
registerHibernateType( Types.BLOB, StandardBasicTypes.BLOB.getName() ); registerHibernateType( Types.BLOB, StandardBasicTypes.BLOB.getName() );
registerHibernateType( Types.CLOB, StandardBasicTypes.CLOB.getName() ); registerHibernateType( Types.CLOB, StandardBasicTypes.CLOB.getName() );
registerHibernateType( Types.REAL, StandardBasicTypes.FLOAT.getName() ); registerHibernateType( Types.REAL, StandardBasicTypes.FLOAT.getName() );
uniqueDelegate = new DefaultUniqueDelegate( this );
} }
/** /**
@ -1907,23 +1913,6 @@ public abstract class Dialect implements ConversionContext {
return true; return true;
} }
/**
* Does this dialect support the <tt>UNIQUE</tt> 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). * 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 "; 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() { public boolean hasSelfReferentialForeignKeyBug() {
return false; return false;
} }
@ -2056,15 +2035,6 @@ public abstract class Dialect implements ConversionContext {
return true; 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 * Completely optional cascading drop clause
* *
@ -2416,4 +2386,8 @@ public abstract class Dialect implements ConversionContext {
public boolean useFollowOnLocking() { public boolean useFollowOnLocking() {
return false; return false;
} }
public UniqueDelegate getUniqueDelegate() {
return uniqueDelegate;
}
} }

View File

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

View File

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

View File

@ -422,15 +422,7 @@ public class Table implements RelationalModel, Serializable {
alter.append( " not null" ); alter.append( " not null" );
} }
// If the column is 1.) unique, 2.) the dialect supports the dialect.getUniqueDelegate().applyUnique( this, column, alter );
// 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" );
}
if ( column.hasCheckConstraint() && dialect.supportsColumnCheck() ) { if ( column.hasCheckConstraint() && dialect.supportsColumnCheck() ) {
alter.append( " check(" ) alter.append( " check(" )
@ -527,21 +519,7 @@ public class Table implements RelationalModel, Serializable {
} }
// If the column is 1.) unique and nullable or 2.) unique, dialect.getUniqueDelegate().applyUnique( this, col, buf );
// 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" );
}
}
if ( col.hasCheckConstraint() && dialect.supportsColumnCheck() ) { if ( col.hasCheckConstraint() && dialect.supportsColumnCheck() ) {
buf.append( " check (" ) buf.append( " check (" )
@ -564,21 +542,7 @@ public class Table implements RelationalModel, Serializable {
.append( getPrimaryKey().sqlConstraintString( dialect ) ); .append( getPrimaryKey().sqlConstraintString( dialect ) );
} }
if ( dialect.supportsUniqueConstraintInCreateAlterTable() ) { dialect.getUniqueDelegate().createUniqueConstraint( this, buf );
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) );
}*/
if ( dialect.supportsTableCheck() ) { if ( dialect.supportsTableCheck() ) {
Iterator chiter = checkConstraints.iterator(); Iterator chiter = checkConstraints.iterator();