HHH-4553 - Hibernate doesn't support official JPA2 escape char for table name
git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@18158 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
parent
25343680c9
commit
6b9e796074
|
@ -444,6 +444,9 @@ public class BinderHelper {
|
|||
( (org.hibernate.mapping.Column) id.getColumnIterator().next() ).getName()
|
||||
);
|
||||
}
|
||||
// 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 ( !isDefault( generatorName ) ) {
|
||||
//we have a named generator
|
||||
IdGenerator gen = mappings.getGenerator( generatorName, localGenerators );
|
||||
|
|
|
@ -189,9 +189,15 @@ public class Ejb3Column {
|
|||
}
|
||||
|
||||
protected void initMappingColumn(
|
||||
String columnName, String propertyName, int length, int precision, int scale, boolean nullable,
|
||||
String sqlType, boolean unique, boolean applyNamingStrategy
|
||||
) {
|
||||
String columnName,
|
||||
String propertyName,
|
||||
int length,
|
||||
int precision,
|
||||
int scale,
|
||||
boolean nullable,
|
||||
String sqlType,
|
||||
boolean unique,
|
||||
boolean applyNamingStrategy) {
|
||||
if ( StringHelper.isNotEmpty( formulaString ) ) {
|
||||
this.formula = new Formula();
|
||||
this.formula.setFormula( formulaString );
|
||||
|
@ -218,16 +224,25 @@ public class Ejb3Column {
|
|||
if ( applyNamingStrategy ) {
|
||||
if ( StringHelper.isEmpty( columnName ) ) {
|
||||
if ( propertyName != null ) {
|
||||
mappingColumn.setName( mappings.getNamingStrategy().propertyToColumnName( propertyName ) );
|
||||
mappingColumn.setName(
|
||||
mappings.getObjectNameNormalizer().normalizeIdentifierQuoting(
|
||||
mappings.getNamingStrategy().propertyToColumnName( propertyName )
|
||||
)
|
||||
);
|
||||
}
|
||||
//Do nothing otherwise
|
||||
}
|
||||
else {
|
||||
mappingColumn.setName( mappings.getNamingStrategy().columnName( columnName ) );
|
||||
columnName = mappings.getObjectNameNormalizer().normalizeIdentifierQuoting( columnName );
|
||||
columnName = mappings.getNamingStrategy().columnName( columnName );
|
||||
columnName = mappings.getObjectNameNormalizer().normalizeIdentifierQuoting( columnName );
|
||||
mappingColumn.setName( columnName );
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ( StringHelper.isNotEmpty( columnName ) ) mappingColumn.setName( columnName );
|
||||
if ( StringHelper.isNotEmpty( columnName ) ) {
|
||||
mappingColumn.setName( mappings.getObjectNameNormalizer().normalizeIdentifierQuoting( columnName ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -383,31 +398,38 @@ public class Ejb3Column {
|
|||
log.debug( "Column(s) overridden for property {}", inferredData.getPropertyName() );
|
||||
}
|
||||
if ( actualCols == null ) {
|
||||
columns = buildImplicitColumn( inferredData,
|
||||
columns = buildImplicitColumn(
|
||||
inferredData,
|
||||
suffixForDefaultColumnName,
|
||||
secondaryTables,
|
||||
propertyHolder,
|
||||
nullability,
|
||||
mappings );
|
||||
mappings
|
||||
);
|
||||
}
|
||||
else {
|
||||
final int length = actualCols.length;
|
||||
columns = new Ejb3Column[length];
|
||||
for (int index = 0; index < length; index++) {
|
||||
final ObjectNameNormalizer nameNormalizer = mappings.getObjectNameNormalizer();
|
||||
javax.persistence.Column col = actualCols[index];
|
||||
String sqlType = col.columnDefinition().equals( "" ) ? null : col.columnDefinition();
|
||||
final String sqlType = col.columnDefinition().equals( "" )
|
||||
? null
|
||||
: nameNormalizer.normalizeIdentifierQuoting( col.columnDefinition() );
|
||||
final String tableName = nameNormalizer.normalizeIdentifierQuoting( col.table() );
|
||||
final String columnName = nameNormalizer.normalizeIdentifierQuoting( col.name() );
|
||||
Ejb3Column column = new Ejb3Column();
|
||||
column.setImplicit( false );
|
||||
column.setSqlType( sqlType );
|
||||
column.setLength( col.length() );
|
||||
column.setPrecision( col.precision() );
|
||||
column.setScale( col.scale() );
|
||||
column.setLogicalColumnName( col.name() );
|
||||
//support for explicit property name + suffix
|
||||
if ( StringHelper.isEmpty( column.getLogicalColumnName() )
|
||||
&& ! StringHelper.isEmpty( suffixForDefaultColumnName ) ) {
|
||||
if ( StringHelper.isEmpty( columnName ) && ! StringHelper.isEmpty( suffixForDefaultColumnName ) ) {
|
||||
column.setLogicalColumnName( inferredData.getPropertyName() + suffixForDefaultColumnName );
|
||||
}
|
||||
else {
|
||||
column.setLogicalColumnName( columnName );
|
||||
}
|
||||
|
||||
column.setPropertyName(
|
||||
BinderHelper.getRelativePath( propertyHolder, inferredData.getPropertyName() )
|
||||
|
@ -418,7 +440,7 @@ public class Ejb3Column {
|
|||
column.setUnique( col.unique() );
|
||||
column.setInsertable( col.insertable() );
|
||||
column.setUpdatable( col.updatable() );
|
||||
column.setSecondaryTableName( col.table() );
|
||||
column.setSecondaryTableName( tableName );
|
||||
column.setPropertyHolder( propertyHolder );
|
||||
column.setJoins( secondaryTables );
|
||||
column.setMappings( mappings );
|
||||
|
@ -436,12 +458,11 @@ public class Ejb3Column {
|
|||
Map<String, Join> secondaryTables,
|
||||
PropertyHolder propertyHolder,
|
||||
Nullability nullability,
|
||||
ExtendedMappings mappings
|
||||
) {
|
||||
Ejb3Column[] columns;
|
||||
columns = new Ejb3Column[1];
|
||||
ExtendedMappings mappings) {
|
||||
Ejb3Column column = new Ejb3Column();
|
||||
column.setImplicit( false );
|
||||
Ejb3Column[] columns = new Ejb3Column[1];
|
||||
columns[0] = column;
|
||||
|
||||
//not following the spec but more clean
|
||||
if ( nullability != Nullability.FORCED_NULL
|
||||
&& inferredData.getClassOrElement().isPrimitive()
|
||||
|
@ -466,7 +487,6 @@ public class Ejb3Column {
|
|||
column.setImplicit( true );
|
||||
}
|
||||
column.bind();
|
||||
columns[0] = column;
|
||||
return columns;
|
||||
}
|
||||
|
||||
|
|
|
@ -332,8 +332,14 @@ public class Ejb3JoinColumn extends Ejb3Column {
|
|||
columnDefinition = joinAnn.columnDefinition();
|
||||
referencedColumnName = joinAnn.referencedColumnName();
|
||||
}
|
||||
String sqlType = "".equals( columnDefinition ) ? null : columnDefinition;
|
||||
String name = "".equals( colName ) ? defaultName : colName;
|
||||
|
||||
String sqlType = "".equals( columnDefinition )
|
||||
? null
|
||||
: mappings.getObjectNameNormalizer().normalizeIdentifierQuoting( columnDefinition );
|
||||
String name = "".equals( colName )
|
||||
? defaultName
|
||||
: colName;
|
||||
name = mappings.getObjectNameNormalizer().normalizeIdentifierQuoting( name );
|
||||
return new Ejb3JoinColumn(
|
||||
sqlType,
|
||||
name, false, false,
|
||||
|
@ -344,6 +350,7 @@ public class Ejb3JoinColumn extends Ejb3Column {
|
|||
);
|
||||
}
|
||||
else {
|
||||
defaultName = mappings.getObjectNameNormalizer().normalizeIdentifierQuoting( defaultName );
|
||||
return new Ejb3JoinColumn(
|
||||
(String) null, defaultName,
|
||||
false, false, true, true, null, (String) null,
|
||||
|
|
|
@ -48,7 +48,6 @@ import org.hibernate.mapping.PersistentClass;
|
|||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.mapping.ToOne;
|
||||
import org.hibernate.mapping.Value;
|
||||
import org.hibernate.util.CollectionHelper;
|
||||
import org.hibernate.util.StringHelper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -78,9 +77,8 @@ public class ResultsetMappingSecondPass implements QuerySecondPass {
|
|||
|
||||
for (EntityResult entity : ann.entities()) {
|
||||
//TODO parameterize lock mode?
|
||||
List properties = new ArrayList();
|
||||
List propertyNames = new ArrayList();
|
||||
Map propertyresults = new HashMap();
|
||||
List<FieldResult> properties = new ArrayList<FieldResult>();
|
||||
List<String> propertyNames = new ArrayList<String>();
|
||||
for (FieldResult field : entity.fields()) {
|
||||
//use an ArrayList cause we might have several columns per root property
|
||||
String name = field.name();
|
||||
|
@ -120,18 +118,16 @@ public class ResultsetMappingSecondPass implements QuerySecondPass {
|
|||
}
|
||||
}
|
||||
|
||||
Set uniqueReturnProperty = new HashSet();
|
||||
Iterator iterator = properties.iterator();
|
||||
while ( iterator.hasNext() ) {
|
||||
FieldResult propertyresult = (FieldResult) iterator.next();
|
||||
String name = propertyresult.name();
|
||||
Set<String> uniqueReturnProperty = new HashSet<String>();
|
||||
Map<String, ArrayList<String>> propertyResultsTmp = new HashMap<String, ArrayList<String>>();
|
||||
for ( Object property : properties ) {
|
||||
final FieldResult propertyresult = ( FieldResult ) property;
|
||||
final String name = propertyresult.name();
|
||||
if ( "class".equals( name ) ) {
|
||||
throw new MappingException(
|
||||
"class is not a valid property name to use in a @FieldResult, use @Entity(discriminatorColumn) instead"
|
||||
);
|
||||
}
|
||||
ArrayList allResultColumns = new ArrayList();
|
||||
allResultColumns.add( propertyresult.column() );
|
||||
|
||||
if ( uniqueReturnProperty.contains( name ) ) {
|
||||
throw new MappingException(
|
||||
|
@ -140,38 +136,56 @@ public class ResultsetMappingSecondPass implements QuerySecondPass {
|
|||
);
|
||||
}
|
||||
uniqueReturnProperty.add( name );
|
||||
|
||||
final String quotingNormalizedColumnName = mappings.getObjectNameNormalizer()
|
||||
.normalizeIdentifierQuoting( propertyresult.column() );
|
||||
|
||||
String key = StringHelper.root( name );
|
||||
ArrayList intermediateResults = (ArrayList) propertyresults.get( key );
|
||||
ArrayList<String> intermediateResults = propertyResultsTmp.get( key );
|
||||
if ( intermediateResults == null ) {
|
||||
propertyresults.put( key, allResultColumns );
|
||||
}
|
||||
else {
|
||||
intermediateResults.addAll( allResultColumns );
|
||||
intermediateResults = new ArrayList<String>();
|
||||
propertyResultsTmp.put( key, intermediateResults );
|
||||
}
|
||||
intermediateResults.add( quotingNormalizedColumnName );
|
||||
}
|
||||
Iterator entries = propertyresults.entrySet().iterator();
|
||||
while ( entries.hasNext() ) {
|
||||
Map.Entry entry = (Map.Entry) entries.next();
|
||||
if ( entry.getValue() instanceof ArrayList ) {
|
||||
ArrayList list = (ArrayList) entry.getValue();
|
||||
entry.setValue( list.toArray( new String[list.size()] ) );
|
||||
}
|
||||
|
||||
Map<String, String[]> propertyResults = new HashMap<String,String[]>();
|
||||
for ( Map.Entry<String, ArrayList<String>> entry : propertyResultsTmp.entrySet() ) {
|
||||
propertyResults.put(
|
||||
entry.getKey(),
|
||||
entry.getValue().toArray( new String[ entry.getValue().size() ] )
|
||||
);
|
||||
}
|
||||
|
||||
if ( !BinderHelper.isDefault( entity.discriminatorColumn() ) ) {
|
||||
propertyresults.put( "class", new String[] { entity.discriminatorColumn() } );
|
||||
final String quotingNormalizedName = mappings.getObjectNameNormalizer().normalizeIdentifierQuoting(
|
||||
entity.discriminatorColumn()
|
||||
);
|
||||
propertyResults.put( "class", new String[] { quotingNormalizedName } );
|
||||
}
|
||||
|
||||
propertyresults = propertyresults.isEmpty() ? CollectionHelper.EMPTY_MAP : propertyresults;
|
||||
NativeSQLQueryRootReturn result =
|
||||
new NativeSQLQueryRootReturn(
|
||||
"alias" + entityAliasIndex++, entity.entityClass().getName(), propertyresults, LockMode.READ
|
||||
);
|
||||
if ( propertyResults.isEmpty() ) {
|
||||
propertyResults = java.util.Collections.emptyMap();
|
||||
}
|
||||
|
||||
NativeSQLQueryRootReturn result = new NativeSQLQueryRootReturn(
|
||||
"alias" + entityAliasIndex++,
|
||||
entity.entityClass().getName(),
|
||||
propertyResults,
|
||||
LockMode.READ
|
||||
);
|
||||
definition.addQueryReturn( result );
|
||||
}
|
||||
|
||||
for (ColumnResult column : ann.columns()) {
|
||||
definition.addQueryReturn( new NativeSQLQueryScalarReturn( column.name(), null ) );
|
||||
for ( ColumnResult column : ann.columns() ) {
|
||||
definition.addQueryReturn(
|
||||
new NativeSQLQueryScalarReturn(
|
||||
mappings.getObjectNameNormalizer().normalizeIdentifierQuoting(
|
||||
column.name()
|
||||
),
|
||||
null
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if ( isDefault ) {
|
||||
|
@ -182,6 +196,7 @@ public class ResultsetMappingSecondPass implements QuerySecondPass {
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
private List getFollowers(Iterator parentPropIter, String reducedName, String name) {
|
||||
boolean hasFollowers = false;
|
||||
List followers = new ArrayList();
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Middleware LLC.
|
||||
* 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
|
||||
|
@ -20,7 +20,6 @@
|
|||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
package org.hibernate;
|
||||
|
||||
|
|
|
@ -2451,12 +2451,14 @@ public class Configuration implements Serializable {
|
|||
String name,
|
||||
String subselect,
|
||||
boolean isAbstract) {
|
||||
name = getObjectNameNormalizer().normalizeIdentifierQuoting( name );
|
||||
schema = getObjectNameNormalizer().normalizeIdentifierQuoting( schema );
|
||||
catalog = getObjectNameNormalizer().normalizeIdentifierQuoting( catalog );
|
||||
|
||||
String key = subselect == null ? Table.qualify( catalog, schema, name ) : subselect;
|
||||
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 );
|
||||
|
@ -2481,14 +2483,15 @@ public class Configuration implements Serializable {
|
|||
boolean isAbstract,
|
||||
String subselect,
|
||||
Table includedTable) throws DuplicateMappingException {
|
||||
name = getObjectNameNormalizer().normalizeIdentifierQuoting( name );
|
||||
schema = getObjectNameNormalizer().normalizeIdentifierQuoting( schema );
|
||||
catalog = getObjectNameNormalizer().normalizeIdentifierQuoting( catalog );
|
||||
|
||||
String key = subselect == null ? Table.qualify(catalog, schema, name) : subselect;
|
||||
if ( tables.containsKey( key ) ) {
|
||||
throw new DuplicateMappingException( "table", name );
|
||||
}
|
||||
|
||||
schema = getObjectNameNormalizer().normalizeIdentifierQuoting( schema );
|
||||
catalog = getObjectNameNormalizer().normalizeIdentifierQuoting( catalog );
|
||||
|
||||
Table table = new DenormalizedTable( includedTable );
|
||||
table.setAbstract( isAbstract );
|
||||
table.setName( name );
|
||||
|
|
|
@ -100,8 +100,12 @@ public abstract class Constraint implements RelationalModel, Serializable {
|
|||
|
||||
public String sqlDropString(Dialect dialect, String defaultCatalog, String defaultSchema) {
|
||||
if ( isGenerated( dialect ) ) {
|
||||
return "alter table " + getTable()
|
||||
.getQualifiedName( dialect, defaultCatalog, defaultSchema ) + " drop constraint " + getName();
|
||||
return new StringBuffer()
|
||||
.append( "alter table " )
|
||||
.append( getTable().getQualifiedName( dialect, defaultCatalog, defaultSchema ) )
|
||||
.append( " drop constraint " )
|
||||
.append( dialect.quote( getName() ) )
|
||||
.toString();
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
|
|
|
@ -39,22 +39,29 @@ public class UniqueKey extends Constraint {
|
|||
|
||||
public String sqlConstraintString(Dialect dialect) {
|
||||
StringBuffer buf = new StringBuffer( "unique (" );
|
||||
boolean hadNullableColumn = false;
|
||||
Iterator iter = getColumnIterator();
|
||||
boolean nullable = false;
|
||||
while ( iter.hasNext() ) {
|
||||
Column column = (Column) iter.next();
|
||||
if ( !nullable && column.isNullable() ) nullable = true;
|
||||
if ( !hadNullableColumn && column.isNullable() ) {
|
||||
hadNullableColumn = true;
|
||||
}
|
||||
buf.append( column.getQuotedName( dialect ) );
|
||||
if ( iter.hasNext() ) buf.append( ", " );
|
||||
if ( iter.hasNext() ) {
|
||||
buf.append( ", " );
|
||||
}
|
||||
}
|
||||
//do not add unique constraint on DB not supporting unique and nullable columns
|
||||
return !nullable || dialect.supportsNotNullUnique() ?
|
||||
return !hadNullableColumn || dialect.supportsNotNullUnique() ?
|
||||
buf.append( ')' ).toString() :
|
||||
null;
|
||||
}
|
||||
|
||||
public String sqlConstraintString(Dialect dialect, String constraintName, String defaultCatalog,
|
||||
String defaultSchema) {
|
||||
public String sqlConstraintString(
|
||||
Dialect dialect,
|
||||
String constraintName,
|
||||
String defaultCatalog,
|
||||
String defaultSchema) {
|
||||
StringBuffer buf = new StringBuffer(
|
||||
dialect.getAddPrimaryKeyConstraintString( constraintName )
|
||||
).append( '(' );
|
||||
|
|
|
@ -188,6 +188,9 @@ public class Ejb3Configuration implements Serializable, Referenceable {
|
|||
this.setProperty( Environment.DATASOURCE, metadata.getNonJtaDatasource() );
|
||||
}
|
||||
defineTransactionType( metadata.getTransactionType(), workingVars );
|
||||
if ( metadata.isUseQuotedIdentifiers() ) {
|
||||
this.setProperty( Environment.GLOBALLY_QUOTED_IDENTIFIERS, "true" );
|
||||
}
|
||||
if ( metadata.getClasses().size() > 0 ) {
|
||||
workingVars.put( HibernatePersistence.CLASS_NAMES, metadata.getClasses() );
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@ public class PersistenceMetadata {
|
|||
private String jtaDatasource;
|
||||
private String provider;
|
||||
private PersistenceUnitTransactionType transactionType;
|
||||
private boolean useQuotedIdentifiers = false; // the spec (erroneously?) calls this delimited-identifiers
|
||||
private List<String> classes = new ArrayList<String>();
|
||||
private List<String> packages = new ArrayList<String>();
|
||||
private List<String> mappingFiles = new ArrayList<String>();
|
||||
|
@ -94,6 +95,14 @@ public class PersistenceMetadata {
|
|||
this.provider = provider;
|
||||
}
|
||||
|
||||
public boolean isUseQuotedIdentifiers() {
|
||||
return useQuotedIdentifiers;
|
||||
}
|
||||
|
||||
public void setUseQuotedIdentifiers(boolean useQuotedIdentifiers) {
|
||||
this.useQuotedIdentifiers = useQuotedIdentifiers;
|
||||
}
|
||||
|
||||
public List<String> getClasses() {
|
||||
return classes;
|
||||
}
|
||||
|
@ -162,6 +171,7 @@ public class PersistenceMetadata {
|
|||
.append("\tnonJtaDataSource: ").append(nonJtaDatasource).append("\n")
|
||||
.append("\ttransactionType: ").append(transactionType).append("\n")
|
||||
.append("\tprovider: ").append(provider).append("\n")
|
||||
.append("\tuseQuotedIdentifiers: ").append(useQuotedIdentifiers).append("\n")
|
||||
.append("\tclasses[\n");
|
||||
if (classes != null) {
|
||||
for (String elt : classes) {
|
||||
|
|
|
@ -209,6 +209,9 @@ public final class PersistenceXmlLoader {
|
|||
else if ( tag.equals( "exclude-unlisted-classes" ) ) {
|
||||
metadata.setExcludeUnlistedClasses( true );
|
||||
}
|
||||
else if ( tag.equals( "delimited-identifiers" ) ) {
|
||||
metadata.setUseQuotedIdentifiers( true );
|
||||
}
|
||||
else if ( tag.equals( "properties" ) ) {
|
||||
NodeList props = element.getChildNodes();
|
||||
for ( int j = 0; j < props.getLength() ; j++ ) {
|
||||
|
|
Loading…
Reference in New Issue