HHH-4553 - Hibernate doesn't support official JPA2 escape char for table name
git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@18148 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
parent
ecb103cf55
commit
a2bf14ae7c
|
@ -395,6 +395,7 @@ public final class AnnotationBinder {
|
|||
idGen.addParam( org.hibernate.id.SequenceGenerator.SEQUENCE, seqGen.sequenceName() );
|
||||
}
|
||||
//FIXME: work on initialValue() through SequenceGenerator.PARAMETERS
|
||||
// steve : or just use o.h.id.enhanced.SequenceStyleGenerator
|
||||
if ( seqGen.initialValue() != 1 ) {
|
||||
log.warn(
|
||||
"Hibernate does not support SequenceGenerator.initialValue()"
|
||||
|
@ -485,7 +486,7 @@ public final class AnnotationBinder {
|
|||
String table = ""; //might be no @Table annotation on the annotated class
|
||||
String catalog = "";
|
||||
String discrimValue = null;
|
||||
List<String[]> uniqueConstraints = new ArrayList<String[]>();
|
||||
List<UniqueConstraintHolder> uniqueConstraints = new ArrayList<UniqueConstraintHolder>();
|
||||
Ejb3DiscriminatorColumn discriminatorColumn = null;
|
||||
Ejb3JoinColumn[] inheritanceJoinedColumns = null;
|
||||
|
||||
|
@ -494,7 +495,7 @@ public final class AnnotationBinder {
|
|||
table = tabAnn.name();
|
||||
schema = tabAnn.schema();
|
||||
catalog = tabAnn.catalog();
|
||||
uniqueConstraints = TableBinder.buildUniqueConstraints( tabAnn.uniqueConstraints() );
|
||||
uniqueConstraints = TableBinder.buildUniqueConstraintHolders( tabAnn.uniqueConstraints() );
|
||||
}
|
||||
final boolean hasJoinedColumns = inheritanceState.hasParents
|
||||
&& InheritanceType.JOINED.equals( inheritanceState.type );
|
||||
|
|
|
@ -85,6 +85,7 @@ import org.hibernate.mapping.UniqueKey;
|
|||
import org.hibernate.util.JoinedIterator;
|
||||
import org.hibernate.util.ReflectHelper;
|
||||
import org.hibernate.util.StringHelper;
|
||||
import org.hibernate.util.CollectionHelper;
|
||||
|
||||
/**
|
||||
* Similar to the {@link Configuration} object but handles EJB3 and Hibernate
|
||||
|
@ -121,7 +122,8 @@ public class AnnotationConfiguration extends Configuration {
|
|||
private Set<String> defaultSqlResulSetMappingNames;
|
||||
private Set<String> defaultNamedGenerators;
|
||||
private Map<String, Properties> generatorTables;
|
||||
private Map<Table, List<String[]>> tableUniqueConstraints;
|
||||
private Map<Table, List<UniqueConstraintHolder>> uniqueConstraintHoldersByTable;
|
||||
// private Map<Table, List<String[]>> tableUniqueConstraints;
|
||||
private Map<String, String> mappedByResolver;
|
||||
private Map<String, String> propertyRefResolver;
|
||||
private Map<String, AnyMetaDef> anyMetaDefs;
|
||||
|
@ -249,7 +251,7 @@ public class AnnotationConfiguration extends Configuration {
|
|||
defaultNamedNativeQueryNames = new HashSet<String>();
|
||||
defaultSqlResulSetMappingNames = new HashSet<String>();
|
||||
defaultNamedGenerators = new HashSet<String>();
|
||||
tableUniqueConstraints = new HashMap<Table, List<String[]>>();
|
||||
uniqueConstraintHoldersByTable = new HashMap<Table, List<UniqueConstraintHolder>>();
|
||||
mappedByResolver = new HashMap<String, String>();
|
||||
propertyRefResolver = new HashMap<String, String>();
|
||||
annotatedClasses = new ArrayList<XClass>();
|
||||
|
@ -358,19 +360,19 @@ public class AnnotationConfiguration extends Configuration {
|
|||
//the exception was not recoverable after all
|
||||
throw ( RuntimeException ) e.getCause();
|
||||
}
|
||||
Iterator tables = tableUniqueConstraints.entrySet().iterator();
|
||||
Table table;
|
||||
Map.Entry entry;
|
||||
String keyName;
|
||||
int uniqueIndexPerTable;
|
||||
|
||||
Iterator<Map.Entry<Table,List<UniqueConstraintHolder>>> tables = uniqueConstraintHoldersByTable.entrySet().iterator();
|
||||
while ( tables.hasNext() ) {
|
||||
entry = ( Map.Entry ) tables.next();
|
||||
table = ( Table ) entry.getKey();
|
||||
List<String[]> uniqueConstraints = ( List<String[]> ) entry.getValue();
|
||||
uniqueIndexPerTable = 0;
|
||||
for ( String[] columnNames : uniqueConstraints ) {
|
||||
keyName = "key" + uniqueIndexPerTable++;
|
||||
buildUniqueKeyFromColumnNames( columnNames, table, keyName );
|
||||
final Map.Entry<Table,List<UniqueConstraintHolder>> entry = tables.next();
|
||||
final Table table = entry.getKey();
|
||||
final List<UniqueConstraintHolder> uniqueConstraints = entry.getValue();
|
||||
int uniqueIndexPerTable = 0;
|
||||
for ( UniqueConstraintHolder holder : uniqueConstraints ) {
|
||||
uniqueIndexPerTable++;
|
||||
final String keyName = StringHelper.isEmpty( holder.getName() )
|
||||
? "key" + uniqueIndexPerTable
|
||||
: holder.getName();
|
||||
buildUniqueKeyFromColumnNames( table, keyName, holder.getColumns() );
|
||||
}
|
||||
}
|
||||
applyConstraintsToDDL();
|
||||
|
@ -621,23 +623,26 @@ public class AnnotationConfiguration extends Configuration {
|
|||
}
|
||||
}
|
||||
|
||||
private void buildUniqueKeyFromColumnNames(String[] columnNames, Table table, String keyName) {
|
||||
private void buildUniqueKeyFromColumnNames(Table table, String keyName, String[] columnNames) {
|
||||
ExtendedMappings mappings = createExtendedMappings();
|
||||
keyName = mappings.getObjectNameNormalizer().normalizeIdentifierQuoting( keyName );
|
||||
|
||||
UniqueKey uc;
|
||||
int size = columnNames.length;
|
||||
Column[] columns = new Column[size];
|
||||
Set<Column> unbound = new HashSet<Column>();
|
||||
Set<Column> unboundNoLogical = new HashSet<Column>();
|
||||
ExtendedMappings mappings = createExtendedMappings();
|
||||
for ( int index = 0; index < size; index++ ) {
|
||||
String columnName;
|
||||
final String logicalColumnName = mappings.getObjectNameNormalizer()
|
||||
.normalizeIdentifierQuoting( columnNames[index] );
|
||||
try {
|
||||
columnName = mappings.getPhysicalColumnName( columnNames[index], table );
|
||||
final String columnName = mappings.getPhysicalColumnName( logicalColumnName, table );
|
||||
columns[index] = new Column( columnName );
|
||||
unbound.add( columns[index] );
|
||||
//column equals and hashcode is based on column name
|
||||
}
|
||||
catch ( MappingException e ) {
|
||||
unboundNoLogical.add( new Column( columnNames[index] ) );
|
||||
unboundNoLogical.add( new Column( logicalColumnName ) );
|
||||
}
|
||||
}
|
||||
for ( Column column : columns ) {
|
||||
|
@ -1258,17 +1263,69 @@ public class AnnotationConfiguration extends Configuration {
|
|||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Map<Table, List<String[]>> getTableUniqueConstraints() {
|
||||
return tableUniqueConstraints;
|
||||
final Map<Table, List<String[]>> deprecatedStructure = new HashMap<Table, List<String[]>>(
|
||||
CollectionHelper.determineProperSizing( getUniqueConstraintHoldersByTable() ),
|
||||
CollectionHelper.LOAD_FACTOR
|
||||
);
|
||||
for ( Map.Entry<Table, List<UniqueConstraintHolder>> entry : getUniqueConstraintHoldersByTable().entrySet() ) {
|
||||
List<String[]> columnsPerConstraint = new ArrayList<String[]>(
|
||||
CollectionHelper.determineProperSizing( entry.getValue().size() )
|
||||
);
|
||||
deprecatedStructure.put( entry.getKey(), columnsPerConstraint );
|
||||
for ( UniqueConstraintHolder holder : entry.getValue() ) {
|
||||
columnsPerConstraint.add( holder.getColumns() );
|
||||
}
|
||||
}
|
||||
return deprecatedStructure;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Map<Table, List<UniqueConstraintHolder>> getUniqueConstraintHoldersByTable() {
|
||||
return uniqueConstraintHoldersByTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public void addUniqueConstraints(Table table, List uniqueConstraints) {
|
||||
List oldConstraints = tableUniqueConstraints.get( table );
|
||||
if ( oldConstraints == null ) {
|
||||
oldConstraints = new ArrayList();
|
||||
tableUniqueConstraints.put( table, oldConstraints );
|
||||
List<UniqueConstraintHolder> constraintHolders = new ArrayList<UniqueConstraintHolder>(
|
||||
CollectionHelper.determineProperSizing( uniqueConstraints.size() )
|
||||
);
|
||||
|
||||
int keyNameBase = determineCurrentNumberOfUniqueConstraintHolders( table );
|
||||
for ( String[] columns : (List<String[]>)uniqueConstraints ) {
|
||||
final String keyName = "key" + keyNameBase++;
|
||||
constraintHolders.add(
|
||||
new UniqueConstraintHolder().setName( keyName ).setColumns( columns )
|
||||
);
|
||||
}
|
||||
oldConstraints.addAll( uniqueConstraints );
|
||||
addUniqueConstraintHolders( table, constraintHolders );
|
||||
}
|
||||
|
||||
private int determineCurrentNumberOfUniqueConstraintHolders(Table table) {
|
||||
List currentHolders = getUniqueConstraintHoldersByTable().get( table );
|
||||
return currentHolders == null
|
||||
? 0
|
||||
: currentHolders.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void addUniqueConstraintHolders(Table table, List<UniqueConstraintHolder> uniqueConstraintHolders) {
|
||||
List<UniqueConstraintHolder> holderList = getUniqueConstraintHoldersByTable().get( table );
|
||||
if ( holderList == null ) {
|
||||
holderList = new ArrayList<UniqueConstraintHolder>();
|
||||
getUniqueConstraintHoldersByTable().put( table, holderList );
|
||||
}
|
||||
holderList.addAll( uniqueConstraintHolders );
|
||||
}
|
||||
|
||||
public void addMappedBy(String entityName, String propertyName, String inversePropertyName) {
|
||||
|
|
|
@ -27,8 +27,6 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.persistence.MappedSuperclass;
|
||||
|
||||
import org.hibernate.AnnotationException;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.annotations.AnyMetaDef;
|
||||
|
@ -134,10 +132,22 @@ public interface ExtendedMappings extends Mappings {
|
|||
*/
|
||||
public AnnotatedClassType addClassType(XClass clazz);
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #getUniqueConstraintHoldersByTable} instead
|
||||
*/
|
||||
@SuppressWarnings({ "JavaDoc" })
|
||||
public Map<Table, List<String[]>> getTableUniqueConstraints();
|
||||
|
||||
public Map<Table, List<UniqueConstraintHolder>> getUniqueConstraintHoldersByTable();
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #addUniqueConstraintHolders} instead
|
||||
*/
|
||||
@SuppressWarnings({ "JavaDoc" })
|
||||
public void addUniqueConstraints(Table table, List uniqueConstraints);
|
||||
|
||||
public void addUniqueConstraintHolders(Table table, List<UniqueConstraintHolder> uniqueConstraintHolders);
|
||||
|
||||
public void addMappedBy(String entityName, String propertyName, String inversePropertyName);
|
||||
|
||||
public String getFromMappedBy(String entityName, String propertyName);
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
|
||||
* third-party contributors as indicated by either @author tags or express
|
||||
* copyright attribution statements applied by the authors. All
|
||||
* third-party contributions are distributed under license by Red Hat Inc.
|
||||
*
|
||||
* 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, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY 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
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.cfg;
|
||||
|
||||
/**
|
||||
* {@link javax.persistence.UniqueConstraint} annotations are handled via second pass. I do not
|
||||
* understand the reasons why at this time, so here I use a holder object to hold the information
|
||||
* needed to create the unique constraint. The ability to name it is new, and so the code used to
|
||||
* simply keep this as a String array (the column names).
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class UniqueConstraintHolder {
|
||||
private String name;
|
||||
private String[] columns;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public UniqueConstraintHolder setName(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String[] getColumns() {
|
||||
return columns;
|
||||
}
|
||||
|
||||
public UniqueConstraintHolder setColumns(String[] columns) {
|
||||
this.columns = columns;
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -23,7 +23,6 @@
|
|||
*/
|
||||
package org.hibernate.cfg.annotations;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
@ -34,7 +33,6 @@ import javax.persistence.JoinTable;
|
|||
import javax.persistence.PrimaryKeyJoinColumn;
|
||||
import javax.persistence.SecondaryTable;
|
||||
import javax.persistence.SecondaryTables;
|
||||
import javax.persistence.UniqueConstraint;
|
||||
|
||||
import org.hibernate.AnnotationException;
|
||||
import org.hibernate.AssertionFailure;
|
||||
|
@ -68,6 +66,10 @@ import org.hibernate.cfg.Ejb3JoinColumn;
|
|||
import org.hibernate.cfg.ExtendedMappings;
|
||||
import org.hibernate.cfg.InheritanceState;
|
||||
import org.hibernate.cfg.PropertyHolder;
|
||||
import org.hibernate.cfg.ObjectNameSource;
|
||||
import org.hibernate.cfg.NamingStrategy;
|
||||
import org.hibernate.cfg.ObjectNameNormalizer;
|
||||
import org.hibernate.cfg.UniqueConstraintHolder;
|
||||
import org.hibernate.engine.ExecuteUpdateResultCheckStyle;
|
||||
import org.hibernate.engine.FilterDefinition;
|
||||
import org.hibernate.engine.Versioning;
|
||||
|
@ -81,6 +83,7 @@ import org.hibernate.mapping.TableOwner;
|
|||
import org.hibernate.mapping.Value;
|
||||
import org.hibernate.util.ReflectHelper;
|
||||
import org.hibernate.util.StringHelper;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -292,9 +295,7 @@ public class EntityBinder {
|
|||
}
|
||||
|
||||
if ( !inheritanceState.hasParents ) {
|
||||
Iterator<Map.Entry<String, String>> iter = filters.entrySet().iterator();
|
||||
while ( iter.hasNext() ) {
|
||||
Map.Entry<String, String> filter = iter.next();
|
||||
for ( Map.Entry<String, String> filter : filters.entrySet() ) {
|
||||
String filterName = filter.getKey();
|
||||
String cond = filter.getValue();
|
||||
if ( BinderHelper.isDefault( cond ) ) {
|
||||
|
@ -386,6 +387,7 @@ public class EntityBinder {
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public void setProxy(Proxy proxy) {
|
||||
if ( proxy != null ) {
|
||||
lazy = proxy.lazy();
|
||||
|
@ -415,29 +417,58 @@ public class EntityBinder {
|
|||
}
|
||||
}
|
||||
|
||||
private String getClassTableName(String tableName) {
|
||||
if ( StringHelper.isEmpty( tableName ) ) {
|
||||
return mappings.getNamingStrategy().classToTableName( name );
|
||||
private static class EntityTableObjectNameSource implements ObjectNameSource {
|
||||
private final String explicitName;
|
||||
private final String logicalName;
|
||||
|
||||
private EntityTableObjectNameSource(String explicitName, String entityName) {
|
||||
this.explicitName = explicitName;
|
||||
this.logicalName = StringHelper.isNotEmpty( explicitName )
|
||||
? explicitName
|
||||
: StringHelper.unqualify( entityName );
|
||||
}
|
||||
else {
|
||||
return mappings.getNamingStrategy().tableName( tableName );
|
||||
|
||||
public String getExplicitName() {
|
||||
return explicitName;
|
||||
}
|
||||
|
||||
public String getLogicalName() {
|
||||
return logicalName;
|
||||
}
|
||||
}
|
||||
|
||||
private static class EntityTableNamingStrategyHelper implements ObjectNameNormalizer.NamingStrategyHelper {
|
||||
private final String entityName;
|
||||
|
||||
private EntityTableNamingStrategyHelper(String entityName) {
|
||||
this.entityName = entityName;
|
||||
}
|
||||
|
||||
public String determineImplicitName(NamingStrategy strategy) {
|
||||
return strategy.classToTableName( entityName );
|
||||
}
|
||||
|
||||
public String handleExplicitName(NamingStrategy strategy, String name) {
|
||||
return strategy.tableName( name );
|
||||
}
|
||||
}
|
||||
|
||||
public void bindTable(
|
||||
String schema, String catalog,
|
||||
String tableName, List uniqueConstraints,
|
||||
String constraints, Table denormalizedSuperclassTable
|
||||
) {
|
||||
String logicalName = StringHelper.isNotEmpty( tableName ) ?
|
||||
tableName :
|
||||
StringHelper.unqualify( name );
|
||||
Table table = TableBinder.fillTable(
|
||||
schema, catalog,
|
||||
getClassTableName( tableName ),
|
||||
logicalName,
|
||||
persistentClass.isAbstract(), uniqueConstraints, constraints,
|
||||
denormalizedSuperclassTable, mappings
|
||||
String tableName, List<UniqueConstraintHolder> uniqueConstraints,
|
||||
String constraints, Table denormalizedSuperclassTable) {
|
||||
EntityTableObjectNameSource tableNameContext = new EntityTableObjectNameSource( tableName, name );
|
||||
EntityTableNamingStrategyHelper namingStrategyHelper = new EntityTableNamingStrategyHelper( name );
|
||||
final Table table = TableBinder.buildAndFillTable(
|
||||
schema,
|
||||
catalog,
|
||||
tableNameContext,
|
||||
namingStrategyHelper,
|
||||
persistentClass.isAbstract(),
|
||||
uniqueConstraints,
|
||||
constraints,
|
||||
denormalizedSuperclassTable,
|
||||
mappings
|
||||
);
|
||||
|
||||
if ( persistentClass instanceof TableOwner ) {
|
||||
|
@ -592,68 +623,89 @@ public class EntityBinder {
|
|||
return addJoin( null, joinTable, holder, noDelayInPkColumnCreation );
|
||||
}
|
||||
|
||||
/**
|
||||
* A non null propertyHolder means than we process the Pk creation without delay
|
||||
*/
|
||||
private static class SecondaryTableNameSource implements ObjectNameSource {
|
||||
// always has an explicit name
|
||||
private final String explicitName;
|
||||
|
||||
private SecondaryTableNameSource(String explicitName) {
|
||||
this.explicitName = explicitName;
|
||||
}
|
||||
|
||||
public String getExplicitName() {
|
||||
return explicitName;
|
||||
}
|
||||
|
||||
public String getLogicalName() {
|
||||
return explicitName;
|
||||
}
|
||||
}
|
||||
|
||||
private static class SecondaryTableNamingStrategyHelper implements ObjectNameNormalizer.NamingStrategyHelper {
|
||||
public String determineImplicitName(NamingStrategy strategy) {
|
||||
// todo : throw an error?
|
||||
return null;
|
||||
}
|
||||
|
||||
public String handleExplicitName(NamingStrategy strategy, String name) {
|
||||
return strategy.tableName( name );
|
||||
}
|
||||
}
|
||||
|
||||
private static SecondaryTableNamingStrategyHelper SEC_TBL_NS_HELPER = new SecondaryTableNamingStrategyHelper();
|
||||
|
||||
private Join addJoin(
|
||||
SecondaryTable secondaryTable, JoinTable joinTable, PropertyHolder propertyHolder,
|
||||
boolean noDelayInPkColumnCreation
|
||||
) {
|
||||
SecondaryTable secondaryTable,
|
||||
JoinTable joinTable,
|
||||
PropertyHolder propertyHolder,
|
||||
boolean noDelayInPkColumnCreation) {
|
||||
// A non null propertyHolder means than we process the Pk creation without delay
|
||||
Join join = new Join();
|
||||
join.setPersistentClass( persistentClass );
|
||||
String schema;
|
||||
String catalog;
|
||||
String table;
|
||||
String realTable;
|
||||
UniqueConstraint[] uniqueConstraintsAnn;
|
||||
|
||||
final String schema;
|
||||
final String catalog;
|
||||
final SecondaryTableNameSource secondaryTableNameContext;
|
||||
final Object joinColumns;
|
||||
final List<UniqueConstraintHolder> uniqueConstraintHolders;
|
||||
|
||||
if ( secondaryTable != null ) {
|
||||
schema = secondaryTable.schema();
|
||||
catalog = secondaryTable.catalog();
|
||||
table = secondaryTable.name();
|
||||
realTable = mappings.getNamingStrategy().tableName( table ); //always an explicit table name
|
||||
uniqueConstraintsAnn = secondaryTable.uniqueConstraints();
|
||||
secondaryTableNameContext = new SecondaryTableNameSource( secondaryTable.name() );
|
||||
joinColumns = secondaryTable.pkJoinColumns();
|
||||
uniqueConstraintHolders = TableBinder.buildUniqueConstraintHolders( secondaryTable.uniqueConstraints() );
|
||||
}
|
||||
else if ( joinTable != null ) {
|
||||
schema = joinTable.schema();
|
||||
catalog = joinTable.catalog();
|
||||
table = joinTable.name();
|
||||
realTable = mappings.getNamingStrategy().tableName( table ); //always an explicit table name
|
||||
uniqueConstraintsAnn = joinTable.uniqueConstraints();
|
||||
secondaryTableNameContext = new SecondaryTableNameSource( joinTable.name() );
|
||||
joinColumns = joinTable.joinColumns();
|
||||
uniqueConstraintHolders = TableBinder.buildUniqueConstraintHolders( joinTable.uniqueConstraints() );
|
||||
}
|
||||
else {
|
||||
throw new AssertionFailure( "Both JoinTable and SecondaryTable are null" );
|
||||
}
|
||||
List uniqueConstraints = new ArrayList( uniqueConstraintsAnn == null ?
|
||||
0 :
|
||||
uniqueConstraintsAnn.length );
|
||||
if ( uniqueConstraintsAnn != null && uniqueConstraintsAnn.length != 0 ) {
|
||||
for (UniqueConstraint uc : uniqueConstraintsAnn) {
|
||||
uniqueConstraints.add( uc.columnNames() );
|
||||
}
|
||||
}
|
||||
Table tableMapping = TableBinder.fillTable(
|
||||
|
||||
final Table table = TableBinder.buildAndFillTable(
|
||||
schema,
|
||||
catalog,
|
||||
realTable,
|
||||
table, false, uniqueConstraints, null, null, mappings
|
||||
secondaryTableNameContext,
|
||||
SEC_TBL_NS_HELPER,
|
||||
false,
|
||||
uniqueConstraintHolders,
|
||||
null,
|
||||
null,
|
||||
mappings
|
||||
);
|
||||
|
||||
//no check constraints available on joins
|
||||
join.setTable( tableMapping );
|
||||
join.setTable( table );
|
||||
|
||||
//somehow keep joins() for later.
|
||||
//Has to do the work later because it needs persistentClass id!
|
||||
Object joinColumns = null;
|
||||
//get the appropriate pk columns
|
||||
if ( secondaryTable != null ) {
|
||||
joinColumns = secondaryTable.pkJoinColumns();
|
||||
}
|
||||
else if ( joinTable != null ) {
|
||||
joinColumns = joinTable.joinColumns();
|
||||
}
|
||||
log.info(
|
||||
"Adding secondary table to entity {} -> {}", persistentClass.getEntityName(), join.getTable().getName()
|
||||
);
|
||||
|
||||
org.hibernate.annotations.Table matchingTable = findMatchingComplimentTableAnnotation( join );
|
||||
if ( matchingTable != null ) {
|
||||
join.setSequentialSelect( FetchMode.JOIN != matchingTable.fetch() );
|
||||
|
@ -689,8 +741,8 @@ public class EntityBinder {
|
|||
createPrimaryColumnsToSecondaryTable( joinColumns, propertyHolder, join );
|
||||
}
|
||||
else {
|
||||
secondaryTables.put( realTable, join );
|
||||
secondaryTableJoins.put( realTable, joinColumns );
|
||||
secondaryTables.put( table.getQuotedName(), join );
|
||||
secondaryTableJoins.put( table.getQuotedName(), joinColumns );
|
||||
}
|
||||
return join;
|
||||
}
|
||||
|
|
|
@ -32,10 +32,15 @@ import org.hibernate.AnnotationException;
|
|||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.annotations.Index;
|
||||
import org.hibernate.util.StringHelper;
|
||||
import org.hibernate.util.CollectionHelper;
|
||||
import org.hibernate.cfg.BinderHelper;
|
||||
import org.hibernate.cfg.Ejb3JoinColumn;
|
||||
import org.hibernate.cfg.ExtendedMappings;
|
||||
import org.hibernate.cfg.IndexOrUniqueKeySecondPass;
|
||||
import org.hibernate.cfg.ObjectNameNormalizer;
|
||||
import org.hibernate.cfg.ObjectNameSource;
|
||||
import org.hibernate.cfg.NamingStrategy;
|
||||
import org.hibernate.cfg.UniqueConstraintHolder;
|
||||
import org.hibernate.mapping.Collection;
|
||||
import org.hibernate.mapping.Column;
|
||||
import org.hibernate.mapping.DependantValue;
|
||||
|
@ -62,7 +67,8 @@ public class TableBinder {
|
|||
private String catalog;
|
||||
private String name;
|
||||
private boolean isAbstract;
|
||||
private List<String[]> uniqueConstraints;
|
||||
private List<UniqueConstraintHolder> uniqueConstraints;
|
||||
// private List<String[]> uniqueConstraints;
|
||||
String constraints;
|
||||
Table denormalizedSuperTable;
|
||||
ExtendedMappings mappings;
|
||||
|
@ -93,7 +99,7 @@ public class TableBinder {
|
|||
}
|
||||
|
||||
public void setUniqueConstraints(UniqueConstraint[] uniqueConstraints) {
|
||||
this.uniqueConstraints = TableBinder.buildUniqueConstraints( uniqueConstraints );
|
||||
this.uniqueConstraints = TableBinder.buildUniqueConstraintHolders( uniqueConstraints );
|
||||
}
|
||||
|
||||
public void setConstraints(String constraints) {
|
||||
|
@ -108,45 +114,150 @@ public class TableBinder {
|
|||
this.mappings = mappings;
|
||||
}
|
||||
|
||||
private static class AssociationTableNameSource implements ObjectNameSource {
|
||||
private final String explicitName;
|
||||
private final String logicalName;
|
||||
|
||||
private AssociationTableNameSource(String explicitName, String logicalName) {
|
||||
this.explicitName = explicitName;
|
||||
this.logicalName = logicalName;
|
||||
}
|
||||
|
||||
public String getExplicitName() {
|
||||
return explicitName;
|
||||
}
|
||||
|
||||
public String getLogicalName() {
|
||||
return logicalName;
|
||||
}
|
||||
}
|
||||
|
||||
// only bind association table currently
|
||||
public Table bind() {
|
||||
//logicalName only accurate for assoc table...
|
||||
String unquotedOwnerTable = StringHelper.unquote( ownerEntityTable );
|
||||
String unquotedAssocTable = StringHelper.unquote( associatedEntityTable );
|
||||
final String unquotedOwnerTable = StringHelper.unquote( ownerEntityTable );
|
||||
final String unquotedAssocTable = StringHelper.unquote( associatedEntityTable );
|
||||
|
||||
String logicalName = mappings.getNamingStrategy()
|
||||
.logicalCollectionTableName(
|
||||
name,
|
||||
final ObjectNameSource nameSource = buildNameContext( unquotedOwnerTable, unquotedAssocTable );
|
||||
|
||||
final boolean ownerEntityTableQuoted = StringHelper.isQuoted( ownerEntityTable );
|
||||
final boolean associatedEntityTableQuoted = StringHelper.isQuoted( associatedEntityTable );
|
||||
final ObjectNameNormalizer.NamingStrategyHelper namingStrategyHelper = new ObjectNameNormalizer.NamingStrategyHelper() {
|
||||
public String determineImplicitName(NamingStrategy strategy) {
|
||||
final String strategyResult = strategy.collectionTableName(
|
||||
ownerEntity,
|
||||
unquotedOwnerTable,
|
||||
associatedEntity,
|
||||
unquotedAssocTable,
|
||||
propertyName );
|
||||
if ( StringHelper.isQuoted( ownerEntityTable ) || StringHelper.isQuoted( associatedEntityTable ) ) {
|
||||
logicalName = StringHelper.quote( logicalName );
|
||||
}
|
||||
String extendedName;
|
||||
if ( name != null ) {
|
||||
extendedName = mappings.getNamingStrategy().tableName( name );
|
||||
}
|
||||
else {
|
||||
extendedName = mappings.getNamingStrategy()
|
||||
.collectionTableName(
|
||||
ownerEntity,
|
||||
unquotedOwnerTable,
|
||||
associatedEntity,
|
||||
unquotedAssocTable,
|
||||
propertyName
|
||||
);
|
||||
if ( StringHelper.isQuoted( ownerEntityTable ) || StringHelper.isQuoted( associatedEntityTable ) ) {
|
||||
extendedName = StringHelper.quote( extendedName );
|
||||
propertyName
|
||||
|
||||
);
|
||||
return ownerEntityTableQuoted || associatedEntityTableQuoted
|
||||
? StringHelper.quote( strategyResult )
|
||||
: strategyResult;
|
||||
}
|
||||
}
|
||||
return fillTable(
|
||||
schema, catalog,
|
||||
extendedName, logicalName, isAbstract, uniqueConstraints, constraints,
|
||||
denormalizedSuperTable, mappings
|
||||
|
||||
public String handleExplicitName(NamingStrategy strategy, String name) {
|
||||
return strategy.tableName( name );
|
||||
}
|
||||
};
|
||||
|
||||
return buildAndFillTable(
|
||||
schema,
|
||||
catalog,
|
||||
nameSource,
|
||||
namingStrategyHelper,
|
||||
isAbstract,
|
||||
uniqueConstraints,
|
||||
constraints,
|
||||
denormalizedSuperTable,
|
||||
mappings
|
||||
);
|
||||
}
|
||||
|
||||
private ObjectNameSource buildNameContext(String unquotedOwnerTable, String unquotedAssocTable) {
|
||||
String logicalName = mappings.getNamingStrategy().logicalCollectionTableName(
|
||||
name,
|
||||
unquotedOwnerTable,
|
||||
unquotedAssocTable,
|
||||
propertyName
|
||||
);
|
||||
if ( StringHelper.isQuoted( ownerEntityTable ) || StringHelper.isQuoted( associatedEntityTable ) ) {
|
||||
logicalName = StringHelper.quote( logicalName );
|
||||
}
|
||||
|
||||
return new AssociationTableNameSource( name, logicalName );
|
||||
}
|
||||
|
||||
public static Table buildAndFillTable(
|
||||
String schema,
|
||||
String catalog,
|
||||
ObjectNameSource nameSource,
|
||||
ObjectNameNormalizer.NamingStrategyHelper namingStrategyHelper,
|
||||
boolean isAbstract,
|
||||
List<UniqueConstraintHolder> uniqueConstraints,
|
||||
String constraints,
|
||||
Table denormalizedSuperTable,
|
||||
ExtendedMappings mappings) {
|
||||
schema = BinderHelper.isDefault( schema ) ? mappings.getSchemaName() : schema;
|
||||
catalog = BinderHelper.isDefault( catalog ) ? mappings.getCatalogName() : catalog;
|
||||
|
||||
String realTableName = mappings.getObjectNameNormalizer().normalizeDatabaseIdentifier(
|
||||
nameSource.getExplicitName(),
|
||||
namingStrategyHelper
|
||||
);
|
||||
|
||||
final Table table;
|
||||
if ( denormalizedSuperTable != null ) {
|
||||
table = mappings.addDenormalizedTable(
|
||||
schema,
|
||||
catalog,
|
||||
realTableName,
|
||||
isAbstract,
|
||||
null, // subselect
|
||||
denormalizedSuperTable
|
||||
);
|
||||
}
|
||||
else {
|
||||
table = mappings.addTable(
|
||||
schema,
|
||||
catalog,
|
||||
realTableName,
|
||||
null, // subselect
|
||||
isAbstract
|
||||
);
|
||||
}
|
||||
|
||||
if ( uniqueConstraints != null && uniqueConstraints.size() > 0 ) {
|
||||
mappings.addUniqueConstraintHolders( table, uniqueConstraints );
|
||||
}
|
||||
|
||||
if ( constraints != null ) table.addCheckConstraint( constraints );
|
||||
|
||||
// logicalName is null if we are in the second pass
|
||||
final String logicalName = nameSource.getLogicalName();
|
||||
if ( logicalName != null ) {
|
||||
mappings.addTableBinding( schema, catalog, logicalName, realTableName, denormalizedSuperTable );
|
||||
}
|
||||
return table;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param schema
|
||||
* @param catalog
|
||||
* @param realTableName
|
||||
* @param logicalName
|
||||
* @param isAbstract
|
||||
* @param uniqueConstraints
|
||||
* @param constraints
|
||||
* @param denormalizedSuperTable
|
||||
* @param mappings
|
||||
* @return
|
||||
*
|
||||
* @deprecated Use {@link #buildAndFillTable} instead.
|
||||
*/
|
||||
@SuppressWarnings({ "JavaDoc" })
|
||||
public static Table fillTable(
|
||||
String schema, String catalog, String realTableName, String logicalName, boolean isAbstract,
|
||||
List uniqueConstraints, String constraints, Table denormalizedSuperTable, ExtendedMappings mappings
|
||||
|
@ -195,8 +306,9 @@ public class TableBinder {
|
|||
associatedClass = destinationEntity;
|
||||
}
|
||||
else {
|
||||
associatedClass = columns[0].getPropertyHolder() == null ? null : columns[0].getPropertyHolder()
|
||||
.getPersistentClass();
|
||||
associatedClass = columns[0].getPropertyHolder() == null
|
||||
? null
|
||||
: columns[0].getPropertyHolder().getPersistentClass();
|
||||
}
|
||||
final String mappedByProperty = columns[0].getMappedBy();
|
||||
if ( StringHelper.isNotEmpty( mappedByProperty ) ) {
|
||||
|
@ -235,7 +347,7 @@ public class TableBinder {
|
|||
*/
|
||||
Iterator idColumns;
|
||||
if ( referencedEntity instanceof JoinedSubclass ) {
|
||||
idColumns = ( (JoinedSubclass) referencedEntity ).getKey().getColumnIterator();
|
||||
idColumns = referencedEntity.getKey().getColumnIterator();
|
||||
}
|
||||
else {
|
||||
idColumns = referencedEntity.getIdentifier().getColumnIterator();
|
||||
|
@ -345,7 +457,7 @@ public class TableBinder {
|
|||
}
|
||||
}
|
||||
value.createForeignKey();
|
||||
if ( unique == true ) {
|
||||
if ( unique ) {
|
||||
createUniqueConstraint( value );
|
||||
}
|
||||
}
|
||||
|
@ -384,6 +496,10 @@ public class TableBinder {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #buildUniqueConstraintHolders} instead
|
||||
*/
|
||||
@SuppressWarnings({ "JavaDoc" })
|
||||
public static List<String[]> buildUniqueConstraints(UniqueConstraint[] constraintsArray) {
|
||||
List<String[]> result = new ArrayList<String[]>();
|
||||
if ( constraintsArray.length != 0 ) {
|
||||
|
@ -394,6 +510,32 @@ public class TableBinder {
|
|||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a list of {@link org.hibernate.cfg.UniqueConstraintHolder} instances given a list of
|
||||
* {@link UniqueConstraint} annotations.
|
||||
*
|
||||
* @param annotations The {@link UniqueConstraint} annotations.
|
||||
*
|
||||
* @return The built {@link org.hibernate.cfg.UniqueConstraintHolder} instances.
|
||||
*/
|
||||
public static List<UniqueConstraintHolder> buildUniqueConstraintHolders(UniqueConstraint[] annotations) {
|
||||
List<UniqueConstraintHolder> result;
|
||||
if ( annotations == null || annotations.length == 0 ) {
|
||||
result = java.util.Collections.emptyList();
|
||||
}
|
||||
else {
|
||||
result = new ArrayList<UniqueConstraintHolder>( CollectionHelper.determineProperSizing( annotations.length ) );
|
||||
for ( UniqueConstraint uc : annotations ) {
|
||||
result.add(
|
||||
new UniqueConstraintHolder()
|
||||
.setName( uc.name() )
|
||||
.setColumns( uc.columnNames() )
|
||||
);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public void setDefaultName(
|
||||
String ownerEntity, String ownerEntityTable, String associatedEntity, String associatedEntityTable,
|
||||
String propertyName
|
||||
|
|
|
@ -68,7 +68,6 @@ import org.hibernate.SessionFactory;
|
|||
import org.hibernate.SessionFactoryObserver;
|
||||
import org.hibernate.DuplicateMappingException;
|
||||
import org.hibernate.tuple.entity.EntityTuplizerFactory;
|
||||
import org.hibernate.tuple.component.ComponentTuplizerFactory;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.dialect.MySQLDialect;
|
||||
import org.hibernate.dialect.function.SQLFunction;
|
||||
|
@ -2456,6 +2455,8 @@ public class Configuration implements Serializable {
|
|||
Table table = ( Table ) tables.get( key );
|
||||
|
||||
if ( table == null ) {
|
||||
schema = getObjectNameNormalizer().normalizeIdentifierQuoting( schema );
|
||||
catalog = getObjectNameNormalizer().normalizeIdentifierQuoting( catalog );
|
||||
table = new Table();
|
||||
table.setAbstract( isAbstract );
|
||||
table.setName( name );
|
||||
|
@ -2485,6 +2486,9 @@ public class Configuration implements Serializable {
|
|||
throw new DuplicateMappingException( "table", name );
|
||||
}
|
||||
|
||||
schema = getObjectNameNormalizer().normalizeIdentifierQuoting( schema );
|
||||
catalog = getObjectNameNormalizer().normalizeIdentifierQuoting( catalog );
|
||||
|
||||
Table table = new DenormalizedTable( includedTable );
|
||||
table.setAbstract( isAbstract );
|
||||
table.setName( name );
|
||||
|
@ -2786,5 +2790,22 @@ public class Configuration implements Serializable {
|
|||
public MappedSuperclass getMappedSuperclass(Class type) {
|
||||
return (MappedSuperclass) mappedSuperclasses.get( type );
|
||||
}
|
||||
|
||||
public ObjectNameNormalizer getObjectNameNormalizer() {
|
||||
return normalizer;
|
||||
}
|
||||
}
|
||||
|
||||
final ObjectNameNormalizer normalizer = new ObjectNameNormalizerImpl();
|
||||
|
||||
final class ObjectNameNormalizerImpl extends ObjectNameNormalizer implements Serializable {
|
||||
public boolean isUseQuotedIdentifiersGlobally() {
|
||||
String setting = (String) properties.get( Environment.GLOBALLY_QUOTED_IDENTIFIERS );
|
||||
return setting != null && Boolean.valueOf( setting ).booleanValue();
|
||||
}
|
||||
|
||||
public NamingStrategy getNamingStrategy() {
|
||||
return namingStrategy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -501,6 +501,11 @@ public final class Environment {
|
|||
*/
|
||||
public static final String JACC_CONTEXTID = "hibernate.jacc_context_id";
|
||||
|
||||
/**
|
||||
* Should all database identifiers be quoted.
|
||||
*/
|
||||
public static final String GLOBALLY_QUOTED_IDENTIFIERS = "hibernate.globally_quoted_identifiers";
|
||||
|
||||
/**
|
||||
* Enable nullability checking.
|
||||
* Raises an exception if a property marked as not-null is null.
|
||||
|
|
|
@ -2045,15 +2045,24 @@ public final class HbmBinder {
|
|||
// GENERATOR
|
||||
Element subnode = node.element( "generator" );
|
||||
if ( subnode != null ) {
|
||||
model.setIdentifierGeneratorStrategy( subnode.attributeValue( "class" ) );
|
||||
final String generatorClass = subnode.attributeValue( "class" );
|
||||
model.setIdentifierGeneratorStrategy( generatorClass );
|
||||
|
||||
Properties params = new Properties();
|
||||
// YUCK! but cannot think of a clean way to do this given the string-config based scheme
|
||||
params.put( PersistentIdentifierGenerator.IDENTIFIER_NORMALIZER, mappings.getObjectNameNormalizer() );
|
||||
|
||||
if ( mappings.getSchemaName() != null ) {
|
||||
params.setProperty( PersistentIdentifierGenerator.SCHEMA, mappings.getSchemaName() );
|
||||
params.setProperty(
|
||||
PersistentIdentifierGenerator.SCHEMA,
|
||||
mappings.getObjectNameNormalizer().normalizeIdentifierQuoting( mappings.getSchemaName() )
|
||||
);
|
||||
}
|
||||
if ( mappings.getCatalogName() != null ) {
|
||||
params.setProperty( PersistentIdentifierGenerator.CATALOG, mappings.getCatalogName() );
|
||||
params.setProperty(
|
||||
PersistentIdentifierGenerator.CATALOG,
|
||||
mappings.getObjectNameNormalizer().normalizeIdentifierQuoting( mappings.getCatalogName() )
|
||||
);
|
||||
}
|
||||
|
||||
Iterator iter = subnode.elementIterator( "param" );
|
||||
|
|
|
@ -543,4 +543,11 @@ public interface Mappings {
|
|||
* @return the MappedSuperclass
|
||||
*/
|
||||
org.hibernate.mapping.MappedSuperclass getMappedSuperclass(Class type);
|
||||
|
||||
/**
|
||||
* Retrieve the database identifier normalizer for this context.
|
||||
*
|
||||
* @return The normalizer.
|
||||
*/
|
||||
public ObjectNameNormalizer getObjectNameNormalizer();
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
|
||||
* third-party contributors as indicated by either @author tags or express
|
||||
* copyright attribution statements applied by the authors. All
|
||||
* third-party contributions are distributed under license by Red Hat Inc.
|
||||
*
|
||||
* 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, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY 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
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.cfg;
|
||||
|
||||
import org.hibernate.util.StringHelper;
|
||||
|
||||
/**
|
||||
* Provides centralized normalization of how database object names are handled.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public abstract class ObjectNameNormalizer {
|
||||
|
||||
/**
|
||||
* Helper contract for dealing with {@link NamingStrategy} in different situations.
|
||||
*/
|
||||
public static interface NamingStrategyHelper {
|
||||
/**
|
||||
* Called when the user supplied no explicit name/identifier for the given database object.
|
||||
*
|
||||
* @param strategy The naming strategy in effect
|
||||
*
|
||||
* @return The implicit name
|
||||
*/
|
||||
public String determineImplicitName(NamingStrategy strategy);
|
||||
|
||||
/**
|
||||
* Called when the user has supplied an explicit name for the database object.
|
||||
*
|
||||
* @param strategy The naming strategy in effect
|
||||
* @param name The {@link ObjectNameNormalizer#normalizeIdentifierQuoting normalized} explicit object name.
|
||||
*
|
||||
* @return The strategy-handled name.
|
||||
*/
|
||||
public String handleExplicitName(NamingStrategy strategy, String name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the actual contract of normalizing a database name.
|
||||
*
|
||||
* @param explicitName The name the user explicitly gave for the database object.
|
||||
* @param helper The {@link NamingStrategy} helper.
|
||||
*
|
||||
* @return The normalized identifier.
|
||||
*/
|
||||
public String normalizeDatabaseIdentifier(final String explicitName, NamingStrategyHelper helper) {
|
||||
// apply naming strategy
|
||||
if ( StringHelper.isEmpty( explicitName ) ) {
|
||||
// No explicit name given, so allow the naming strategy the chance
|
||||
// to determine it based on the corresponding mapped java name
|
||||
final String objectName = helper.determineImplicitName( getNamingStrategy() );
|
||||
// Conceivable that the naming strategy could return a quoted identifier, or
|
||||
// that user enabled <delimited-identifiers/>
|
||||
return normalizeIdentifierQuoting( objectName );
|
||||
}
|
||||
else {
|
||||
// An explicit name was given:
|
||||
// in some cases we allow the naming strategy to "fine tune" these, but first
|
||||
// handle any quoting for consistent handling in naming strategies
|
||||
String objectName = normalizeIdentifierQuoting( explicitName );
|
||||
objectName = helper.handleExplicitName( getNamingStrategy(), objectName );
|
||||
return normalizeIdentifierQuoting( objectName );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow normalizing of just the quoting aspect of identifiers. This is useful for
|
||||
* schema and catalog in terms of initially making this public.
|
||||
* <p/>
|
||||
* This implements the rules set forth in JPA 2 (section "2.13 Naming of Database Objects") which
|
||||
* states that the double-quote (") is the character which should be used to denote a <tt>quoted
|
||||
* identifier</tt>. Here, we handle recognizing that and converting it to the more elegant
|
||||
* bactick (`) approach used in Hibernate.. Additionally we account for applying what JPA2 terms
|
||||
*
|
||||
*
|
||||
* @param identifier The identifier to be quoting-normalized.
|
||||
* @return The identifier accounting for any quoting that need be applied.
|
||||
*/
|
||||
public String normalizeIdentifierQuoting(String identifier) {
|
||||
if ( identifier == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Convert the JPA2 specific quoting character (double quote) to Hibernate's (back tick)
|
||||
if ( identifier.startsWith( "\"" ) && identifier.endsWith( "\"" ) ) {
|
||||
return '`' + identifier.substring( 1, identifier.length() - 1 ) + '`';
|
||||
}
|
||||
|
||||
// If the user has requested "global" use of quoted identifiers, quote this identifier (using back ticks)
|
||||
// if not already
|
||||
if ( isUseQuotedIdentifiersGlobally() && ! ( identifier.startsWith( "`" ) && identifier.endsWith( "`" ) ) ) {
|
||||
return '`' + identifier + '`';
|
||||
}
|
||||
|
||||
return identifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve whether the user requested that all database identifiers be quoted.
|
||||
*
|
||||
* @return True if the user requested that all database identifiers be quoted, false otherwise.
|
||||
*/
|
||||
protected abstract boolean isUseQuotedIdentifiersGlobally();
|
||||
|
||||
/**
|
||||
* Get the current {@link NamingStrategy}.
|
||||
*
|
||||
* @return The current {@link NamingStrategy}.
|
||||
*/
|
||||
protected abstract NamingStrategy getNamingStrategy();
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
|
||||
* third-party contributors as indicated by either @author tags or express
|
||||
* copyright attribution statements applied by the authors. All
|
||||
* third-party contributions are distributed under license by Red Hat Inc.
|
||||
*
|
||||
* 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, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY 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
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.cfg;
|
||||
|
||||
/**
|
||||
* Source for database object names (identifiers).
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface ObjectNameSource {
|
||||
/**
|
||||
* Retrieve the name explicitly provided by the user.
|
||||
*
|
||||
* @return The explicit name.
|
||||
*/
|
||||
public String getExplicitName();
|
||||
|
||||
/**
|
||||
* Retrieve the logical name for this object. Usually this is the name under which
|
||||
* the "thing" is registered with the {@link Mappings}.
|
||||
*
|
||||
* @return The logical name.
|
||||
*/
|
||||
public String getLogicalName();
|
||||
}
|
|
@ -169,6 +169,11 @@ public class DerbyDialect extends DB2Dialect {
|
|||
return sb.toString();
|
||||
}
|
||||
|
||||
public boolean supportsVariableLimit() {
|
||||
// we bind the limit and offset values directly into the sql...
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean hasForUpdateClause(int forUpdateIndex) {
|
||||
return forUpdateIndex >= 0;
|
||||
}
|
||||
|
|
|
@ -1466,17 +1466,21 @@ qu *
|
|||
* By default, the incoming value is checked to see if its first character
|
||||
* is the back-tick (`). If so, the dialect specific quoting is applied.
|
||||
*
|
||||
* @param column The value to be quoted.
|
||||
* @param name The value to be quoted.
|
||||
* @return The quoted (or unmodified, if not starting with back-tick) value.
|
||||
* @see #openQuote()
|
||||
* @see #closeQuote()
|
||||
*/
|
||||
public final String quote(String column) {
|
||||
if ( column.charAt( 0 ) == '`' ) {
|
||||
return openQuote() + column.substring( 1, column.length() - 1 ) + closeQuote();
|
||||
public final String quote(String name) {
|
||||
if ( name == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ( name.charAt( 0 ) == '`' ) {
|
||||
return openQuote() + name.substring( 1, name.length() - 1 ) + closeQuote();
|
||||
}
|
||||
else {
|
||||
return column;
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@ import org.slf4j.Logger;
|
|||
import org.slf4j.LoggerFactory;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.cfg.ObjectNameNormalizer;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.SessionImplementor;
|
||||
import org.hibernate.exception.JDBCExceptionHelper;
|
||||
|
@ -61,38 +62,55 @@ public class IncrementGenerator implements IdentifierGenerator, Configurable {
|
|||
private String sql;
|
||||
private Class returnClass;
|
||||
|
||||
public synchronized Serializable generate(SessionImplementor session, Object object)
|
||||
throws HibernateException {
|
||||
|
||||
if (sql!=null) {
|
||||
public synchronized Serializable generate(SessionImplementor session, Object object) throws HibernateException {
|
||||
if ( sql != null ) {
|
||||
getNext( session );
|
||||
}
|
||||
return IdentifierGeneratorHelper.createNumber(next++, returnClass);
|
||||
return IdentifierGeneratorHelper.createNumber( next++, returnClass );
|
||||
}
|
||||
|
||||
public void configure(Type type, Properties params, Dialect dialect)
|
||||
throws MappingException {
|
||||
|
||||
String tableList = params.getProperty("tables");
|
||||
if (tableList==null) tableList = params.getProperty(PersistentIdentifierGenerator.TABLES);
|
||||
String[] tables = StringHelper.split(", ", tableList);
|
||||
String column = params.getProperty("column");
|
||||
if (column==null) column = params.getProperty(PersistentIdentifierGenerator.PK);
|
||||
String schema = params.getProperty(PersistentIdentifierGenerator.SCHEMA);
|
||||
String catalog = params.getProperty(PersistentIdentifierGenerator.CATALOG);
|
||||
public void configure(Type type, Properties params, Dialect dialect) throws MappingException {
|
||||
returnClass = type.getReturnedClass();
|
||||
|
||||
ObjectNameNormalizer normalizer =
|
||||
( ObjectNameNormalizer ) params.get( PersistentIdentifierGenerator.IDENTIFIER_NORMALIZER );
|
||||
|
||||
String column = params.getProperty( "column" );
|
||||
if ( column == null ) {
|
||||
column = params.getProperty( PersistentIdentifierGenerator.PK );
|
||||
}
|
||||
column = dialect.quote( normalizer.normalizeIdentifierQuoting( column ) );
|
||||
|
||||
String tableList = params.getProperty( "tables" );
|
||||
if ( tableList == null ) {
|
||||
tableList = params.getProperty( PersistentIdentifierGenerator.TABLES );
|
||||
}
|
||||
String[] tables = StringHelper.split( ", ", tableList );
|
||||
|
||||
final String schema = dialect.quote(
|
||||
normalizer.normalizeIdentifierQuoting(
|
||||
params.getProperty( PersistentIdentifierGenerator.SCHEMA )
|
||||
)
|
||||
);
|
||||
final String catalog = dialect.quote(
|
||||
normalizer.normalizeIdentifierQuoting(
|
||||
params.getProperty( PersistentIdentifierGenerator.CATALOG )
|
||||
)
|
||||
);
|
||||
|
||||
StringBuffer buf = new StringBuffer();
|
||||
for ( int i=0; i<tables.length; i++ ) {
|
||||
if (tables.length>1) {
|
||||
buf.append("select ").append(column).append(" from ");
|
||||
for ( int i=0; i < tables.length; i++ ) {
|
||||
final String tableName = dialect.quote( normalizer.normalizeIdentifierQuoting( tables[i] ) );
|
||||
if ( tables.length > 1 ) {
|
||||
buf.append( "select " ).append( column ).append( " from " );
|
||||
}
|
||||
buf.append( Table.qualify( catalog, schema, tableName ) );
|
||||
if ( i < tables.length-1 ) {
|
||||
buf.append( " union " );
|
||||
}
|
||||
buf.append( Table.qualify( catalog, schema, tables[i] ) );
|
||||
if ( i<tables.length-1) buf.append(" union ");
|
||||
}
|
||||
if (tables.length>1) {
|
||||
buf.insert(0, "( ").append(" ) ids_");
|
||||
if ( tables.length > 1 ) {
|
||||
buf.insert( 0, "( " ).append( " ) ids_" );
|
||||
column = "ids_." + column;
|
||||
}
|
||||
|
||||
|
@ -100,9 +118,7 @@ public class IncrementGenerator implements IdentifierGenerator, Configurable {
|
|||
}
|
||||
|
||||
private void getNext( SessionImplementor session ) {
|
||||
|
||||
log.debug("fetching initial value: " + sql);
|
||||
|
||||
log.debug( "fetching initial value: " + sql );
|
||||
try {
|
||||
PreparedStatement st = session.getBatcher().prepareSelectStatement(sql);
|
||||
try {
|
||||
|
@ -133,7 +149,7 @@ public class IncrementGenerator implements IdentifierGenerator, Configurable {
|
|||
sqle,
|
||||
"could not fetch initial value for increment generator",
|
||||
sql
|
||||
);
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@ import org.slf4j.LoggerFactory;
|
|||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.cfg.ObjectNameNormalizer;
|
||||
import org.hibernate.jdbc.util.FormatStyle;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.SessionImplementor;
|
||||
|
@ -221,22 +222,41 @@ public class MultipleHiLoPerTableGenerator
|
|||
}
|
||||
|
||||
public void configure(Type type, Properties params, Dialect dialect) throws MappingException {
|
||||
tableName = PropertiesHelper.getString(ID_TABLE, params, DEFAULT_TABLE);
|
||||
pkColumnName = PropertiesHelper.getString(PK_COLUMN_NAME, params, DEFAULT_PK_COLUMN);
|
||||
valueColumnName = PropertiesHelper.getString(VALUE_COLUMN_NAME, params, DEFAULT_VALUE_COLUMN);
|
||||
String schemaName = params.getProperty(SCHEMA);
|
||||
String catalogName = params.getProperty(CATALOG);
|
||||
keySize = PropertiesHelper.getInt(PK_LENGTH_NAME, params, DEFAULT_PK_LENGTH);
|
||||
String keyValue = PropertiesHelper.getString(PK_VALUE_NAME, params, params.getProperty(TABLE) );
|
||||
ObjectNameNormalizer normalizer = ( ObjectNameNormalizer ) params.get( IDENTIFIER_NORMALIZER );
|
||||
|
||||
if ( tableName.indexOf( '.' )<0 ) {
|
||||
tableName = normalizer.normalizeIdentifierQuoting( PropertiesHelper.getString( ID_TABLE, params, DEFAULT_TABLE ) );
|
||||
if ( tableName.indexOf( '.' ) < 0 ) {
|
||||
tableName = dialect.quote( tableName );
|
||||
final String schemaName = dialect.quote(
|
||||
normalizer.normalizeIdentifierQuoting( params.getProperty( SCHEMA ) )
|
||||
);
|
||||
final String catalogName = dialect.quote(
|
||||
normalizer.normalizeIdentifierQuoting( params.getProperty( CATALOG ) )
|
||||
);
|
||||
tableName = Table.qualify( catalogName, schemaName, tableName );
|
||||
}
|
||||
else {
|
||||
// if already qualified there is not much we can do in a portable manner so we pass it
|
||||
// through and assume the user has set up the name correctly.
|
||||
}
|
||||
|
||||
pkColumnName = dialect.quote(
|
||||
normalizer.normalizeIdentifierQuoting(
|
||||
PropertiesHelper.getString( PK_COLUMN_NAME, params, DEFAULT_PK_COLUMN )
|
||||
)
|
||||
);
|
||||
valueColumnName = dialect.quote(
|
||||
normalizer.normalizeIdentifierQuoting(
|
||||
PropertiesHelper.getString( VALUE_COLUMN_NAME, params, DEFAULT_VALUE_COLUMN )
|
||||
)
|
||||
);
|
||||
keySize = PropertiesHelper.getInt(PK_LENGTH_NAME, params, DEFAULT_PK_LENGTH);
|
||||
String keyValue = PropertiesHelper.getString(PK_VALUE_NAME, params, params.getProperty(TABLE) );
|
||||
|
||||
query = "select " +
|
||||
valueColumnName +
|
||||
" from " +
|
||||
dialect.appendLockHint(LockMode.UPGRADE, tableName) +
|
||||
dialect.appendLockHint( LockMode.PESSIMISTIC_WRITE, tableName ) +
|
||||
" where " + pkColumnName + " = '" + keyValue + "'" +
|
||||
dialect.getForUpdateString();
|
||||
|
||||
|
|
|
@ -68,6 +68,11 @@ public interface PersistentIdentifierGenerator extends IdentifierGenerator {
|
|||
*/
|
||||
public static final String CATALOG = "catalog";
|
||||
|
||||
/**
|
||||
* The key under whcih to find the {@link org.hibernate.cfg.ObjectNameNormalizer} in the config param map.
|
||||
*/
|
||||
public static final String IDENTIFIER_NORMALIZER = "identifier_normalizer";
|
||||
|
||||
/**
|
||||
* The SQL required to create the underlying database objects.
|
||||
*
|
||||
|
|
|
@ -34,6 +34,7 @@ import org.slf4j.Logger;
|
|||
import org.slf4j.LoggerFactory;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.cfg.ObjectNameNormalizer;
|
||||
import org.hibernate.exception.JDBCExceptionHelper;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.SessionImplementor;
|
||||
|
@ -53,8 +54,8 @@ import org.hibernate.util.PropertiesHelper;
|
|||
* @see TableHiLoGenerator
|
||||
* @author Gavin King
|
||||
*/
|
||||
|
||||
public class SequenceGenerator implements PersistentIdentifierGenerator, Configurable {
|
||||
private static final Logger log = LoggerFactory.getLogger(SequenceGenerator.class);
|
||||
|
||||
/**
|
||||
* The sequence parameter
|
||||
|
@ -72,20 +73,29 @@ public class SequenceGenerator implements PersistentIdentifierGenerator, Configu
|
|||
private Type identifierType;
|
||||
private String sql;
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(SequenceGenerator.class);
|
||||
|
||||
public void configure(Type type, Properties params, Dialect dialect) throws MappingException {
|
||||
sequenceName = PropertiesHelper.getString(SEQUENCE, params, "hibernate_sequence");
|
||||
parameters = params.getProperty(PARAMETERS);
|
||||
String schemaName = params.getProperty(SCHEMA);
|
||||
String catalogName = params.getProperty(CATALOG);
|
||||
ObjectNameNormalizer normalizer = ( ObjectNameNormalizer ) params.get( IDENTIFIER_NORMALIZER );
|
||||
sequenceName = normalizer.normalizeIdentifierQuoting(
|
||||
PropertiesHelper.getString( SEQUENCE, params, "hibernate_sequence" )
|
||||
);
|
||||
parameters = params.getProperty( PARAMETERS );
|
||||
|
||||
if (sequenceName.indexOf( '.' ) < 0) {
|
||||
sequenceName = Table.qualify( catalogName, schemaName, sequenceName );
|
||||
if ( sequenceName.indexOf( '.' ) < 0 ) {
|
||||
final String schemaName = normalizer.normalizeIdentifierQuoting( params.getProperty( SCHEMA ) );
|
||||
final String catalogName = normalizer.normalizeIdentifierQuoting( params.getProperty( CATALOG ) );
|
||||
sequenceName = Table.qualify(
|
||||
dialect.quote( catalogName ),
|
||||
dialect.quote( schemaName ),
|
||||
dialect.quote( sequenceName )
|
||||
);
|
||||
}
|
||||
else {
|
||||
// if already qualified there is not much we can do in a portable manner so we pass it
|
||||
// through and assume the user has set up the name correctly.
|
||||
}
|
||||
|
||||
this.identifierType = type;
|
||||
sql = dialect.getSequenceNextValString(sequenceName);
|
||||
sql = dialect.getSequenceNextValString( sequenceName );
|
||||
}
|
||||
|
||||
public Serializable generate(SessionImplementor session, Object obj)
|
||||
|
|
|
@ -36,6 +36,7 @@ import org.slf4j.Logger;
|
|||
import org.slf4j.LoggerFactory;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.cfg.ObjectNameNormalizer;
|
||||
import org.hibernate.jdbc.util.FormatStyle;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.SessionImplementor;
|
||||
|
@ -88,20 +89,33 @@ public class TableGenerator extends TransactionHelper
|
|||
private String update;
|
||||
|
||||
public void configure(Type type, Properties params, Dialect dialect) {
|
||||
ObjectNameNormalizer normalizer = ( ObjectNameNormalizer ) params.get( IDENTIFIER_NORMALIZER );
|
||||
|
||||
tableName = PropertiesHelper.getString(TABLE, params, DEFAULT_TABLE_NAME);
|
||||
columnName = PropertiesHelper.getString(COLUMN, params, DEFAULT_COLUMN_NAME);
|
||||
String schemaName = params.getProperty(SCHEMA);
|
||||
String catalogName = params.getProperty(CATALOG);
|
||||
|
||||
if ( tableName.indexOf( '.' )<0 ) {
|
||||
tableName = Table.qualify( catalogName, schemaName, tableName );
|
||||
tableName = PropertiesHelper.getString( TABLE, params, DEFAULT_TABLE_NAME );
|
||||
if ( tableName.indexOf( '.' ) < 0 ) {
|
||||
final String schemaName = normalizer.normalizeIdentifierQuoting( params.getProperty( SCHEMA ) );
|
||||
final String catalogName = normalizer.normalizeIdentifierQuoting( params.getProperty( CATALOG ) );
|
||||
tableName = Table.qualify(
|
||||
dialect.quote( catalogName ),
|
||||
dialect.quote( schemaName ),
|
||||
dialect.quote( tableName )
|
||||
);
|
||||
}
|
||||
else {
|
||||
// if already qualified there is not much we can do in a portable manner so we pass it
|
||||
// through and assume the user has set up the name correctly.
|
||||
}
|
||||
|
||||
columnName = dialect.quote(
|
||||
normalizer.normalizeIdentifierQuoting(
|
||||
PropertiesHelper.getString( COLUMN, params, DEFAULT_COLUMN_NAME )
|
||||
)
|
||||
);
|
||||
|
||||
query = "select " +
|
||||
columnName +
|
||||
" from " +
|
||||
dialect.appendLockHint(LockMode.UPGRADE, tableName) +
|
||||
dialect.appendLockHint(LockMode.PESSIMISTIC_WRITE, tableName) +
|
||||
dialect.getForUpdateString();
|
||||
|
||||
update = "update " +
|
||||
|
|
|
@ -34,6 +34,7 @@ import org.hibernate.id.PersistentIdentifierGenerator;
|
|||
import org.hibernate.id.Configurable;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.cfg.ObjectNameNormalizer;
|
||||
import org.hibernate.engine.SessionImplementor;
|
||||
import org.hibernate.mapping.Table;
|
||||
import org.hibernate.util.PropertiesHelper;
|
||||
|
@ -160,7 +161,7 @@ public class SequenceStyleGenerator implements PersistentIdentifierGenerator, Co
|
|||
this.identifierType = type;
|
||||
boolean forceTableUse = PropertiesHelper.getBoolean( FORCE_TBL_PARAM, params, false );
|
||||
|
||||
final String sequenceName = determineSequenceName( params );
|
||||
final String sequenceName = determineSequenceName( params, dialect );
|
||||
|
||||
final int initialValue = determineInitialValue( params );
|
||||
int incrementSize = determineIncrementSize( params );
|
||||
|
@ -190,14 +191,25 @@ public class SequenceStyleGenerator implements PersistentIdentifierGenerator, Co
|
|||
* Called during {@link #configure configuration}.
|
||||
*
|
||||
* @param params The params supplied in the generator config (plus some standard useful extras).
|
||||
* @param dialect The dialect in effect
|
||||
* @return The sequence name
|
||||
*/
|
||||
protected String determineSequenceName(Properties params) {
|
||||
protected String determineSequenceName(Properties params, Dialect dialect) {
|
||||
ObjectNameNormalizer normalizer = ( ObjectNameNormalizer ) params.get( IDENTIFIER_NORMALIZER );
|
||||
String sequenceName = PropertiesHelper.getString( SEQUENCE_PARAM, params, DEF_SEQUENCE_NAME );
|
||||
if ( sequenceName.indexOf( '.' ) < 0 ) {
|
||||
sequenceName = normalizer.normalizeIdentifierQuoting( sequenceName );
|
||||
String schemaName = params.getProperty( SCHEMA );
|
||||
String catalogName = params.getProperty( CATALOG );
|
||||
sequenceName = Table.qualify( catalogName, schemaName, sequenceName );
|
||||
sequenceName = Table.qualify(
|
||||
dialect.quote( catalogName ),
|
||||
dialect.quote( schemaName ),
|
||||
dialect.quote( sequenceName )
|
||||
);
|
||||
}
|
||||
else {
|
||||
// if already qualified there is not much we can do in a portable manner so we pass it
|
||||
// through and assume the user has set up the name correctly.
|
||||
}
|
||||
return sequenceName;
|
||||
}
|
||||
|
@ -210,10 +222,13 @@ public class SequenceStyleGenerator implements PersistentIdentifierGenerator, Co
|
|||
* physical table</b>.
|
||||
*
|
||||
* @param params The params supplied in the generator config (plus some standard useful extras).
|
||||
* @param dialect The dialect in effect.
|
||||
* @return The value column name
|
||||
*/
|
||||
protected String determineValueColumnName(Properties params) {
|
||||
return PropertiesHelper.getString( VALUE_COLUMN_PARAM, params, DEF_VALUE_COLUMN );
|
||||
protected String determineValueColumnName(Properties params, Dialect dialect) {
|
||||
ObjectNameNormalizer normalizer = ( ObjectNameNormalizer ) params.get( IDENTIFIER_NORMALIZER );
|
||||
String name = PropertiesHelper.getString( VALUE_COLUMN_PARAM, params, DEF_VALUE_COLUMN );
|
||||
return dialect.quote( normalizer.normalizeIdentifierQuoting( name ) );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -296,7 +311,7 @@ public class SequenceStyleGenerator implements PersistentIdentifierGenerator, Co
|
|||
return new SequenceStructure( dialect, sequenceName, initialValue, incrementSize );
|
||||
}
|
||||
else {
|
||||
String valueColumnName = determineValueColumnName( params );
|
||||
String valueColumnName = determineValueColumnName( params, dialect );
|
||||
return new TableStructure( dialect, sequenceName, valueColumnName, initialValue, incrementSize );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,8 +46,8 @@ import org.hibernate.type.Type;
|
|||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.cfg.ObjectNameNormalizer;
|
||||
import org.hibernate.jdbc.util.FormatStyle;
|
||||
import org.hibernate.mapping.Table;
|
||||
import org.hibernate.util.PropertiesHelper;
|
||||
|
@ -287,9 +287,9 @@ public class TableGenerator extends TransactionHelper implements PersistentIdent
|
|||
public void configure(Type type, Properties params, Dialect dialect) throws MappingException {
|
||||
identifierType = type;
|
||||
|
||||
tableName = determneGeneratorTableName( params );
|
||||
segmentColumnName = determineSegmentColumnName( params );
|
||||
valueColumnName = determineValueColumnName( params );
|
||||
tableName = determneGeneratorTableName( params, dialect );
|
||||
segmentColumnName = determineSegmentColumnName( params, dialect );
|
||||
valueColumnName = determineValueColumnName( params, dialect );
|
||||
|
||||
segmentValue = determineSegmentValue( params );
|
||||
|
||||
|
@ -313,16 +313,27 @@ public class TableGenerator extends TransactionHelper implements PersistentIdent
|
|||
*
|
||||
* @see #getTableName()
|
||||
* @param params The params supplied in the generator config (plus some standard useful extras).
|
||||
* @param dialect The dialect in effect
|
||||
* @return The table name to use.
|
||||
*/
|
||||
protected String determneGeneratorTableName(Properties params) {
|
||||
protected String determneGeneratorTableName(Properties params, Dialect dialect) {
|
||||
String name = PropertiesHelper.getString( TABLE_PARAM, params, DEF_TABLE );
|
||||
boolean isGivenNameUnqualified = name.indexOf( '.' ) < 0;
|
||||
if ( isGivenNameUnqualified ) {
|
||||
ObjectNameNormalizer normalizer = ( ObjectNameNormalizer ) params.get( IDENTIFIER_NORMALIZER );
|
||||
name = normalizer.normalizeIdentifierQuoting( name );
|
||||
// if the given name is un-qualified we may neen to qualify it
|
||||
String schemaName = params.getProperty( SCHEMA );
|
||||
String catalogName = params.getProperty( CATALOG );
|
||||
name = Table.qualify( catalogName, schemaName, name );
|
||||
String schemaName = normalizer.normalizeIdentifierQuoting( params.getProperty( SCHEMA ) );
|
||||
String catalogName = normalizer.normalizeIdentifierQuoting( params.getProperty( CATALOG ) );
|
||||
name = Table.qualify(
|
||||
dialect.quote( catalogName ),
|
||||
dialect.quote( schemaName ),
|
||||
dialect.quote( name)
|
||||
);
|
||||
}
|
||||
else {
|
||||
// if already qualified there is not much we can do in a portable manner so we pass it
|
||||
// through and assume the user has set up the name correctly.
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
@ -335,10 +346,13 @@ public class TableGenerator extends TransactionHelper implements PersistentIdent
|
|||
*
|
||||
* @see #getSegmentColumnName()
|
||||
* @param params The params supplied in the generator config (plus some standard useful extras).
|
||||
* @param dialect The dialect in effect
|
||||
* @return The name of the segment column
|
||||
*/
|
||||
protected String determineSegmentColumnName(Properties params) {
|
||||
return PropertiesHelper.getString( SEGMENT_COLUMN_PARAM, params, DEF_SEGMENT_COLUMN );
|
||||
protected String determineSegmentColumnName(Properties params, Dialect dialect) {
|
||||
ObjectNameNormalizer normalizer = ( ObjectNameNormalizer ) params.get( IDENTIFIER_NORMALIZER );
|
||||
String name = PropertiesHelper.getString( SEGMENT_COLUMN_PARAM, params, DEF_SEGMENT_COLUMN );
|
||||
return dialect.quote( normalizer.normalizeIdentifierQuoting( name ) );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -348,10 +362,13 @@ public class TableGenerator extends TransactionHelper implements PersistentIdent
|
|||
*
|
||||
* @see #getValueColumnName()
|
||||
* @param params The params supplied in the generator config (plus some standard useful extras).
|
||||
* @param dialect The dialect in effect
|
||||
* @return The name of the value column
|
||||
*/
|
||||
protected String determineValueColumnName(Properties params) {
|
||||
return PropertiesHelper.getString( VALUE_COLUMN_PARAM, params, DEF_VALUE_COLUMN );
|
||||
protected String determineValueColumnName(Properties params, Dialect dialect) {
|
||||
ObjectNameNormalizer normalizer = ( ObjectNameNormalizer ) params.get( IDENTIFIER_NORMALIZER );
|
||||
String name = PropertiesHelper.getString( VALUE_COLUMN_PARAM, params, DEF_VALUE_COLUMN );
|
||||
return dialect.quote( normalizer.normalizeIdentifierQuoting( name ) );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -69,7 +69,7 @@ public class TableStructure extends TransactionHelper implements DatabaseStructu
|
|||
this.valueColumnName = valueColumnName;
|
||||
|
||||
selectQuery = "select " + valueColumnName + " as id_val" +
|
||||
" from " + dialect.appendLockHint( LockMode.UPGRADE, tableName ) +
|
||||
" from " + dialect.appendLockHint( LockMode.PESSIMISTIC_WRITE, tableName ) +
|
||||
dialect.getForUpdateString();
|
||||
|
||||
updateQuery = "update " + tableName +
|
||||
|
|
|
@ -11,8 +11,11 @@ import org.hibernate.id.enhanced.SequenceStyleGenerator;
|
|||
import org.hibernate.id.enhanced.SequenceStructure;
|
||||
import org.hibernate.id.enhanced.OptimizerFactory;
|
||||
import org.hibernate.id.enhanced.TableStructure;
|
||||
import org.hibernate.id.PersistentIdentifierGenerator;
|
||||
import org.hibernate.Hibernate;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.cfg.ObjectNameNormalizer;
|
||||
import org.hibernate.cfg.NamingStrategy;
|
||||
|
||||
/**
|
||||
* Tests that SequenceStyleGenerator configures itself as expected
|
||||
|
@ -34,7 +37,7 @@ public class SequenceStyleConfigUnitTest extends UnitTestCase {
|
|||
*/
|
||||
public void testDefaultedSequenceBackedConfiguration() {
|
||||
Dialect dialect = new SequenceDialect();
|
||||
Properties props = new Properties();
|
||||
Properties props = buildGeneratorPropertiesBase();
|
||||
SequenceStyleGenerator generator = new SequenceStyleGenerator();
|
||||
generator.configure( Hibernate.LONG, props, dialect );
|
||||
|
||||
|
@ -43,12 +46,29 @@ public class SequenceStyleConfigUnitTest extends UnitTestCase {
|
|||
assertEquals( SequenceStyleGenerator.DEF_SEQUENCE_NAME, generator.getDatabaseStructure().getName() );
|
||||
}
|
||||
|
||||
private Properties buildGeneratorPropertiesBase() {
|
||||
Properties props = new Properties();
|
||||
props.put(
|
||||
PersistentIdentifierGenerator.IDENTIFIER_NORMALIZER,
|
||||
new ObjectNameNormalizer() {
|
||||
protected boolean isUseQuotedIdentifiersGlobally() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected NamingStrategy getNamingStrategy() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
);
|
||||
return props;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test all params defaulted with a dialect which does not support sequences
|
||||
*/
|
||||
public void testDefaultedTableBackedConfiguration() {
|
||||
Dialect dialect = new TableDialect();
|
||||
Properties props = new Properties();
|
||||
Properties props = buildGeneratorPropertiesBase();
|
||||
SequenceStyleGenerator generator = new SequenceStyleGenerator();
|
||||
generator.configure( Hibernate.LONG, props, dialect );
|
||||
|
||||
|
@ -63,7 +83,7 @@ public class SequenceStyleConfigUnitTest extends UnitTestCase {
|
|||
* dialect supporting pooled sequences (pooled) and not (hilo)
|
||||
*/
|
||||
public void testDefaultOptimizerBasedOnIncrementBackedBySequence() {
|
||||
Properties props = new Properties();
|
||||
Properties props = buildGeneratorPropertiesBase();
|
||||
props.setProperty( SequenceStyleGenerator.INCREMENT_PARAM, "10" );
|
||||
|
||||
// for dialects which do not support pooled sequences, we default to pooled+table
|
||||
|
@ -89,7 +109,7 @@ public class SequenceStyleConfigUnitTest extends UnitTestCase {
|
|||
* pooled.
|
||||
*/
|
||||
public void testDefaultOptimizerBasedOnIncrementBackedByTable() {
|
||||
Properties props = new Properties();
|
||||
Properties props = buildGeneratorPropertiesBase();
|
||||
props.setProperty( SequenceStyleGenerator.INCREMENT_PARAM, "10" );
|
||||
Dialect dialect = new TableDialect();
|
||||
SequenceStyleGenerator generator = new SequenceStyleGenerator();
|
||||
|
@ -104,7 +124,7 @@ public class SequenceStyleConfigUnitTest extends UnitTestCase {
|
|||
*/
|
||||
public void testForceTableUse() {
|
||||
Dialect dialect = new SequenceDialect();
|
||||
Properties props = new Properties();
|
||||
Properties props = buildGeneratorPropertiesBase();
|
||||
props.setProperty( SequenceStyleGenerator.FORCE_TBL_PARAM, "true" );
|
||||
SequenceStyleGenerator generator = new SequenceStyleGenerator();
|
||||
generator.configure( Hibernate.LONG, props, dialect );
|
||||
|
@ -121,7 +141,7 @@ public class SequenceStyleConfigUnitTest extends UnitTestCase {
|
|||
final Dialect dialect = new SequenceDialect();
|
||||
|
||||
// optimizer=none w/ increment > 1 => should honor optimizer
|
||||
Properties props = new Properties();
|
||||
Properties props = buildGeneratorPropertiesBase();
|
||||
props.setProperty( SequenceStyleGenerator.OPT_PARAM, OptimizerFactory.NONE );
|
||||
props.setProperty( SequenceStyleGenerator.INCREMENT_PARAM, "20" );
|
||||
SequenceStyleGenerator generator = new SequenceStyleGenerator();
|
||||
|
@ -132,7 +152,7 @@ public class SequenceStyleConfigUnitTest extends UnitTestCase {
|
|||
assertEquals( 1, generator.getDatabaseStructure().getIncrementSize() );
|
||||
|
||||
// optimizer=hilo w/ increment > 1 => hilo
|
||||
props = new Properties();
|
||||
props = buildGeneratorPropertiesBase();
|
||||
props.setProperty( SequenceStyleGenerator.OPT_PARAM, OptimizerFactory.HILO );
|
||||
props.setProperty( SequenceStyleGenerator.INCREMENT_PARAM, "20" );
|
||||
generator = new SequenceStyleGenerator();
|
||||
|
@ -143,7 +163,7 @@ public class SequenceStyleConfigUnitTest extends UnitTestCase {
|
|||
assertEquals( 20, generator.getDatabaseStructure().getIncrementSize() );
|
||||
|
||||
// optimizer=pooled w/ increment > 1 => hilo
|
||||
props = new Properties();
|
||||
props = buildGeneratorPropertiesBase();
|
||||
props.setProperty( SequenceStyleGenerator.OPT_PARAM, OptimizerFactory.POOL );
|
||||
props.setProperty( SequenceStyleGenerator.INCREMENT_PARAM, "20" );
|
||||
generator = new SequenceStyleGenerator();
|
||||
|
|
Loading…
Reference in New Issue