HHH-8897 : Integrate org.hibernate.metamodel from metamodel branch into master
This commit is contained in:
parent
1a87adca08
commit
513f8ca869
|
@ -137,6 +137,7 @@ subprojects { subProject ->
|
|||
dependencies {
|
||||
compile( libraries.logging )
|
||||
compile( libraries.logging_annotations )
|
||||
compile( libraries.logging_processor )
|
||||
|
||||
testCompile( libraries.junit )
|
||||
testCompile( libraries.byteman )
|
||||
|
@ -152,8 +153,11 @@ subprojects { subProject ->
|
|||
jaxb( libraries.jaxb ){
|
||||
exclude group: "javax.xml.stream"
|
||||
}
|
||||
jaxb( libraries.jaxb )
|
||||
jaxb( libraries.jaxb2_basics )
|
||||
jaxb( libraries.jaxb2_ant )
|
||||
jaxb( libraries.jaxb2_jaxb )
|
||||
jaxb( libraries.jaxb2_jaxb_xjc )
|
||||
|
||||
animalSniffer ( libraries.animal_sniffer )
|
||||
javaApiSignature ( libraries.java16_signature )
|
||||
|
|
|
@ -10,6 +10,7 @@ versionInjection {
|
|||
dependencies {
|
||||
compile( libraries.jta )
|
||||
compile( libraries.dom4j )
|
||||
compile( libraries.classmate )
|
||||
compile( libraries.commons_annotations )
|
||||
compile( libraries.jpa )
|
||||
compile( libraries.javassist )
|
||||
|
@ -21,7 +22,6 @@ dependencies {
|
|||
provided( libraries.ant )
|
||||
provided( libraries.jacc )
|
||||
provided( libraries.validation )
|
||||
provided( libraries.classmate )
|
||||
|
||||
testCompile( project(':hibernate-testing') )
|
||||
testCompile( libraries.validation )
|
||||
|
@ -111,7 +111,7 @@ task jaxb {
|
|||
// input schemas
|
||||
cfgXsd = file( 'src/main/resources/org/hibernate/hibernate-configuration-4.0.xsd')
|
||||
hbmXsd = file( 'src/main/resources/org/hibernate/hibernate-mapping-4.0.xsd' )
|
||||
ormXsd = file( 'src/main/resources/org/hibernate/jpa/orm_2_0.xsd' )
|
||||
ormXsd = file( 'src/main/resources/org/hibernate/jpa/orm_2_1.xsd' )
|
||||
|
||||
// input bindings
|
||||
cfgXjb = file( 'src/main/xjb/hbm-configuration-bindings.xjb' )
|
||||
|
@ -133,7 +133,7 @@ task jaxb {
|
|||
// hibernate-configuration
|
||||
ant.xjc(
|
||||
destdir: '${jaxbTargetDir}',
|
||||
package: 'org.hibernate.internal.jaxb.cfg',
|
||||
package: 'org.hibernate.jaxb.spi.cfg',
|
||||
binding: 'src/main/xjb/hbm-configuration-bindings.xjb',
|
||||
schema: cfgXsd.path
|
||||
)
|
||||
|
@ -141,21 +141,25 @@ task jaxb {
|
|||
// hibernate-mapping
|
||||
ant.xjc(
|
||||
destdir: '${jaxbTargetDir}',
|
||||
package: 'org.hibernate.internal.jaxb.mapping.hbm',
|
||||
package: 'org.hibernate.jaxb.spi.hbm',
|
||||
binding: hbmXjb.path,
|
||||
schema: hbmXsd.path,
|
||||
extension: 'true'
|
||||
) {
|
||||
arg line: '-Xinheritance'
|
||||
arg line: '-Xinheritance -Xsimplify'
|
||||
}
|
||||
|
||||
// orm.xml (jpa)
|
||||
ant.xjc(
|
||||
destdir: '${jaxbTargetDir}',
|
||||
package: 'org.hibernate.internal.jaxb.mapping.orm',
|
||||
package: 'org.hibernate.jaxb.spi.orm',
|
||||
binding: 'src/main/xjb/orm-bindings.xjb',
|
||||
schema: ormXsd.path
|
||||
)
|
||||
schema: ormXsd.path,
|
||||
extension: 'true'
|
||||
) {
|
||||
arg line: '-Xinheritance'
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
*/
|
||||
package org.hibernate;
|
||||
|
||||
import org.hibernate.internal.jaxb.Origin;
|
||||
import org.hibernate.jaxb.spi.Origin;
|
||||
import org.hibernate.internal.util.xml.XmlDocument;
|
||||
|
||||
/**
|
||||
|
|
|
@ -30,6 +30,8 @@ import java.util.Set;
|
|||
import javax.naming.Referenceable;
|
||||
|
||||
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||
import org.hibernate.cfg.Settings;
|
||||
import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
|
||||
import org.hibernate.engine.spi.FilterDefinition;
|
||||
import org.hibernate.metadata.ClassMetadata;
|
||||
import org.hibernate.metadata.CollectionMetadata;
|
||||
|
@ -71,6 +73,12 @@ public interface SessionFactory extends Referenceable, Serializable {
|
|||
*/
|
||||
public Interceptor getInterceptor();
|
||||
|
||||
public CustomEntityDirtinessStrategy getCustomEntityDirtinessStrategy();
|
||||
public CurrentTenantIdentifierResolver getCurrentTenantIdentifierResolver();
|
||||
public SessionFactoryObserver[] getSessionFactoryObservers();
|
||||
public EntityNameResolver[] getEntityNameResolvers();
|
||||
public Settings getSettings();
|
||||
|
||||
/**
|
||||
* Get the delegate for handling entity-not-found exception conditions.
|
||||
*
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, Red Hat Inc. 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 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;
|
||||
|
||||
/**
|
||||
* An enumeration of truth values.
|
||||
* <p/>
|
||||
* Yes this *could* be handled with Boolean, but then you run into potential problems with premature
|
||||
* auto-unboxing.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public enum TruthValue {
|
||||
TRUE,
|
||||
FALSE,
|
||||
UNKNOWN;
|
||||
|
||||
public static boolean toBoolean(TruthValue value, boolean defaultValue) {
|
||||
if ( value == TruthValue.TRUE ) {
|
||||
return true;
|
||||
}
|
||||
if ( value == TruthValue.FALSE ) {
|
||||
return false;
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, Red Hat Inc. 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 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.annotations;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
/**
|
||||
* Annotation used to indicate that an entity represents shared (non tenant aware) data in a multi-tenant
|
||||
* application.
|
||||
*
|
||||
* Valid only at the root of an inheritance hierarchy.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@java.lang.annotation.Target(TYPE)
|
||||
@Retention(RUNTIME)
|
||||
public @interface MultiTenancy {
|
||||
public boolean shared() default true;
|
||||
|
||||
/**
|
||||
* The discriminator values can be either be handled as literals or handled through JDBC parameter binding.
|
||||
* {@code true} here (the default) indicates that the parameter binding approach should be used; {@code false}
|
||||
* indicates the value should be handled as a literal.
|
||||
* <p/>
|
||||
* Care should be used specifying to use literals here. PreparedStatements will not be able to be reused
|
||||
* nearly as often by the database/driver which can potentially cause a significant performance impact to your
|
||||
* application.
|
||||
*/
|
||||
public boolean useParameterBinding() default true;
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, Red Hat Inc. 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 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.annotations;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
/**
|
||||
* Describes the column to use as the multi-tenancy discriminator value for the entity.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@java.lang.annotation.Target( TYPE )
|
||||
@Retention( RUNTIME )
|
||||
public @interface TenantColumn {
|
||||
/**
|
||||
* Name of the column to use.
|
||||
*/
|
||||
public String name();
|
||||
|
||||
/**
|
||||
* (Optional) The name of the table that contains the column. If absent the column is assumed to be in the
|
||||
* primary table.
|
||||
*/
|
||||
public String table() default "";
|
||||
|
||||
/**
|
||||
* Names the Hibernate mapping type to use for mapping values to/from the specified column. Defaults to
|
||||
* {@code "string"} which is a {@link String}/{@link java.sql.Types#VARCHAR VARCHAR} mapping.
|
||||
*/
|
||||
public String type() default "string";
|
||||
|
||||
/**
|
||||
* (Optional) The column length. (Applies only if a string-valued column is used.)
|
||||
*/
|
||||
int length() default 255;
|
||||
|
||||
/**
|
||||
* (Optional) The precision for a decimal (exact numeric) column. (Applies only if a decimal column is used.)
|
||||
* Value must be set by developer if used when generating the DDL for the column.
|
||||
*/
|
||||
int precision() default 0;
|
||||
|
||||
/**
|
||||
* (Optional) The scale for a decimal (exact numeric) column. (Applies only if a decimal column is used.)
|
||||
*/
|
||||
int scale() default 0;
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, Red Hat Inc. 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 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.annotations;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
/**
|
||||
* Describes a formula fragment to use as the multi-tenancy discriminator value for the entity.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
* @see Formula
|
||||
*/
|
||||
@java.lang.annotation.Target(TYPE)
|
||||
@Retention(RUNTIME)
|
||||
public @interface TenantFormula {
|
||||
/**
|
||||
* The formula fragment.
|
||||
*/
|
||||
public String value();
|
||||
}
|
|
@ -34,7 +34,7 @@ import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl;
|
|||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.integrator.spi.Integrator;
|
||||
import org.hibernate.integrator.spi.IntegratorService;
|
||||
import org.hibernate.internal.jaxb.cfg.JaxbHibernateConfiguration;
|
||||
import org.hibernate.jaxb.spi.cfg.JaxbHibernateConfiguration;
|
||||
import org.hibernate.internal.util.config.ConfigurationHelper;
|
||||
import org.hibernate.service.ConfigLoader;
|
||||
import org.hibernate.service.Service;
|
||||
|
|
|
@ -140,7 +140,8 @@ public class StrategySelectorBuilder {
|
|||
throw new StrategySelectionException(
|
||||
"Implementation class [" + strategyRegistration.getStrategyImplementation().getName()
|
||||
+ "] does not implement strategy interface ["
|
||||
+ strategyRegistration.getStrategyRole().getName() + "]"
|
||||
+ strategyRegistration.getStrategyRole().getName() + "]",
|
||||
strategyRegistration.getStrategyImplementation().getName()
|
||||
);
|
||||
}
|
||||
explicitStrategyRegistrations.add( strategyRegistration );
|
||||
|
|
|
@ -126,7 +126,8 @@ public class StrategySelectorImpl implements StrategySelector {
|
|||
}
|
||||
catch (ClassLoadingException e) {
|
||||
throw new StrategySelectionException(
|
||||
"Unable to resolve name [" + name + "] as strategy [" + strategy.getName() + "]"
|
||||
"Unable to resolve name [" + name + "] as strategy [" + strategy.getName() + "]",
|
||||
name
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -161,7 +162,8 @@ public class StrategySelectorImpl implements StrategySelector {
|
|||
catch (Exception e) {
|
||||
throw new StrategySelectionException(
|
||||
String.format( "Could not instantiate named strategy class [%s]", implementationClass.getName() ),
|
||||
e
|
||||
e,
|
||||
implementationClass.getName()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,13 +31,16 @@ import org.hibernate.HibernateException;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class StrategySelectionException extends HibernateException {
|
||||
|
||||
private final String implementationClassName;
|
||||
/**
|
||||
* Constructs a StrategySelectionException using the specified message.
|
||||
*
|
||||
* @param message A message explaining the exception condition.
|
||||
*/
|
||||
public StrategySelectionException(String message) {
|
||||
public StrategySelectionException(String message, String implementationClassName) {
|
||||
super( message );
|
||||
this.implementationClassName = implementationClassName;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -46,7 +49,17 @@ public class StrategySelectionException extends HibernateException {
|
|||
* @param message A message explaining the exception condition.
|
||||
* @param cause The underlying cause.
|
||||
*/
|
||||
public StrategySelectionException(String message, Throwable cause) {
|
||||
public StrategySelectionException(String message, Throwable cause, String implementationClassName) {
|
||||
super( message, cause );
|
||||
this.implementationClassName = implementationClassName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the selected implementation class involved with the exception.
|
||||
*
|
||||
* @return the implementation class name.
|
||||
*/
|
||||
public String getImplementationClassName() {
|
||||
return implementationClassName;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, Red Hat Inc. 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 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.boot.spi;
|
||||
|
||||
/**
|
||||
* Models the definition of caching settings for a particular region. Generally as found in either:<ul>
|
||||
* <li>{@code cfg.xml}</li>
|
||||
* <li>{@code hbm.xml}</li>
|
||||
* <li>annotation</li>
|
||||
* </ul>
|
||||
* Though certainly other custom sources are acceptable too.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class CacheRegionDefinition {
|
||||
public static enum CacheRegionType {
|
||||
ENTITY,
|
||||
COLLECTION,
|
||||
QUERY
|
||||
}
|
||||
|
||||
private final CacheRegionType regionType;
|
||||
private final String role;
|
||||
private final String usage;
|
||||
private final String region;
|
||||
private final boolean cacheLazy;
|
||||
|
||||
public CacheRegionDefinition(
|
||||
CacheRegionType cacheType,
|
||||
String role,
|
||||
String usage,
|
||||
String region,
|
||||
boolean cacheLazy) {
|
||||
this.regionType = cacheType;
|
||||
this.role = role;
|
||||
this.usage = usage;
|
||||
this.region = region;
|
||||
this.cacheLazy = cacheLazy;
|
||||
}
|
||||
|
||||
public CacheRegionType getRegionType() {
|
||||
return regionType;
|
||||
}
|
||||
|
||||
public String getRole() {
|
||||
return role;
|
||||
}
|
||||
|
||||
public String getUsage() {
|
||||
return usage;
|
||||
}
|
||||
|
||||
public String getRegion() {
|
||||
return region;
|
||||
}
|
||||
|
||||
public boolean isCacheLazy() {
|
||||
return cacheLazy;
|
||||
}
|
||||
}
|
|
@ -28,8 +28,8 @@ import java.util.Comparator;
|
|||
import org.hibernate.cache.spi.CacheDataDescription;
|
||||
import org.hibernate.mapping.Collection;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.metamodel.binding.EntityBinding;
|
||||
import org.hibernate.metamodel.binding.PluralAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.EntityBinding;
|
||||
import org.hibernate.metamodel.spi.binding.PluralAttributeBinding;
|
||||
import org.hibernate.type.VersionType;
|
||||
|
||||
/**
|
||||
|
@ -134,7 +134,7 @@ public class CacheDataDescriptionImpl implements CacheDataDescription {
|
|||
private static Comparator getVersionComparator(EntityBinding model ) {
|
||||
if ( model.isVersioned() ) {
|
||||
final VersionType versionType = (VersionType) model.getHierarchyDetails()
|
||||
.getVersioningAttributeBinding()
|
||||
.getEntityVersion().getVersioningAttributeBinding()
|
||||
.getHibernateTypeDescriptor()
|
||||
.getResolvedTypeMapping();
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ import org.hibernate.event.spi.PostInsertEventListener;
|
|||
import org.hibernate.event.spi.PostUpdateEvent;
|
||||
import org.hibernate.event.spi.PostUpdateEventListener;
|
||||
import org.hibernate.integrator.spi.Integrator;
|
||||
import org.hibernate.metamodel.source.MetadataImplementor;
|
||||
import org.hibernate.metamodel.spi.MetadataImplementor;
|
||||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.service.spi.SessionFactoryServiceRegistry;
|
||||
|
|
|
@ -636,7 +636,51 @@ public interface AvailableSettings {
|
|||
*/
|
||||
String IGNORE_EXPLICIT_DISCRIMINATOR_COLUMNS_FOR_JOINED_SUBCLASS = "hibernate.discriminator.ignore_explicit_for_joined";
|
||||
|
||||
String ENABLE_LAZY_LOAD_NO_TRANS = "hibernate.enable_lazy_load_no_trans";
|
||||
/**
|
||||
* Names a {@link org.hibernate.Interceptor} implementation to be applied to the {@link org.hibernate.SessionFactory}
|
||||
* Can reference<ul>
|
||||
* <li>Interceptor instance</li>
|
||||
* <li>Interceptor implementation {@link Class} reference</li>
|
||||
* <li>Interceptor implementation class name</li>
|
||||
* </ul>
|
||||
*
|
||||
* @since 5.0
|
||||
*/
|
||||
String INTERCEPTOR = "hibernate.sessionFactory.interceptor";
|
||||
|
||||
/**
|
||||
* Setting that controls whether we seek out JPA "static metamodel" classes and populate them. Accepts
|
||||
* 3 values:<ul>
|
||||
* <li>
|
||||
* <b>enabled</b> - Do the population
|
||||
* </li>
|
||||
* <li>
|
||||
* <b>disabled</b> - Do not do the population
|
||||
* </li>
|
||||
* <li>
|
||||
* <b>ignoreUnsupported</b> - Do the population, but ignore any non-JPA features that would otherwise
|
||||
* result in the population failing.
|
||||
* </li>
|
||||
* </ul>
|
||||
*/
|
||||
public static final String JPA_METAMODEL_POPULATION = "hibernate.ejb.metamodel.population";
|
||||
|
||||
/**
|
||||
* Used to specify the {@link org.hibernate.tool.schema.spi.SchemaManagementTool} to use for performing
|
||||
* schema management. The default is to use {@link org.hibernate.tool.schema.internal.HibernateSchemaManagementTool}
|
||||
*
|
||||
* @since 5.0
|
||||
*/
|
||||
String SCHEMA_MANAGEMENT_TOOL = "hibernate.schema_management_tool";
|
||||
|
||||
/**
|
||||
* A constant naming the setting used to identify the {@link org.hibernate.engine.jdbc.spi.SchemaNameResolver} to use
|
||||
* <p/>
|
||||
* TODO : add to Environment
|
||||
*/
|
||||
String SCHEMA_NAME_RESOLVER = "hibernate.schema_name_resolver";
|
||||
|
||||
String ENABLE_LAZY_LOAD_NO_TRANS = "hibernate.enable_lazy_load_no_trans";
|
||||
|
||||
String HQL_BULK_ID_STRATEGY = "hibernate.hql.bulk_id_strategy";
|
||||
|
||||
|
@ -701,6 +745,15 @@ public interface AvailableSettings {
|
|||
*/
|
||||
String UNIQUE_CONSTRAINT_SCHEMA_UPDATE_STRATEGY = "hibernate.schema_update.unique_constraint_strategy";
|
||||
|
||||
/**
|
||||
* If enabled, an entity's member field types and method return types will automatically be indexed. This allows,
|
||||
* for example, auto-discovery of @Embeddables without explicitly listing them in the annotated classes. This
|
||||
* setting will also check classes identified by certain annotations (such as @Target). JPA requires these classes
|
||||
* to be identified in the annotated classes, however legacy Hibernate behavior was to allow it. Due to the
|
||||
* performance hit, disabled by default.
|
||||
*/
|
||||
String ENABLE_AUTO_INDEX_MEMBER_TYPES = "hibernate.enable_auto_index_member_types";
|
||||
|
||||
/**
|
||||
* A setting to control whether to {@link org.hibernate.engine.internal.StatisticalLoggingSessionEventListener} is
|
||||
* enabled on all Sessions (unless explicitly disabled for a given Session). The default value of this
|
||||
|
|
|
@ -24,9 +24,12 @@
|
|||
package org.hibernate.cfg;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.metamodel.internal.HashedNameUtil;
|
||||
|
||||
/**
|
||||
* The default <tt>NamingStrategy</tt>
|
||||
|
@ -93,6 +96,22 @@ public class DefaultNamingStrategy implements NamingStrategy, Serializable {
|
|||
if (header == null) throw new AssertionFailure("NammingStrategy not properly filled");
|
||||
return columnName( header ); //+ "_" + referencedColumnName not used for backward compatibility
|
||||
}
|
||||
|
||||
public String foreignKeyName(String sourceTableName, List<String> sourceColumnNames,
|
||||
String targetTableName, List<String> targetColumnNames) {
|
||||
List<String> combinedColumnNames = new ArrayList<String>();
|
||||
combinedColumnNames.addAll( sourceColumnNames );
|
||||
combinedColumnNames.addAll( targetColumnNames );
|
||||
return HashedNameUtil.generateName( "FK_", sourceTableName + "_" + targetTableName, combinedColumnNames );
|
||||
}
|
||||
|
||||
public String uniqueKeyName(String tableName, List<String> columnNames) {
|
||||
return HashedNameUtil.generateName( "UK_", tableName, columnNames );
|
||||
}
|
||||
|
||||
public String indexName(String tableName, List<String> columnNames) {
|
||||
return HashedNameUtil.generateName( "IDX_", tableName, columnNames );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the column name or the unqualified property name
|
||||
|
|
|
@ -23,9 +23,12 @@
|
|||
*/
|
||||
package org.hibernate.cfg;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.metamodel.internal.HashedNameUtil;
|
||||
|
||||
/**
|
||||
* Naming strategy implementing the EJB3 standards
|
||||
|
@ -76,6 +79,22 @@ public class EJB3NamingStrategy implements NamingStrategy, Serializable {
|
|||
if ( header == null ) throw new AssertionFailure( "NamingStrategy not properly filled" );
|
||||
return columnName( header + "_" + referencedColumnName );
|
||||
}
|
||||
|
||||
public String foreignKeyName(String sourceTableName, List<String> sourceColumnNames,
|
||||
String targetTableName, List<String> targetColumnNames) {
|
||||
List<String> combinedColumnNames = new ArrayList<String>();
|
||||
combinedColumnNames.addAll( sourceColumnNames );
|
||||
combinedColumnNames.addAll( targetColumnNames );
|
||||
return HashedNameUtil.generateName( "FK_", sourceTableName + "_" + targetTableName, combinedColumnNames );
|
||||
}
|
||||
|
||||
public String uniqueKeyName(String tableName, List<String> columnNames) {
|
||||
return HashedNameUtil.generateName( "UK_", tableName, columnNames );
|
||||
}
|
||||
|
||||
public String indexName(String tableName, List<String> columnNames) {
|
||||
return HashedNameUtil.generateName( "IDX_", tableName, columnNames );
|
||||
}
|
||||
|
||||
public String logicalColumnName(String columnName, String propertyName) {
|
||||
return StringHelper.isNotEmpty( columnName ) ? columnName : StringHelper.unqualify( propertyName );
|
||||
|
|
|
@ -1724,8 +1724,8 @@ public final class HbmBinder {
|
|||
oneToOne.setConstrained( constrained );
|
||||
|
||||
oneToOne.setForeignKeyType( constrained ?
|
||||
ForeignKeyDirection.FOREIGN_KEY_FROM_PARENT :
|
||||
ForeignKeyDirection.FOREIGN_KEY_TO_PARENT );
|
||||
ForeignKeyDirection.FROM_PARENT :
|
||||
ForeignKeyDirection.TO_PARENT );
|
||||
|
||||
initOuterJoinFetchSetting( node, oneToOne );
|
||||
initLaziness( node, oneToOne, mappings, true );
|
||||
|
|
|
@ -24,9 +24,12 @@
|
|||
package org.hibernate.cfg;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.metamodel.internal.HashedNameUtil;
|
||||
|
||||
/**
|
||||
* An improved naming strategy that prefers embedded
|
||||
|
@ -106,6 +109,22 @@ public class ImprovedNamingStrategy implements NamingStrategy, Serializable {
|
|||
if (header == null) throw new AssertionFailure("NamingStrategy not properly filled");
|
||||
return columnName( header ); //+ "_" + referencedColumnName not used for backward compatibility
|
||||
}
|
||||
|
||||
public String foreignKeyName(String sourceTableName, List<String> sourceColumnNames,
|
||||
String targetTableName, List<String> targetColumnNames) {
|
||||
List<String> combinedColumnNames = new ArrayList<String>();
|
||||
combinedColumnNames.addAll( sourceColumnNames );
|
||||
combinedColumnNames.addAll( targetColumnNames );
|
||||
return HashedNameUtil.generateName( "FK_", sourceTableName + "_" + targetTableName, combinedColumnNames );
|
||||
}
|
||||
|
||||
public String uniqueKeyName(String tableName, List<String> columnNames) {
|
||||
return HashedNameUtil.generateName( "UK_", tableName, columnNames );
|
||||
}
|
||||
|
||||
public String indexName(String tableName, List<String> columnNames) {
|
||||
return HashedNameUtil.generateName( "IDX_", tableName, columnNames );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the column name or the unqualified property name
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
*/
|
||||
package org.hibernate.cfg;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* A set of rules for determining the physical column
|
||||
|
@ -37,6 +39,7 @@ package org.hibernate.cfg;
|
|||
* @see ImprovedNamingStrategy
|
||||
* @author Gavin King
|
||||
* @author Emmanuel Bernard
|
||||
* @author Brett Meyer
|
||||
*/
|
||||
public interface NamingStrategy {
|
||||
/**
|
||||
|
@ -93,6 +96,33 @@ public interface NamingStrategy {
|
|||
public String foreignKeyColumnName(
|
||||
String propertyName, String propertyEntityName, String propertyTableName, String referencedColumnName
|
||||
);
|
||||
/**
|
||||
* Return a constraint name for foreign keys that are not explicitly named in the mappings/annotations.
|
||||
*
|
||||
* @param tableName The foreign key's source table
|
||||
* @param columnNames The source columns within the foreign key
|
||||
* @param tableName The foreign key's target table
|
||||
* @param columnNames The target columns within the foreign key
|
||||
* @return The generated foreign key constraint name
|
||||
*/
|
||||
public String foreignKeyName(String sourceTableName, List<String> sourceColumnNames,
|
||||
String targetTableName, List<String> targetColumnNames);
|
||||
/**
|
||||
* Return a constraint name for unique keys that are not explicitly named in the mappings/annotations.
|
||||
*
|
||||
* @param tableName The unique key's table
|
||||
* @param columnNames The columns within the unique key
|
||||
* @return The generated unique key constraint name
|
||||
*/
|
||||
public String uniqueKeyName(String tableName, List<String> columnNames);
|
||||
/**
|
||||
* Return a constraint name for indexes that are not explicitly named in the mappings/annotations.
|
||||
*
|
||||
* @param tableName The index's table
|
||||
* @param columnNames The columns within the index
|
||||
* @return The generated index constraint name
|
||||
*/
|
||||
public String indexName(String tableName, List<String> columnNames);
|
||||
/**
|
||||
* Return the logical column name used to refer to a column in the metadata
|
||||
* (like index, unique constraints etc)
|
||||
|
|
|
@ -56,6 +56,10 @@ public abstract class ObjectNameNormalizer {
|
|||
public String handleExplicitName(NamingStrategy strategy, String name);
|
||||
}
|
||||
|
||||
public static interface LogicalNamingStrategyHelper extends NamingStrategyHelper{
|
||||
public String getLogicalName(NamingStrategy strategy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the actual contract of normalizing a database name.
|
||||
*
|
||||
|
@ -78,7 +82,6 @@ public abstract class ObjectNameNormalizer {
|
|||
// handle any quoting for consistent handling in naming strategies
|
||||
objectName = normalizeIdentifierQuoting( explicitName );
|
||||
objectName = helper.handleExplicitName( getNamingStrategy(), objectName );
|
||||
return normalizeIdentifierQuoting( objectName );
|
||||
}
|
||||
// Conceivable that the naming strategy could return a quoted identifier, or
|
||||
// that user enabled <delimited-identifiers/>
|
||||
|
|
|
@ -106,8 +106,8 @@ public class OneToOneSecondPass implements SecondPass {
|
|||
if ( !optional ) value.setConstrained( true );
|
||||
value.setForeignKeyType(
|
||||
value.isConstrained() ?
|
||||
ForeignKeyDirection.FOREIGN_KEY_FROM_PARENT :
|
||||
ForeignKeyDirection.FOREIGN_KEY_TO_PARENT
|
||||
ForeignKeyDirection.FROM_PARENT :
|
||||
ForeignKeyDirection.TO_PARENT
|
||||
);
|
||||
PropertyBinder binder = new PropertyBinder();
|
||||
binder.setName( propertyName );
|
||||
|
|
|
@ -42,7 +42,7 @@ import org.hibernate.cache.spi.QueryCacheFactory;
|
|||
import org.hibernate.cache.spi.RegionFactory;
|
||||
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
|
||||
import org.hibernate.engine.jdbc.connections.spi.MultiTenantConnectionProvider;
|
||||
import org.hibernate.engine.jdbc.spi.ExtractedDatabaseMetaData;
|
||||
import org.hibernate.engine.jdbc.env.spi.ExtractedDatabaseMetaData;
|
||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||
import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform;
|
||||
import org.hibernate.engine.transaction.spi.TransactionFactory;
|
||||
|
|
|
@ -33,7 +33,7 @@ import org.hibernate.cfg.Configuration;
|
|||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.integrator.spi.Integrator;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.metamodel.source.MetadataImplementor;
|
||||
import org.hibernate.metamodel.spi.MetadataImplementor;
|
||||
import org.hibernate.service.spi.SessionFactoryServiceRegistry;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
|
|
@ -80,6 +80,11 @@ import org.hibernate.internal.util.collections.ArrayHelper;
|
|||
import org.hibernate.internal.util.io.StreamCopier;
|
||||
import org.hibernate.mapping.Column;
|
||||
import org.hibernate.metamodel.spi.TypeContributions;
|
||||
import org.hibernate.metamodel.spi.relational.AuxiliaryDatabaseObject;
|
||||
import org.hibernate.metamodel.spi.relational.ForeignKey;
|
||||
import org.hibernate.metamodel.spi.relational.Index;
|
||||
import org.hibernate.metamodel.spi.relational.Sequence;
|
||||
import org.hibernate.metamodel.spi.relational.Table;
|
||||
import org.hibernate.persister.entity.Lockable;
|
||||
import org.hibernate.procedure.internal.StandardCallableStatementSupport;
|
||||
import org.hibernate.procedure.spi.CallableStatementSupport;
|
||||
|
@ -89,6 +94,13 @@ import org.hibernate.sql.ANSIJoinFragment;
|
|||
import org.hibernate.sql.CaseFragment;
|
||||
import org.hibernate.sql.ForUpdateFragment;
|
||||
import org.hibernate.sql.JoinFragment;
|
||||
import org.hibernate.tool.schema.internal.StandardAuxiliaryDatabaseObjectExporter;
|
||||
import org.hibernate.tool.schema.internal.StandardForeignKeyExporter;
|
||||
import org.hibernate.tool.schema.internal.StandardIndexExporter;
|
||||
import org.hibernate.tool.schema.internal.StandardSequenceExporter;
|
||||
import org.hibernate.tool.schema.internal.StandardTableExporter;
|
||||
import org.hibernate.tool.schema.internal.TemporaryTableExporter;
|
||||
import org.hibernate.tool.schema.spi.Exporter;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
import org.hibernate.type.descriptor.sql.ClobTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
|
@ -1965,6 +1977,37 @@ public abstract class Dialect implements ConversionContext {
|
|||
|
||||
// DDL support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
private StandardTableExporter tableExporter = new StandardTableExporter( this );
|
||||
private StandardSequenceExporter sequenceExporter = new StandardSequenceExporter( this );
|
||||
private StandardIndexExporter indexExporter = new StandardIndexExporter( this );
|
||||
private StandardForeignKeyExporter foreignKeyExporter = new StandardForeignKeyExporter( this );
|
||||
private StandardAuxiliaryDatabaseObjectExporter auxiliaryObjectExporter = new StandardAuxiliaryDatabaseObjectExporter( this );
|
||||
private TemporaryTableExporter temporaryTableExporter = new TemporaryTableExporter( this );
|
||||
|
||||
public Exporter<Table> getTableExporter() {
|
||||
return tableExporter;
|
||||
}
|
||||
|
||||
public Exporter<Table> getTemporaryTableExporter() {
|
||||
return temporaryTableExporter;
|
||||
}
|
||||
|
||||
public Exporter<Sequence> getSequenceExporter() {
|
||||
return sequenceExporter;
|
||||
}
|
||||
|
||||
public Exporter<Index> getIndexExporter() {
|
||||
return indexExporter;
|
||||
}
|
||||
|
||||
public Exporter<ForeignKey> getForeignKeyExporter() {
|
||||
return foreignKeyExporter;
|
||||
}
|
||||
|
||||
public Exporter<AuxiliaryDatabaseObject> getAuxiliaryDatabaseObjectExporter() {
|
||||
return auxiliaryObjectExporter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SQL command used to create the named schema
|
||||
*
|
||||
|
@ -1987,6 +2030,15 @@ public abstract class Dialect implements ConversionContext {
|
|||
return "drop schema " + schemaName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SQL command used to retrieve the current schema name
|
||||
*
|
||||
* @return The current schema retrieval SQL
|
||||
*/
|
||||
public String getCurrentSchemaCommand() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does this dialect support the <tt>ALTER TABLE</tt> syntax?
|
||||
*
|
||||
|
|
|
@ -427,4 +427,9 @@ public class H2Dialect extends Dialect {
|
|||
public boolean supportsTuplesInSubqueries() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCurrentSchemaCommand() {
|
||||
return "call schema()";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -620,4 +620,9 @@ public class Oracle8iDialect extends Dialect {
|
|||
// Oracle supports returning cursors
|
||||
return StandardCallableStatementSupport.REF_CURSOR_INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCurrentSchemaCommand() {
|
||||
return "select sys_context( 'userenv', 'current_schema' ) from dual";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,9 +23,9 @@ package org.hibernate.dialect.unique;
|
|||
import java.util.Iterator;
|
||||
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.metamodel.relational.Column;
|
||||
import org.hibernate.metamodel.relational.Index;
|
||||
import org.hibernate.metamodel.relational.UniqueKey;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.metamodel.spi.relational.Column;
|
||||
import org.hibernate.metamodel.spi.relational.UniqueKey;
|
||||
|
||||
/**
|
||||
* DB2 does not allow unique constraints on nullable columns. Rather than
|
||||
|
@ -68,13 +68,27 @@ public class DB2UniqueDelegate extends DefaultUniqueDelegate {
|
|||
@Override
|
||||
public String getAlterTableToAddUniqueKeyCommand(UniqueKey uniqueKey) {
|
||||
if ( hasNullable( uniqueKey ) ) {
|
||||
return Index.buildSqlCreateIndexString(
|
||||
dialect,
|
||||
uniqueKey.getName(),
|
||||
uniqueKey.getTable(),
|
||||
uniqueKey.getColumns(),
|
||||
true
|
||||
);
|
||||
// TODO: This borrows from Index's old way of doing things. This
|
||||
// should be using StandardIndexExporter. However, not all callers
|
||||
// have JdbcEnvironment available. We'll need to refactor a bit...
|
||||
String keyName = dialect.qualifyIndexName() ? uniqueKey.getName()
|
||||
: StringHelper.unqualify( uniqueKey.getName() );
|
||||
StringBuilder buf = new StringBuilder( "create unique index " )
|
||||
.append( keyName ).append( " on " )
|
||||
.append( uniqueKey.getTable().getQualifiedName( dialect ) )
|
||||
.append( " (" );
|
||||
boolean first = true;
|
||||
for ( Column column : uniqueKey.getColumns() ) {
|
||||
if ( first ) {
|
||||
first = false;
|
||||
}
|
||||
else {
|
||||
buf.append( ", " );
|
||||
}
|
||||
buf.append( ( column.getColumnName().getText( dialect ) ) );
|
||||
}
|
||||
buf.append( ")" );
|
||||
return buf.toString();
|
||||
}
|
||||
else {
|
||||
return super.getAlterTableToAddUniqueKeyCommand( uniqueKey );
|
||||
|
@ -105,7 +119,12 @@ public class DB2UniqueDelegate extends DefaultUniqueDelegate {
|
|||
@Override
|
||||
public String getAlterTableToDropUniqueKeyCommand(UniqueKey uniqueKey) {
|
||||
if ( hasNullable( uniqueKey ) ) {
|
||||
return Index.buildSqlDropIndexString( dialect, uniqueKey.getTable(), uniqueKey.getName() );
|
||||
// TODO: This borrows from Index's old way of doing things. This
|
||||
// should be using StandardIndexExporter. However, not all callers
|
||||
// have JdbcEnvironment available. We'll need to refactor a bit...
|
||||
return "drop index " + StringHelper.qualify(
|
||||
uniqueKey.getTable().getQualifiedName( dialect ),
|
||||
uniqueKey.getName() );
|
||||
}
|
||||
else {
|
||||
return super.getAlterTableToDropUniqueKeyCommand( uniqueKey );
|
||||
|
|
|
@ -23,9 +23,9 @@ package org.hibernate.dialect.unique;
|
|||
import java.util.Iterator;
|
||||
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.metamodel.relational.Column;
|
||||
import org.hibernate.metamodel.relational.Table;
|
||||
import org.hibernate.metamodel.relational.UniqueKey;
|
||||
import org.hibernate.metamodel.spi.relational.Column;
|
||||
import org.hibernate.metamodel.spi.relational.Table;
|
||||
import org.hibernate.metamodel.spi.relational.UniqueKey;
|
||||
|
||||
/**
|
||||
* The default UniqueDelegate implementation for most dialects. Uses
|
||||
|
@ -135,8 +135,8 @@ public class DefaultUniqueDelegate implements UniqueDelegate {
|
|||
final StringBuilder sb = new StringBuilder( " unique (" );
|
||||
final Iterator columnIterator = uniqueKey.getColumns().iterator();
|
||||
while ( columnIterator.hasNext() ) {
|
||||
final org.hibernate.mapping.Column column = (org.hibernate.mapping.Column) columnIterator.next();
|
||||
sb.append( column.getQuotedName( dialect ) );
|
||||
Column column = (Column) columnIterator.next();
|
||||
sb.append( column.getColumnName().getText( dialect ) );
|
||||
if ( columnIterator.hasNext() ) {
|
||||
sb.append( ", " );
|
||||
}
|
||||
|
@ -149,10 +149,17 @@ public class DefaultUniqueDelegate implements UniqueDelegate {
|
|||
public String getAlterTableToDropUniqueKeyCommand(UniqueKey uniqueKey) {
|
||||
// Do this here, rather than allowing UniqueKey/Constraint to do it.
|
||||
// We need full, simplified control over whether or not it happens.
|
||||
final String tableName = uniqueKey.getTable().getQualifiedName( dialect );
|
||||
final String constraintName = dialect.quote( uniqueKey.getName() );
|
||||
|
||||
return "alter table " + tableName + " drop constraint " + constraintName;
|
||||
final StringBuilder buf = new StringBuilder( "alter table " );
|
||||
buf.append( uniqueKey.getTable().getQualifiedName( dialect ) );
|
||||
buf.append(" drop constraint " );
|
||||
if ( dialect.supportsIfExistsBeforeConstraintName() ) {
|
||||
buf.append( "if exists " );
|
||||
}
|
||||
buf.append( dialect.quote( uniqueKey.getName() ) );
|
||||
if ( dialect.supportsIfExistsAfterConstraintName() ) {
|
||||
buf.append( " if exists" );
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
package org.hibernate.dialect.unique;
|
||||
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.metamodel.relational.UniqueKey;
|
||||
import org.hibernate.metamodel.spi.relational.UniqueKey;
|
||||
|
||||
/**
|
||||
* Informix requires the constraint name to come last on the alter table.
|
||||
|
|
|
@ -20,9 +20,9 @@
|
|||
*/
|
||||
package org.hibernate.dialect.unique;
|
||||
|
||||
import org.hibernate.metamodel.relational.Column;
|
||||
import org.hibernate.metamodel.relational.Table;
|
||||
import org.hibernate.metamodel.relational.UniqueKey;
|
||||
import org.hibernate.metamodel.spi.relational.Column;
|
||||
import org.hibernate.metamodel.spi.relational.Table;
|
||||
import org.hibernate.metamodel.spi.relational.UniqueKey;
|
||||
|
||||
/**
|
||||
* Dialect-level delegate in charge of applying "uniqueness" to a column. Uniqueness can be defined
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, Red Hat Inc. 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 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.engine.config.spi;
|
||||
|
||||
|
||||
import static org.hibernate.engine.config.spi.ConfigurationService.Converter;
|
||||
|
||||
/**
|
||||
* Standard set of setting converters
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class StandardConverters {
|
||||
public static final Converter<Boolean> BOOLEAN = new Converter<Boolean>() {
|
||||
@Override
|
||||
public Boolean convert(Object value) {
|
||||
if ( value == null ) {
|
||||
throw new IllegalArgumentException( "Null value passed to convert" );
|
||||
}
|
||||
|
||||
return Boolean.class.isInstance( value )
|
||||
? Boolean.class.cast( value )
|
||||
: Boolean.parseBoolean( value.toString() );
|
||||
}
|
||||
};
|
||||
|
||||
public static final Converter<String> STRING = new Converter<String>() {
|
||||
@Override
|
||||
public String convert(Object value) {
|
||||
if ( value == null ) {
|
||||
throw new IllegalArgumentException( "Null value passed to convert" );
|
||||
}
|
||||
|
||||
return value.toString();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Disallow direct instantiation
|
||||
*/
|
||||
private StandardConverters() {
|
||||
}
|
||||
}
|
|
@ -222,7 +222,7 @@ public final class Cascade {
|
|||
}
|
||||
|
||||
if (type.isAssociationType() && ((AssociationType)type).getForeignKeyDirection().equals(
|
||||
ForeignKeyDirection.FOREIGN_KEY_TO_PARENT )) {
|
||||
ForeignKeyDirection.TO_PARENT )) {
|
||||
// If FK direction is to-parent, we must remove the orphan *before* the queued update(s)
|
||||
// occur. Otherwise, replacing the association on a managed entity, without manually
|
||||
// nulling and flushing, causes FK constraint violations.
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, Red Hat Inc. 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 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.engine.jdbc.connections.internal;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class UserSuppliedConnectionException extends HibernateException {
|
||||
public UserSuppliedConnectionException() {
|
||||
super( "The application must supply JDBC connections" );
|
||||
}
|
||||
}
|
|
@ -58,12 +58,12 @@ public class UserSuppliedConnectionProviderImpl implements ConnectionProvider {
|
|||
|
||||
@Override
|
||||
public Connection getConnection() throws SQLException {
|
||||
throw new UnsupportedOperationException( "The application must supply JDBC connections" );
|
||||
throw new UserSuppliedConnectionException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeConnection(Connection conn) throws SQLException {
|
||||
throw new UnsupportedOperationException( "The application must supply JDBC connections" );
|
||||
throw new UserSuppliedConnectionException();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, Red Hat Inc. 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 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.engine.jdbc.connections.spi;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* Provides centralized access to JDBC connections. Centralized to hide the complexity of accounting for contextual
|
||||
* (multi-tenant) versus non-contextual access.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface JdbcConnectionAccess extends Serializable {
|
||||
/**
|
||||
* Obtain a JDBC connection
|
||||
*
|
||||
* @return The obtained connection
|
||||
*
|
||||
* @throws SQLException Indicates a problem getting the connection
|
||||
*/
|
||||
public Connection obtainConnection() throws SQLException;
|
||||
|
||||
/**
|
||||
* Release a previously obtained connection
|
||||
*
|
||||
* @param connection The connection to release
|
||||
*
|
||||
* @throws SQLException Indicates a problem releasing the connection
|
||||
*/
|
||||
public void releaseConnection(Connection connection) throws SQLException;
|
||||
|
||||
/**
|
||||
* Does the underlying provider of connections support aggressive releasing of connections (and re-acquisition
|
||||
* of those connections later, if need be) in JTA environments?
|
||||
*
|
||||
* @see org.hibernate.engine.jdbc.connections.spi.ConnectionProvider#supportsAggressiveRelease()
|
||||
* @see org.hibernate.engine.jdbc.connections.spi.MultiTenantConnectionProvider#supportsAggressiveRelease()
|
||||
*/
|
||||
public boolean supportsAggressiveRelease();
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, Red Hat Inc. 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 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.engine.jdbc.env.internal;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.jdbc.env.spi.SchemaNameResolver;
|
||||
|
||||
/**
|
||||
* Default implementation
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class DefaultSchemaNameResolver implements SchemaNameResolver {
|
||||
public static final DefaultSchemaNameResolver INSTANCE = new DefaultSchemaNameResolver();
|
||||
|
||||
@Override
|
||||
public String resolveSchemaName(Connection connection, Dialect dialect) throws SQLException {
|
||||
Statement statement = connection.createStatement();
|
||||
try {
|
||||
ResultSet resultSet = statement.executeQuery( dialect.getCurrentSchemaCommand() );
|
||||
try {
|
||||
if ( ! resultSet.next() ) {
|
||||
return null;
|
||||
}
|
||||
return resultSet.getString( 1 );
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
resultSet.close();
|
||||
}
|
||||
catch (SQLException ignore) {
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
statement.close();
|
||||
}
|
||||
catch (SQLException ignore) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,142 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, Red Hat Inc. 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 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.engine.jdbc.env.internal;
|
||||
|
||||
import org.hibernate.engine.jdbc.env.spi.ExtractedDatabaseMetaData;
|
||||
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
||||
import org.hibernate.engine.jdbc.env.spi.SQLStateType;
|
||||
|
||||
/**
|
||||
* Standard implementation of ExtractedDatabaseMetaData
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class ExtractedDatabaseMetaDataImpl implements ExtractedDatabaseMetaData {
|
||||
private final JdbcEnvironment jdbcEnvironment;
|
||||
|
||||
private final boolean supportsRefCursors;
|
||||
private final boolean supportsNamedParameters;
|
||||
private final boolean supportsScrollableResults;
|
||||
private final boolean supportsGetGeneratedKeys;
|
||||
private final boolean supportsBatchUpdates;
|
||||
private final boolean supportsDataDefinitionInTransaction;
|
||||
private final boolean doesDataDefinitionCauseTransactionCommit;
|
||||
private final SQLStateType sqlStateType;
|
||||
private final boolean lobLocatorUpdateCopy;
|
||||
|
||||
/**
|
||||
* Form used when {@link java.sql.DatabaseMetaData} is not available.
|
||||
*
|
||||
* @param jdbcEnvironment The JDBC environment containing this metadata.
|
||||
*/
|
||||
public ExtractedDatabaseMetaDataImpl(JdbcEnvironment jdbcEnvironment) {
|
||||
this.jdbcEnvironment = jdbcEnvironment;
|
||||
|
||||
// if possible, set values that will allow things to still work....
|
||||
this.supportsRefCursors = false; // Java 8 feature, safest to say not.
|
||||
this.supportsNamedParameters = false;
|
||||
this.supportsScrollableResults = false;
|
||||
this.supportsGetGeneratedKeys = false;
|
||||
this.supportsBatchUpdates = false;
|
||||
this.sqlStateType = SQLStateType.UNKNOWN;
|
||||
this.lobLocatorUpdateCopy = false;
|
||||
|
||||
// ugh my favorites...
|
||||
this.supportsDataDefinitionInTransaction = true;
|
||||
this.doesDataDefinitionCauseTransactionCommit = false;
|
||||
}
|
||||
|
||||
public ExtractedDatabaseMetaDataImpl(
|
||||
JdbcEnvironmentImpl jdbcEnvironment,
|
||||
boolean supportsRefCursors,
|
||||
boolean supportsNamedParameters,
|
||||
boolean supportsScrollableResults,
|
||||
boolean supportsGetGeneratedKeys,
|
||||
boolean supportsBatchUpdates,
|
||||
boolean supportsDataDefinitionInTransaction,
|
||||
boolean doesDataDefinitionCauseTransactionCommit,
|
||||
SQLStateType sqlStateType,
|
||||
boolean lobLocatorUpdateCopy) {
|
||||
this.jdbcEnvironment = jdbcEnvironment;
|
||||
this.supportsRefCursors = supportsRefCursors;
|
||||
this.supportsNamedParameters = supportsNamedParameters;
|
||||
this.supportsScrollableResults = supportsScrollableResults;
|
||||
this.supportsGetGeneratedKeys = supportsGetGeneratedKeys;
|
||||
this.supportsBatchUpdates = supportsBatchUpdates;
|
||||
this.supportsDataDefinitionInTransaction = supportsDataDefinitionInTransaction;
|
||||
this.doesDataDefinitionCauseTransactionCommit = doesDataDefinitionCauseTransactionCommit;
|
||||
this.sqlStateType = sqlStateType;
|
||||
this.lobLocatorUpdateCopy = lobLocatorUpdateCopy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsRefCursors() {
|
||||
return supportsRefCursors;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JdbcEnvironment getJdbcEnvironment() {
|
||||
return jdbcEnvironment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsNamedParameters() {
|
||||
return supportsNamedParameters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsScrollableResults() {
|
||||
return supportsScrollableResults;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsGetGeneratedKeys() {
|
||||
return supportsGetGeneratedKeys;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsBatchUpdates() {
|
||||
return supportsBatchUpdates;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsDataDefinitionInTransaction() {
|
||||
return supportsDataDefinitionInTransaction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doesDataDefinitionCauseTransactionCommit() {
|
||||
return doesDataDefinitionCauseTransactionCommit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLStateType getSqlStateType() {
|
||||
return sqlStateType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doesLobLocatorUpdateCopy() {
|
||||
return lobLocatorUpdateCopy;
|
||||
}
|
||||
}
|
339
hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/JdbcEnvironmentImpl.java
vendored
Normal file
339
hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/JdbcEnvironmentImpl.java
vendored
Normal file
|
@ -0,0 +1,339 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, Red Hat Inc. 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 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.engine.jdbc.env.internal;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.boot.registry.selector.spi.StrategySelectionException;
|
||||
import org.hibernate.boot.registry.selector.spi.StrategySelector;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.config.spi.ConfigurationService;
|
||||
import org.hibernate.engine.config.spi.StandardConverters;
|
||||
import org.hibernate.engine.jdbc.cursor.internal.StandardRefCursorSupport;
|
||||
import org.hibernate.engine.jdbc.env.spi.ExtractedDatabaseMetaData;
|
||||
import org.hibernate.engine.jdbc.env.spi.IdentifierHelper;
|
||||
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
||||
import org.hibernate.engine.jdbc.env.spi.LobCreatorBuilder;
|
||||
import org.hibernate.engine.jdbc.env.spi.QualifiedObjectNameSupport;
|
||||
import org.hibernate.engine.jdbc.env.spi.SQLStateType;
|
||||
import org.hibernate.engine.jdbc.env.spi.SchemaNameResolver;
|
||||
import org.hibernate.engine.jdbc.env.spi.StandardQualifiedObjectNameSupportImpl;
|
||||
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
|
||||
import org.hibernate.engine.jdbc.spi.TypeInfo;
|
||||
import org.hibernate.exception.internal.SQLExceptionTypeDelegate;
|
||||
import org.hibernate.exception.internal.SQLStateConversionDelegate;
|
||||
import org.hibernate.exception.internal.StandardSQLExceptionConverter;
|
||||
import org.hibernate.exception.spi.SQLExceptionConverter;
|
||||
import org.hibernate.internal.CoreLogging;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.metamodel.spi.relational.Identifier;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
import org.hibernate.service.spi.ServiceRegistryImplementor;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class JdbcEnvironmentImpl implements JdbcEnvironment {
|
||||
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( JdbcEnvironmentImpl.class );
|
||||
|
||||
private final ServiceRegistryImplementor serviceRegistry;
|
||||
private final Dialect dialect;
|
||||
|
||||
private final SqlExceptionHelper sqlExceptionHelper;
|
||||
private final ExtractedDatabaseMetaData extractedMetaDataSupport;
|
||||
private final Set<String> reservedWords;
|
||||
private final Identifier currentCatalog;
|
||||
private final Identifier currentSchema;
|
||||
private final IdentifierHelper identifierHelper;
|
||||
private final QualifiedObjectNameSupport qualifiedObjectNameSupport;
|
||||
private final LobCreatorBuilderImpl lobCreatorBuilder;
|
||||
private final LinkedHashSet<TypeInfo> typeInfoSet = new LinkedHashSet<TypeInfo>();
|
||||
|
||||
/**
|
||||
* Constructor form used when the JDBC {@link DatabaseMetaData} is not available.
|
||||
*
|
||||
* @param serviceRegistry The service registry
|
||||
* @param dialect The resolved dialect.
|
||||
*/
|
||||
public JdbcEnvironmentImpl(ServiceRegistryImplementor serviceRegistry, Dialect dialect) {
|
||||
this.serviceRegistry = serviceRegistry;
|
||||
this.dialect = dialect;
|
||||
|
||||
this.sqlExceptionHelper = buildSqlExceptionHelper( dialect );
|
||||
this.extractedMetaDataSupport = new ExtractedDatabaseMetaDataImpl( this );
|
||||
|
||||
// make sure reserved-words, current-catalog and current-schema happen before the identifier-helper!
|
||||
this.reservedWords = dialect.getKeywords();
|
||||
this.currentCatalog = Identifier.toIdentifier(
|
||||
serviceRegistry.getService( ConfigurationService.class )
|
||||
.getSetting( AvailableSettings.DEFAULT_CATALOG, StandardConverters.STRING )
|
||||
);
|
||||
this.currentSchema = Identifier.toIdentifier(
|
||||
serviceRegistry.getService( ConfigurationService.class )
|
||||
.getSetting( AvailableSettings.DEFAULT_SCHEMA, StandardConverters.STRING )
|
||||
);
|
||||
|
||||
final boolean globallyQuoteIdentifiers = serviceRegistry.getService( ConfigurationService.class )
|
||||
.getSetting( AvailableSettings.GLOBALLY_QUOTED_IDENTIFIERS, StandardConverters.BOOLEAN, false );
|
||||
|
||||
// a simple temporary impl that works on H2
|
||||
this.identifierHelper = new NormalizingIdentifierHelperImpl(
|
||||
this,
|
||||
globallyQuoteIdentifiers,
|
||||
true, // storesMixedCaseQuotedIdentifiers
|
||||
false, // storesLowerCaseQuotedIdentifiers
|
||||
false, // storesUpperCaseQuotedIdentifiers
|
||||
true, // storesUpperCaseIdentifiers
|
||||
false // storesLowerCaseIdentifiers
|
||||
);
|
||||
|
||||
// again, a simple temporary impl that works on H2
|
||||
this.qualifiedObjectNameSupport = new StandardQualifiedObjectNameSupportImpl(
|
||||
".",
|
||||
true,
|
||||
dialect.openQuote(),
|
||||
dialect.closeQuote()
|
||||
);
|
||||
|
||||
this.lobCreatorBuilder = LobCreatorBuilderImpl.makeLobCreatorBuilder();
|
||||
|
||||
}
|
||||
|
||||
public JdbcEnvironmentImpl(ServiceRegistryImplementor serviceRegistry, Dialect dialect, DatabaseMetaData dbmd) throws SQLException {
|
||||
this.serviceRegistry = serviceRegistry;
|
||||
this.dialect = dialect;
|
||||
|
||||
this.sqlExceptionHelper = buildSqlExceptionHelper( dialect );
|
||||
|
||||
this.extractedMetaDataSupport = new ExtractedDatabaseMetaDataImpl(
|
||||
this,
|
||||
StandardRefCursorSupport.supportsRefCursors( dbmd ),
|
||||
dbmd.supportsNamedParameters(),
|
||||
dbmd.supportsResultSetType( ResultSet.TYPE_SCROLL_INSENSITIVE ),
|
||||
dbmd.supportsGetGeneratedKeys(),
|
||||
dbmd.supportsBatchUpdates(),
|
||||
!dbmd.dataDefinitionIgnoredInTransactions(),
|
||||
dbmd.dataDefinitionCausesTransactionCommit(),
|
||||
parseSQLStateType( dbmd.getSQLStateType() ),
|
||||
dbmd.locatorsUpdateCopy()
|
||||
);
|
||||
|
||||
// make sure reserved-words happen before the identifier-helper!
|
||||
this.reservedWords = buildMergedReservedWords( dialect, dbmd );
|
||||
|
||||
final boolean globallyQuoteIdentifiers = serviceRegistry.getService( ConfigurationService.class )
|
||||
.getSetting( AvailableSettings.GLOBALLY_QUOTED_IDENTIFIERS, StandardConverters.BOOLEAN, false );
|
||||
|
||||
this.identifierHelper = new NormalizingIdentifierHelperImpl(
|
||||
this,
|
||||
globallyQuoteIdentifiers,
|
||||
dbmd.storesMixedCaseQuotedIdentifiers(),
|
||||
dbmd.storesLowerCaseQuotedIdentifiers(),
|
||||
dbmd.storesUpperCaseQuotedIdentifiers(),
|
||||
dbmd.storesUpperCaseIdentifiers(),
|
||||
dbmd.storesLowerCaseIdentifiers()
|
||||
);
|
||||
|
||||
// and that current-catalog and current-schema happen after it
|
||||
this.currentCatalog = determineCurrentCatalog( dbmd );
|
||||
this.currentSchema = determineCurrentSchema( dbmd );
|
||||
|
||||
this.qualifiedObjectNameSupport = new StandardQualifiedObjectNameSupportImpl(
|
||||
dbmd.getCatalogSeparator(),
|
||||
dbmd.isCatalogAtStart(),
|
||||
dialect.openQuote(),
|
||||
dialect.closeQuote()
|
||||
);
|
||||
|
||||
this.typeInfoSet.addAll( TypeInfo.extractTypeInfo( dbmd ) );
|
||||
|
||||
this.lobCreatorBuilder = LobCreatorBuilderImpl.makeLobCreatorBuilder(
|
||||
serviceRegistry.getService( ConfigurationService.class ).getSettings(),
|
||||
dbmd.getConnection()
|
||||
);
|
||||
}
|
||||
|
||||
private SQLStateType parseSQLStateType(int sqlStateType) {
|
||||
switch ( sqlStateType ) {
|
||||
case DatabaseMetaData.sqlStateSQL99 : {
|
||||
return SQLStateType.SQL99;
|
||||
}
|
||||
case DatabaseMetaData.sqlStateXOpen : {
|
||||
return SQLStateType.XOpen;
|
||||
}
|
||||
default : {
|
||||
return SQLStateType.UNKNOWN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private SqlExceptionHelper buildSqlExceptionHelper(Dialect dialect) {
|
||||
SQLExceptionConverter sqlExceptionConverter = dialect.buildSQLExceptionConverter();
|
||||
if ( sqlExceptionConverter == null ) {
|
||||
final StandardSQLExceptionConverter converter = new StandardSQLExceptionConverter();
|
||||
sqlExceptionConverter = converter;
|
||||
converter.addDelegate( dialect.buildSQLExceptionConversionDelegate() );
|
||||
converter.addDelegate( new SQLExceptionTypeDelegate( dialect ) );
|
||||
// todo : vary this based on extractedMetaDataSupport.getSqlStateType()
|
||||
converter.addDelegate( new SQLStateConversionDelegate( dialect ) );
|
||||
}
|
||||
return new SqlExceptionHelper( sqlExceptionConverter );
|
||||
}
|
||||
|
||||
private Identifier determineCurrentCatalog(DatabaseMetaData dbmd) throws SQLException {
|
||||
String currentCatalogName = dbmd.getConnection().getCatalog();
|
||||
if ( currentCatalogName != null ) {
|
||||
// intentionally using fromMetaDataObjectName rather than fromMetaDataCatalogName !!!
|
||||
return identifierHelper.fromMetaDataObjectName( currentCatalogName );
|
||||
}
|
||||
else {
|
||||
currentCatalogName = serviceRegistry.getService( ConfigurationService.class )
|
||||
.getSetting( AvailableSettings.DEFAULT_CATALOG, StandardConverters.STRING );
|
||||
return Identifier.toIdentifier( currentCatalogName );
|
||||
}
|
||||
}
|
||||
|
||||
private Identifier determineCurrentSchema(DatabaseMetaData dbmd) throws SQLException {
|
||||
String currentSchemaName = locateSchemaNameResolver().resolveSchemaName( dbmd.getConnection(), dialect );
|
||||
if ( currentSchemaName != null ) {
|
||||
// intentionally using fromMetaDataObjectName rather than fromMetaDataSchemaName !!!
|
||||
return identifierHelper.fromMetaDataObjectName( currentSchemaName );
|
||||
}
|
||||
else {
|
||||
currentSchemaName = serviceRegistry.getService( ConfigurationService.class )
|
||||
.getSetting( AvailableSettings.DEFAULT_SCHEMA, StandardConverters.STRING );
|
||||
return Identifier.toIdentifier( currentSchemaName );
|
||||
}
|
||||
}
|
||||
|
||||
private SchemaNameResolver locateSchemaNameResolver() {
|
||||
final Object setting = serviceRegistry.getService( ConfigurationService.class )
|
||||
.getSettings()
|
||||
.get( AvailableSettings.SCHEMA_NAME_RESOLVER );
|
||||
try {
|
||||
return serviceRegistry.getService( StrategySelector.class ).resolveDefaultableStrategy(
|
||||
SchemaNameResolver.class,
|
||||
setting,
|
||||
DefaultSchemaNameResolver.INSTANCE
|
||||
);
|
||||
}
|
||||
catch ( StrategySelectionException e ) {
|
||||
final Throwable cause = e.getCause();
|
||||
if ( ClassNotFoundException.class.isInstance( cause ) ) {
|
||||
LOG.unableToLocateConfiguredSchemaNameResolver(
|
||||
e.getImplementationClassName(),
|
||||
cause.toString()
|
||||
);
|
||||
}
|
||||
else if ( InvocationTargetException.class.isInstance( cause ) ) {
|
||||
LOG.unableToInstantiateConfiguredSchemaNameResolver(
|
||||
e.getImplementationClassName(),
|
||||
InvocationTargetException.class.cast( cause ).getTargetException().toString() );
|
||||
}
|
||||
else {
|
||||
LOG.unableToInstantiateConfiguredSchemaNameResolver(
|
||||
e.getImplementationClassName(),
|
||||
cause.toString() );
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private Set<String> buildMergedReservedWords(Dialect dialect, DatabaseMetaData dbmd) throws SQLException {
|
||||
Set<String> reservedWords = new HashSet<String>();
|
||||
reservedWords.addAll( dialect.getKeywords() );
|
||||
// todo : do we need to explicitly handle SQL:2003 keywords?
|
||||
reservedWords.addAll( Arrays.asList( dbmd.getSQLKeywords().split( "," ) ) );
|
||||
return reservedWords;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialect getDialect() {
|
||||
return dialect;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExtractedDatabaseMetaData getExtractedDatabaseMetaData() {
|
||||
return extractedMetaDataSupport;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier getCurrentCatalog() {
|
||||
return currentCatalog;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier getCurrentSchema() {
|
||||
return currentSchema;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QualifiedObjectNameSupport getQualifiedObjectNameSupport() {
|
||||
return qualifiedObjectNameSupport;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IdentifierHelper getIdentifierHelper() {
|
||||
return identifierHelper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getReservedWords() {
|
||||
return reservedWords;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlExceptionHelper getSqlExceptionHelper() {
|
||||
return sqlExceptionHelper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LobCreatorBuilder getLobCreatorBuilder() {
|
||||
return lobCreatorBuilder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeInfo getTypeInfoForJdbcCode(int jdbcTypeCode) {
|
||||
for ( TypeInfo typeInfo : typeInfoSet ) {
|
||||
if ( typeInfo.getJdbcTypeCode() == jdbcTypeCode ) {
|
||||
return typeInfo;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServiceRegistry getServiceRegistry() {
|
||||
return serviceRegistry;
|
||||
}
|
||||
}
|
214
hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/JdbcEnvironmentInitiator.java
vendored
Normal file
214
hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/JdbcEnvironmentInitiator.java
vendored
Normal file
|
@ -0,0 +1,214 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, Red Hat Inc. 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 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.engine.jdbc.env.internal;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.MultiTenancyStrategy;
|
||||
import org.hibernate.boot.registry.StandardServiceInitiator;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
|
||||
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
|
||||
import org.hibernate.engine.jdbc.connections.spi.MultiTenantConnectionProvider;
|
||||
import org.hibernate.engine.jdbc.dialect.spi.DatabaseMetaDataDialectResolutionInfoAdapter;
|
||||
import org.hibernate.engine.jdbc.dialect.spi.DialectFactory;
|
||||
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
|
||||
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfoSource;
|
||||
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.config.ConfigurationHelper;
|
||||
import org.hibernate.service.spi.ServiceRegistryImplementor;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class JdbcEnvironmentInitiator implements StandardServiceInitiator<JdbcEnvironment> {
|
||||
private static final CoreMessageLogger log = Logger.getMessageLogger(
|
||||
CoreMessageLogger.class,
|
||||
JdbcEnvironmentInitiator.class.getName()
|
||||
);
|
||||
|
||||
public static final JdbcEnvironmentInitiator INSTANCE = new JdbcEnvironmentInitiator();
|
||||
|
||||
@Override
|
||||
public Class<JdbcEnvironment> getServiceInitiated() {
|
||||
return JdbcEnvironment.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JdbcEnvironment initiateService(Map configurationValues, ServiceRegistryImplementor registry) {
|
||||
final DialectFactory dialectFactory = registry.getService( DialectFactory.class );
|
||||
|
||||
// 'hibernate.temp.use_jdbc_metadata_defaults' is a temporary magic value.
|
||||
// The need for it is intended to be alleviated with future development, thus it is
|
||||
// not defined as an Environment constant...
|
||||
//
|
||||
// it is used to control whether we should consult the JDBC metadata to determine
|
||||
// certain Settings default values; it is useful to *not* do this when the database
|
||||
// may not be available (mainly in tools usage).
|
||||
boolean useJdbcMetadata = ConfigurationHelper.getBoolean(
|
||||
"hibernate.temp.use_jdbc_metadata_defaults",
|
||||
configurationValues,
|
||||
true
|
||||
);
|
||||
|
||||
if ( useJdbcMetadata ) {
|
||||
final JdbcConnectionAccess jdbcConnectionAccess = buildJdbcConnectionAccess( configurationValues, registry );
|
||||
try {
|
||||
final Connection connection = jdbcConnectionAccess.obtainConnection();
|
||||
try {
|
||||
final DatabaseMetaData dbmd = connection.getMetaData();
|
||||
if ( log.isDebugEnabled() ) {
|
||||
log.debugf(
|
||||
"Database ->\n"
|
||||
+ " name : %s\n"
|
||||
+ " version : %s\n"
|
||||
+ " major : %s\n"
|
||||
+ " minor : %s",
|
||||
dbmd.getDatabaseProductName(),
|
||||
dbmd.getDatabaseProductVersion(),
|
||||
dbmd.getDatabaseMajorVersion(),
|
||||
dbmd.getDatabaseMinorVersion()
|
||||
);
|
||||
log.debugf(
|
||||
"Driver ->\n"
|
||||
+ " name : %s\n"
|
||||
+ " version : %s\n"
|
||||
+ " major : %s\n"
|
||||
+ " minor : %s",
|
||||
dbmd.getDriverName(),
|
||||
dbmd.getDriverVersion(),
|
||||
dbmd.getDriverMajorVersion(),
|
||||
dbmd.getDriverMinorVersion()
|
||||
);
|
||||
log.debugf( "JDBC version : %s.%s", dbmd.getJDBCMajorVersion(), dbmd.getJDBCMinorVersion() );
|
||||
}
|
||||
|
||||
Dialect dialect = dialectFactory.buildDialect(
|
||||
configurationValues,
|
||||
new DialectResolutionInfoSource() {
|
||||
@Override
|
||||
public DialectResolutionInfo getDialectResolutionInfo() {
|
||||
try {
|
||||
return new DatabaseMetaDataDialectResolutionInfoAdapter( connection.getMetaData() );
|
||||
}
|
||||
catch ( SQLException sqlException ) {
|
||||
throw new HibernateException(
|
||||
"Unable to access java.sql.DatabaseMetaData to determine appropriate Dialect to use",
|
||||
sqlException
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
return new JdbcEnvironmentImpl(
|
||||
registry,
|
||||
dialect,
|
||||
dbmd
|
||||
);
|
||||
}
|
||||
catch (SQLException e) {
|
||||
log.unableToObtainConnectionMetadata( e.getMessage() );
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
jdbcConnectionAccess.releaseConnection( connection );
|
||||
}
|
||||
catch (SQLException ignore) {
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
log.unableToObtainConnectionToQueryMetadata( e.getMessage() );
|
||||
}
|
||||
}
|
||||
|
||||
// if we get here, either we were asked to not use JDBC metadata or accessing the JDBC metadata failed.
|
||||
return new JdbcEnvironmentImpl( registry, dialectFactory.buildDialect( configurationValues, null ) );
|
||||
}
|
||||
|
||||
private JdbcConnectionAccess buildJdbcConnectionAccess(Map configValues, ServiceRegistryImplementor registry) {
|
||||
final MultiTenancyStrategy multiTenancyStrategy = MultiTenancyStrategy.determineMultiTenancyStrategy( configValues );
|
||||
if ( MultiTenancyStrategy.NONE == multiTenancyStrategy ) {
|
||||
ConnectionProvider connectionProvider = registry.getService( ConnectionProvider.class );
|
||||
return new ConnectionProviderJdbcConnectionAccess( connectionProvider );
|
||||
}
|
||||
else {
|
||||
final MultiTenantConnectionProvider multiTenantConnectionProvider = registry.getService( MultiTenantConnectionProvider.class );
|
||||
return new MultiTenantConnectionProviderJdbcConnectionAccess( multiTenantConnectionProvider );
|
||||
}
|
||||
}
|
||||
|
||||
private static class ConnectionProviderJdbcConnectionAccess implements JdbcConnectionAccess {
|
||||
private final ConnectionProvider connectionProvider;
|
||||
|
||||
public ConnectionProviderJdbcConnectionAccess(ConnectionProvider connectionProvider) {
|
||||
this.connectionProvider = connectionProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection obtainConnection() throws SQLException {
|
||||
return connectionProvider.getConnection();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void releaseConnection(Connection connection) throws SQLException {
|
||||
connectionProvider.closeConnection( connection );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsAggressiveRelease() {
|
||||
return connectionProvider.supportsAggressiveRelease();
|
||||
}
|
||||
}
|
||||
|
||||
private static class MultiTenantConnectionProviderJdbcConnectionAccess implements JdbcConnectionAccess {
|
||||
private final MultiTenantConnectionProvider connectionProvider;
|
||||
|
||||
public MultiTenantConnectionProviderJdbcConnectionAccess(MultiTenantConnectionProvider connectionProvider) {
|
||||
this.connectionProvider = connectionProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection obtainConnection() throws SQLException {
|
||||
return connectionProvider.getAnyConnection();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void releaseConnection(Connection connection) throws SQLException {
|
||||
connectionProvider.releaseAnyConnection( connection );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsAggressiveRelease() {
|
||||
return connectionProvider.supportsAggressiveRelease();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -21,7 +21,7 @@
|
|||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.engine.jdbc.internal;
|
||||
package org.hibernate.engine.jdbc.env.internal;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.sql.Connection;
|
||||
|
@ -34,6 +34,7 @@ import org.hibernate.engine.jdbc.ContextualLobCreator;
|
|||
import org.hibernate.engine.jdbc.LobCreationContext;
|
||||
import org.hibernate.engine.jdbc.LobCreator;
|
||||
import org.hibernate.engine.jdbc.NonContextualLobCreator;
|
||||
import org.hibernate.engine.jdbc.env.spi.LobCreatorBuilder;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.config.ConfigurationHelper;
|
||||
|
||||
|
@ -44,23 +45,40 @@ import org.jboss.logging.Logger;
|
|||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class LobCreatorBuilder {
|
||||
public class LobCreatorBuilderImpl implements LobCreatorBuilder {
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
|
||||
CoreMessageLogger.class,
|
||||
LobCreatorBuilder.class.getName()
|
||||
LobCreatorBuilderImpl.class.getName()
|
||||
);
|
||||
|
||||
private boolean useContextualLobCreation;
|
||||
private final boolean useContextualLobCreation;
|
||||
|
||||
private LobCreatorBuilderImpl(boolean useContextualLobCreation) {
|
||||
this.useContextualLobCreation = useContextualLobCreation;
|
||||
}
|
||||
|
||||
// factory methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
/**
|
||||
* The public factory method for obtaining the appropriate (according to given JDBC {@link java.sql.Connection}.
|
||||
* The public factory method for obtaining the appropriate LOB creator (according to given
|
||||
* JDBC {@link java.sql.Connection}).
|
||||
*
|
||||
* @param configValues The map of settings
|
||||
* @param jdbcConnection A JDBC {@link java.sql.Connection} which can be used to gauge the drivers level of support,
|
||||
* specifically for creating LOB references.
|
||||
*/
|
||||
public LobCreatorBuilder(Map configValues, Connection jdbcConnection) {
|
||||
this.useContextualLobCreation = useContextualLobCreation( configValues, jdbcConnection );
|
||||
public static LobCreatorBuilderImpl makeLobCreatorBuilder(Map configValues, Connection jdbcConnection) {
|
||||
return new LobCreatorBuilderImpl( useContextualLobCreation( configValues, jdbcConnection ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* For used when JDBC Connection is not available.
|
||||
*
|
||||
* @return Appropriate LobCreatorBuilder
|
||||
*/
|
||||
public static LobCreatorBuilderImpl makeLobCreatorBuilder() {
|
||||
LOG.disablingContextualLOBCreationSinceConnectionNull();
|
||||
return new LobCreatorBuilderImpl( false );
|
||||
}
|
||||
|
||||
private static final Class[] NO_ARG_SIG = new Class[0];
|
|
@ -0,0 +1,217 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, Red Hat Inc. 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 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.engine.jdbc.env.internal;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.engine.jdbc.env.spi.IdentifierHelper;
|
||||
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.metamodel.spi.relational.Identifier;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class NormalizingIdentifierHelperImpl implements IdentifierHelper {
|
||||
private static final Logger log = Logger.getLogger( NormalizingIdentifierHelperImpl.class );
|
||||
|
||||
private final JdbcEnvironment jdbcEnvironment;
|
||||
|
||||
private final boolean globallyQuoteIdentifiers;
|
||||
|
||||
private final boolean storesMixedCaseQuotedIdentifiers;
|
||||
private final boolean storesLowerCaseQuotedIdentifiers;
|
||||
private final boolean storesUpperCaseQuotedIdentifiers;
|
||||
private final boolean storesUpperCaseIdentifiers;
|
||||
private final boolean storesLowerCaseIdentifiers;
|
||||
|
||||
public NormalizingIdentifierHelperImpl(
|
||||
JdbcEnvironment jdbcEnvironment,
|
||||
boolean globallyQuoteIdentifiers,
|
||||
boolean storesMixedCaseQuotedIdentifiers,
|
||||
boolean storesLowerCaseQuotedIdentifiers,
|
||||
boolean storesUpperCaseQuotedIdentifiers,
|
||||
boolean storesUpperCaseIdentifiers,
|
||||
boolean storesLowerCaseIdentifiers) {
|
||||
this.jdbcEnvironment = jdbcEnvironment;
|
||||
this.globallyQuoteIdentifiers = globallyQuoteIdentifiers;
|
||||
this.storesMixedCaseQuotedIdentifiers = storesMixedCaseQuotedIdentifiers;
|
||||
this.storesLowerCaseQuotedIdentifiers = storesLowerCaseQuotedIdentifiers;
|
||||
this.storesUpperCaseQuotedIdentifiers = storesUpperCaseQuotedIdentifiers;
|
||||
this.storesUpperCaseIdentifiers = storesUpperCaseIdentifiers;
|
||||
this.storesLowerCaseIdentifiers = storesLowerCaseIdentifiers;
|
||||
|
||||
if ( storesMixedCaseQuotedIdentifiers && storesLowerCaseQuotedIdentifiers && storesUpperCaseQuotedIdentifiers ) {
|
||||
log.warn( "JDBC Driver reports it stores quoted identifiers in mixed, upper and lower case" );
|
||||
}
|
||||
else if ( storesMixedCaseQuotedIdentifiers && storesUpperCaseQuotedIdentifiers ) {
|
||||
log.warn( "JDBC Driver reports it stores quoted identifiers in both mixed and upper case" );
|
||||
}
|
||||
else if ( storesMixedCaseQuotedIdentifiers && storesLowerCaseQuotedIdentifiers ) {
|
||||
log.warn( "JDBC Driver reports it stores quoted identifiers in both mixed and lower case" );
|
||||
}
|
||||
|
||||
if ( storesUpperCaseIdentifiers && storesLowerCaseIdentifiers ) {
|
||||
log.warn( "JDBC Driver reports it stores non-quoted identifiers in both upper and lower case" );
|
||||
}
|
||||
|
||||
if ( storesUpperCaseIdentifiers && storesUpperCaseQuotedIdentifiers ) {
|
||||
log.warn( "JDBC Driver reports it stores both quoted and non-quoted identifiers in upper case" );
|
||||
}
|
||||
|
||||
if ( storesLowerCaseIdentifiers && storesLowerCaseQuotedIdentifiers ) {
|
||||
log.warn( "JDBC Driver reports it stores both quoted and non-quoted identifiers in lower case" );
|
||||
}
|
||||
}
|
||||
|
||||
// In the DatabaseMetaData method params for catalog and schema name have the following meaning:
|
||||
// 1) <""> means to match things "without a catalog/schema"
|
||||
// 2) <null> means to not limit results based on this field
|
||||
//
|
||||
// todo : not sure how "without a catalog/schema" is interpreted. Current?
|
||||
|
||||
@Override
|
||||
public String toMetaDataCatalogName(Identifier identifier) {
|
||||
if ( identifier == null ) {
|
||||
// todo : not sure if this is interpreted as <""> or <currentCatalog>
|
||||
return jdbcEnvironment.getCurrentCatalog() == null ? null : jdbcEnvironment.getCurrentCatalog().getText();
|
||||
}
|
||||
|
||||
return toText( identifier );
|
||||
}
|
||||
|
||||
private String toText(Identifier identifier) {
|
||||
if ( identifier == null ) {
|
||||
throw new IllegalArgumentException( "Identifier cannot be null; bad usage" );
|
||||
}
|
||||
|
||||
if ( identifier.isQuoted() && storesMixedCaseQuotedIdentifiers ) {
|
||||
return identifier.getText();
|
||||
}
|
||||
else if ( ( identifier.isQuoted() && storesUpperCaseQuotedIdentifiers )
|
||||
|| ( !identifier.isQuoted() && storesUpperCaseIdentifiers ) ) {
|
||||
return StringHelper.toUpperCase( identifier.getText() );
|
||||
}
|
||||
else if ( ( identifier.isQuoted() && storesLowerCaseQuotedIdentifiers )
|
||||
|| ( !identifier.isQuoted() && storesLowerCaseIdentifiers ) ) {
|
||||
return StringHelper.toLowerCase( identifier.getText() );
|
||||
}
|
||||
return identifier.getText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toMetaDataSchemaName(Identifier identifier) {
|
||||
if ( identifier == null ) {
|
||||
// todo : not sure if this is interpreted as <""> or <currentSchema>
|
||||
return jdbcEnvironment.getCurrentSchema() == null ? null : jdbcEnvironment.getCurrentSchema().getText();
|
||||
}
|
||||
|
||||
return toText( identifier );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toMetaDataObjectName(Identifier identifier) {
|
||||
if ( identifier == null ) {
|
||||
// if this method was called, the value is needed
|
||||
throw new IllegalArgumentException( );
|
||||
}
|
||||
return toText( identifier );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier fromMetaDataCatalogName(String catalogName) {
|
||||
if ( catalogName == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ( jdbcEnvironment.getCurrentCatalog() == null
|
||||
|| catalogName.equals( jdbcEnvironment.getCurrentCatalog().getText() ) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return toIdentifier( catalogName );
|
||||
// note really sure the best way to know (can you?) whether the identifier is quoted
|
||||
|
||||
}
|
||||
|
||||
public Identifier toIdentifier(String text) {
|
||||
if ( globallyQuoteIdentifiers ) {
|
||||
return Identifier.toIdentifier( text, true );
|
||||
}
|
||||
|
||||
// lovely decipher of whether the incoming value represents a quoted identifier...
|
||||
final boolean isUpperCase = text.toUpperCase().equals( text );
|
||||
final boolean isLowerCase = text.toLowerCase().equals( text );
|
||||
final boolean isMixedCase = ! isLowerCase && ! isUpperCase;
|
||||
|
||||
if ( jdbcEnvironment.getReservedWords().contains( text ) ) {
|
||||
// unequivocally it needs to be quoted...
|
||||
return Identifier.toIdentifier( text, true );
|
||||
}
|
||||
|
||||
if ( storesMixedCaseQuotedIdentifiers && isMixedCase ) {
|
||||
return Identifier.toIdentifier( text, true );
|
||||
}
|
||||
|
||||
if ( storesLowerCaseQuotedIdentifiers && isLowerCase ) {
|
||||
return Identifier.toIdentifier( text, true );
|
||||
}
|
||||
|
||||
if ( storesUpperCaseQuotedIdentifiers && isUpperCase ) {
|
||||
return Identifier.toIdentifier( text, true );
|
||||
}
|
||||
|
||||
return Identifier.toIdentifier( text );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier toIdentifier(String text, boolean quoted) {
|
||||
return globallyQuoteIdentifiers
|
||||
? Identifier.toIdentifier( text, true )
|
||||
: Identifier.toIdentifier( text, quoted );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier fromMetaDataSchemaName(String schemaName) {
|
||||
if ( schemaName == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ( jdbcEnvironment.getCurrentSchema() == null
|
||||
|| schemaName.equals( jdbcEnvironment.getCurrentSchema().getText() ) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return toIdentifier( schemaName );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier fromMetaDataObjectName(String objectName) {
|
||||
if ( objectName == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return toIdentifier( objectName );
|
||||
}
|
||||
}
|
|
@ -21,11 +21,13 @@
|
|||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.engine.jdbc.spi;
|
||||
package org.hibernate.engine.jdbc.env.spi;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.engine.jdbc.spi.TypeInfo;
|
||||
|
||||
/**
|
||||
* Information extracted from {@link java.sql.DatabaseMetaData} regarding what the JDBC driver reports as
|
||||
* being supported or not. Obviously {@link java.sql.DatabaseMetaData} reports many things, these are a few in
|
||||
|
@ -36,22 +38,11 @@ import java.util.Set;
|
|||
@SuppressWarnings( {"UnusedDeclaration"})
|
||||
public interface ExtractedDatabaseMetaData {
|
||||
/**
|
||||
* Which specification do the reported SQLState codes follow?
|
||||
* Obtain the JDBC Environment from which this metadata came.
|
||||
*
|
||||
* @return The JDBC environment
|
||||
*/
|
||||
public enum SQLStateType {
|
||||
/**
|
||||
* The reported codes follow the X/Open spec
|
||||
*/
|
||||
XOpen,
|
||||
/**
|
||||
* The reported codes follow the SQL spec
|
||||
*/
|
||||
SQL99,
|
||||
/**
|
||||
* It is unknown. Might follow another spec completely, or be a mixture.
|
||||
*/
|
||||
UNKOWN
|
||||
}
|
||||
public JdbcEnvironment getJdbcEnvironment();
|
||||
|
||||
/**
|
||||
* Does the driver report supporting named parameters?
|
||||
|
@ -116,15 +107,6 @@ public interface ExtractedDatabaseMetaData {
|
|||
*/
|
||||
public boolean doesDataDefinitionCauseTransactionCommit();
|
||||
|
||||
/**
|
||||
* Get the list of extra keywords (beyond standard SQL92 keywords) reported by the driver.
|
||||
*
|
||||
* @return The extra keywords used by this database.
|
||||
*
|
||||
* @see java.sql.DatabaseMetaData#getSQLKeywords()
|
||||
*/
|
||||
public Set<String> getExtraKeywords();
|
||||
|
||||
/**
|
||||
* Retrieve the type of codes the driver says it uses for {@code SQLState}. They might follow either
|
||||
* the X/Open standard or the SQL92 standard.
|
||||
|
@ -143,27 +125,4 @@ public interface ExtractedDatabaseMetaData {
|
|||
* @see java.sql.DatabaseMetaData#locatorsUpdateCopy()
|
||||
*/
|
||||
public boolean doesLobLocatorUpdateCopy();
|
||||
|
||||
/**
|
||||
* Retrieve the name of the schema in effect when we connected to the database.
|
||||
*
|
||||
* @return The schema name
|
||||
*/
|
||||
public String getConnectionSchemaName();
|
||||
|
||||
/**
|
||||
* Retrieve the name of the catalog in effect when we connected to the database.
|
||||
*
|
||||
* @return The catalog name
|
||||
*/
|
||||
public String getConnectionCatalogName();
|
||||
|
||||
/**
|
||||
* Set of type info reported by the driver.
|
||||
*
|
||||
* @return The type information obtained from the driver.
|
||||
*
|
||||
* @see java.sql.DatabaseMetaData#getTypeInfo()
|
||||
*/
|
||||
public LinkedHashSet<TypeInfo> getTypeInfoSet();
|
||||
}
|
61
hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/IdentifierHelper.java
vendored
Normal file
61
hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/IdentifierHelper.java
vendored
Normal file
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, Red Hat Inc. 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 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.engine.jdbc.env.spi;
|
||||
|
||||
import org.hibernate.metamodel.spi.relational.Identifier;
|
||||
|
||||
/**
|
||||
* Helper for handling {@link Identifier} instances.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface IdentifierHelper {
|
||||
/**
|
||||
* Generate an {@link Identifier} instance from its simple name
|
||||
*
|
||||
* @param text The text
|
||||
*
|
||||
* @return The identifier form of the name.
|
||||
*/
|
||||
public Identifier toIdentifier(String text);
|
||||
|
||||
/**
|
||||
* Generate an {@link Identifier} instance from its simple name and explicitly whether it is quoted or not
|
||||
* (although note that 'globally quoted identifiers' setting can still cause returned Identifiers to be quoted
|
||||
* even if {@code false} is passed in here).
|
||||
*
|
||||
* @param text The name
|
||||
* @param quoted Is the identifier to be quoted explicitly.
|
||||
*
|
||||
* @return The identifier form of the name.
|
||||
*/
|
||||
public Identifier toIdentifier(String text, boolean quoted);
|
||||
|
||||
public String toMetaDataCatalogName(Identifier identifier);
|
||||
public String toMetaDataSchemaName(Identifier identifier);
|
||||
public String toMetaDataObjectName(Identifier identifier);
|
||||
public Identifier fromMetaDataCatalogName(String catalogName);
|
||||
public Identifier fromMetaDataSchemaName(String schemaName);
|
||||
public Identifier fromMetaDataObjectName(String objectName);
|
||||
}
|
124
hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/JdbcEnvironment.java
vendored
Normal file
124
hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/JdbcEnvironment.java
vendored
Normal file
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, Red Hat Inc. 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 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.engine.jdbc.env.spi;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
|
||||
import org.hibernate.engine.jdbc.spi.TypeInfo;
|
||||
import org.hibernate.metamodel.spi.relational.Identifier;
|
||||
import org.hibernate.service.Service;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
|
||||
/**
|
||||
* Initial look at this concept we keep talking about with merging information from {@link java.sql.DatabaseMetaData}
|
||||
* and {@link org.hibernate.dialect.Dialect}
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface JdbcEnvironment extends Service {
|
||||
/**
|
||||
* Get the dialect for this environment.
|
||||
*
|
||||
* @return The dialect.
|
||||
*/
|
||||
public Dialect getDialect();
|
||||
|
||||
/**
|
||||
* Access to the bits of information we pulled off the JDBC {@link java.sql.DatabaseMetaData} (that did not get
|
||||
* "interpreted" into the helpers/delegates available here).
|
||||
*
|
||||
* @return The values extracted from JDBC DatabaseMetaData
|
||||
*/
|
||||
public ExtractedDatabaseMetaData getExtractedDatabaseMetaData();
|
||||
|
||||
/**
|
||||
* Get the current database catalog. Typically will come from either {@link java.sql.Connection#getCatalog()}
|
||||
* or {@link org.hibernate.cfg.AvailableSettings#DEFAULT_CATALOG}.
|
||||
*
|
||||
* @return The current catalog.
|
||||
*/
|
||||
public Identifier getCurrentCatalog();
|
||||
|
||||
/**
|
||||
* Get the current database catalog. Typically will come from either
|
||||
* {@link SchemaNameResolver#resolveSchemaName(java.sql.Connection, org.hibernate.dialect.Dialect)} or
|
||||
* {@link org.hibernate.cfg.AvailableSettings#DEFAULT_CATALOG}.
|
||||
*
|
||||
* @return The current schema
|
||||
*/
|
||||
public Identifier getCurrentSchema();
|
||||
|
||||
/**
|
||||
* Obtain support for reading and writing qualified object names.
|
||||
*
|
||||
* @return Qualified name support.
|
||||
*/
|
||||
public QualifiedObjectNameSupport getQualifiedObjectNameSupport();
|
||||
|
||||
/**
|
||||
* Obtain the helper for dealing with identifiers in this environment.
|
||||
*
|
||||
* @return The identifier helper.
|
||||
*/
|
||||
public IdentifierHelper getIdentifierHelper();
|
||||
|
||||
/**
|
||||
* Get the complete set of reserved words for this environment. These are significant because they represent
|
||||
* the complete set of terms that MUST BE quoted if used as identifiers. This allows us to apply auto-quoting
|
||||
* in the metamodel based on these terms.
|
||||
*
|
||||
* Note that the standard IdentifierHelper returned by {@link #getIdentifierHelper()} already accounts for
|
||||
* auto-quoting :) yaay!
|
||||
*
|
||||
* @return Reserved words
|
||||
*/
|
||||
public Set<String> getReservedWords();
|
||||
|
||||
/**
|
||||
* Obtain the helper for dealing with JDBC {@link java.sql.SQLException} faults.
|
||||
*
|
||||
* @return This environment's helper.
|
||||
*/
|
||||
public SqlExceptionHelper getSqlExceptionHelper();
|
||||
|
||||
/**
|
||||
* Retrieve the delegate for building {@link org.hibernate.engine.jdbc.LobCreator} instances.
|
||||
*
|
||||
* @return The LobCreator builder.
|
||||
*/
|
||||
public LobCreatorBuilder getLobCreatorBuilder();
|
||||
|
||||
/**
|
||||
* Find type information for the type identified by the given "JDBC type code".
|
||||
*
|
||||
* @param jdbcTypeCode The JDBC type code.
|
||||
*
|
||||
* @return The corresponding type info.
|
||||
*/
|
||||
public TypeInfo getTypeInfoForJdbcCode(int jdbcTypeCode);
|
||||
|
||||
public ServiceRegistry getServiceRegistry();
|
||||
}
|
34
hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/LobCreatorBuilder.java
vendored
Normal file
34
hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/LobCreatorBuilder.java
vendored
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, Red Hat Inc. 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 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.engine.jdbc.env.spi;
|
||||
|
||||
import org.hibernate.engine.jdbc.LobCreationContext;
|
||||
import org.hibernate.engine.jdbc.LobCreator;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface LobCreatorBuilder {
|
||||
LobCreator buildLobCreator(LobCreationContext lobCreationContext);
|
||||
}
|
55
hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/QualifiedObjectNameSupport.java
vendored
Normal file
55
hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/QualifiedObjectNameSupport.java
vendored
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, Red Hat Inc. 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 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.engine.jdbc.env.spi;
|
||||
|
||||
import org.hibernate.metamodel.spi.relational.ObjectName;
|
||||
|
||||
/**
|
||||
* Defines support for reading and writing qualified object names to and from the database. Generally speaking
|
||||
* Hibernate itself only uses {@link #formatName}. Most times when it is "parsing" object names it is coming from
|
||||
* mappings, in which case we expect simple dot-separated syntax and apply {@link ObjectName#parse}
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface QualifiedObjectNameSupport {
|
||||
/**
|
||||
* Performs formatting of an ObjectName to its String representation
|
||||
*
|
||||
* @param objectName The object name to be formatted.
|
||||
*
|
||||
* @return The dialect specific string form of the name.
|
||||
*/
|
||||
public String formatName(ObjectName objectName);
|
||||
|
||||
/**
|
||||
* Parse a String representation of an Object name to its ObjectName. Note that this specifically
|
||||
* attempts to parse the text as if coming from the database. Mapping forms always use
|
||||
* the form {@code <schema>.<catalog>.<name>}, parsing such names should just use {@link ObjectName#parse}
|
||||
*
|
||||
* @param text The object name text
|
||||
*
|
||||
* @return The parsed ObjectName
|
||||
*/
|
||||
public ObjectName parseName(String text);
|
||||
}
|
46
hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/SQLStateType.java
vendored
Normal file
46
hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/SQLStateType.java
vendored
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, Red Hat Inc. 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 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.engine.jdbc.env.spi;
|
||||
|
||||
/**
|
||||
* Enum interpretation of the valid values from {@link java.sql.DatabaseMetaData#getSQLStateType()}
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public enum SQLStateType {
|
||||
/**
|
||||
* The reported codes follow the X/Open spec
|
||||
*/
|
||||
XOpen,
|
||||
/**
|
||||
* The reported codes follow the SQL spec
|
||||
*/
|
||||
SQL99,
|
||||
/**
|
||||
* It is unknown. Might follow another spec completely, or be a mixture.
|
||||
*/
|
||||
UNKNOWN
|
||||
}
|
||||
|
||||
|
46
hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/SchemaNameResolver.java
vendored
Normal file
46
hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/SchemaNameResolver.java
vendored
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2010, Red Hat Inc. 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 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.engine.jdbc.env.spi;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.hibernate.dialect.Dialect;
|
||||
|
||||
/**
|
||||
* Contract for resolving the schema of a {@link Connection}.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface SchemaNameResolver {
|
||||
/**
|
||||
* Given a JDBC {@link Connection}, resolve the name of the schema (if one) to which it connects.
|
||||
*
|
||||
* @param connection The JDBC connection
|
||||
* @param dialect The Dialect
|
||||
*
|
||||
* @return The name of the schema (may be null).
|
||||
*/
|
||||
public String resolveSchemaName(Connection connection, Dialect dialect) throws SQLException;
|
||||
}
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, Red Hat Inc. 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 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.engine.jdbc.env.spi;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.metamodel.spi.relational.IllegalIdentifierException;
|
||||
import org.hibernate.metamodel.spi.relational.ObjectName;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class StandardQualifiedObjectNameSupportImpl implements QualifiedObjectNameSupport {
|
||||
public static final char DEFAULT_QUOTE_START = '\'';
|
||||
public static final char DEFAULT_QUOTE_END = '\'';
|
||||
public static final String DEFAULT_CATALOG_SEPARATOR = ".";
|
||||
|
||||
private final String catalogSeparator;
|
||||
private final boolean catalogAfterName;
|
||||
private final char quotedStart;
|
||||
private final char quotedEnd;
|
||||
|
||||
private final Pattern splitPattern;
|
||||
|
||||
public StandardQualifiedObjectNameSupportImpl(
|
||||
String catalogSeparator,
|
||||
boolean catalogAfterName,
|
||||
char quotedStart,
|
||||
char quotedEnd) {
|
||||
this.catalogSeparator = catalogSeparator;
|
||||
this.catalogAfterName = catalogAfterName;
|
||||
this.quotedStart = quotedStart;
|
||||
this.quotedEnd = quotedEnd;
|
||||
|
||||
splitPattern = ".".equals( catalogSeparator )
|
||||
? Pattern.compile( Pattern.quote( "." ) )
|
||||
: Pattern.compile( "[\\." + catalogSeparator + "]" );
|
||||
}
|
||||
|
||||
public StandardQualifiedObjectNameSupportImpl() {
|
||||
this( DEFAULT_CATALOG_SEPARATOR, false, DEFAULT_QUOTE_START, DEFAULT_QUOTE_END );
|
||||
}
|
||||
|
||||
public StandardQualifiedObjectNameSupportImpl(String catalogSeparator, boolean catalogAfterName, Dialect dialect) {
|
||||
this( catalogSeparator, catalogAfterName, dialect.openQuote(), dialect.closeQuote() );
|
||||
}
|
||||
|
||||
public StandardQualifiedObjectNameSupportImpl(Dialect dialect) {
|
||||
this( DEFAULT_CATALOG_SEPARATOR, false, dialect );
|
||||
}
|
||||
|
||||
public StandardQualifiedObjectNameSupportImpl(String catalogSeparator, boolean catalogAfterName) {
|
||||
this( catalogSeparator, catalogAfterName, DEFAULT_QUOTE_START, DEFAULT_QUOTE_END );
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String formatName(ObjectName objectName) {
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
if ( ! catalogAfterName ) {
|
||||
if ( objectName.getCatalog() != null ) {
|
||||
buffer.append( objectName.getCatalog().getText( quotedStart, quotedEnd ) )
|
||||
.append( catalogSeparator );
|
||||
}
|
||||
}
|
||||
|
||||
if ( objectName.getSchema() != null ) {
|
||||
buffer.append( objectName.getSchema().getText( quotedStart, quotedEnd ) ).append( '.' );
|
||||
}
|
||||
buffer.append( objectName.getName().getText( quotedStart, quotedEnd ) );
|
||||
|
||||
if ( catalogAfterName ) {
|
||||
if ( objectName.getCatalog() != null ) {
|
||||
buffer.append( catalogSeparator )
|
||||
.append( objectName.getCatalog().getText( quotedStart, quotedEnd ) );
|
||||
}
|
||||
}
|
||||
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectName parseName(String text) {
|
||||
if ( text == null ) {
|
||||
throw new IllegalIdentifierException( "Object name must be specified" );
|
||||
}
|
||||
|
||||
String catalogName = null;
|
||||
String schemaName = null;
|
||||
String localObjectName;
|
||||
|
||||
final String[] tokens = splitPattern.split( text );
|
||||
if ( tokens.length == 0 || tokens.length == 1 ) {
|
||||
// we have just a local name...
|
||||
localObjectName = text;
|
||||
}
|
||||
else if ( tokens.length == 2 ) {
|
||||
// we have 'something.name', no real way to know if something is a catalog or schema
|
||||
// but thats ok based on the way we implement Database... so assume schema
|
||||
schemaName = tokens[0];
|
||||
localObjectName = tokens[1];
|
||||
}
|
||||
else if ( tokens.length == 3 ) {
|
||||
if ( catalogAfterName ) {
|
||||
schemaName = tokens[0];
|
||||
localObjectName = tokens[1];
|
||||
catalogName = tokens[2];
|
||||
}
|
||||
else {
|
||||
catalogName = tokens[0];
|
||||
schemaName = tokens[1];
|
||||
localObjectName = tokens[2];
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new HibernateException( "Unable to parse object name: " + text );
|
||||
}
|
||||
|
||||
return new ObjectName( catalogName, schemaName, localObjectName );
|
||||
}
|
||||
}
|
|
@ -23,45 +23,22 @@
|
|||
*/
|
||||
package org.hibernate.engine.jdbc.internal;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.MultiTenancyStrategy;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.jdbc.LobCreationContext;
|
||||
import org.hibernate.engine.jdbc.LobCreator;
|
||||
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
|
||||
import org.hibernate.engine.jdbc.connections.spi.MultiTenantConnectionProvider;
|
||||
import org.hibernate.engine.jdbc.cursor.internal.StandardRefCursorSupport;
|
||||
import org.hibernate.engine.jdbc.dialect.spi.DatabaseMetaDataDialectResolutionInfoAdapter;
|
||||
import org.hibernate.engine.jdbc.dialect.spi.DialectFactory;
|
||||
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
|
||||
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfoSource;
|
||||
import org.hibernate.engine.jdbc.spi.ExtractedDatabaseMetaData;
|
||||
import org.hibernate.engine.jdbc.spi.JdbcConnectionAccess;
|
||||
import org.hibernate.engine.jdbc.env.spi.ExtractedDatabaseMetaData;
|
||||
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||
import org.hibernate.engine.jdbc.spi.ResultSetWrapper;
|
||||
import org.hibernate.engine.jdbc.spi.SchemaNameResolver;
|
||||
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
|
||||
import org.hibernate.engine.jdbc.spi.SqlStatementLogger;
|
||||
import org.hibernate.engine.jdbc.spi.TypeInfo;
|
||||
import org.hibernate.exception.internal.SQLExceptionTypeDelegate;
|
||||
import org.hibernate.exception.internal.SQLStateConversionDelegate;
|
||||
import org.hibernate.exception.internal.StandardSQLExceptionConverter;
|
||||
import org.hibernate.exception.spi.SQLExceptionConverter;
|
||||
import org.hibernate.internal.CoreLogging;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.ReflectHelper;
|
||||
import org.hibernate.internal.util.config.ConfigurationHelper;
|
||||
import org.hibernate.service.spi.Configurable;
|
||||
import org.hibernate.service.spi.ServiceRegistryAwareService;
|
||||
|
@ -76,13 +53,10 @@ public class JdbcServicesImpl implements JdbcServices, ServiceRegistryAwareServi
|
|||
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( JdbcServicesImpl.class );
|
||||
|
||||
private ServiceRegistryImplementor serviceRegistry;
|
||||
private JdbcEnvironment jdbcEnvironment;
|
||||
|
||||
private Dialect dialect;
|
||||
private ConnectionProvider connectionProvider;
|
||||
private SqlStatementLogger sqlStatementLogger;
|
||||
private SqlExceptionHelper sqlExceptionHelper;
|
||||
private ExtractedDatabaseMetaData extractedMetaDataSupport;
|
||||
private LobCreatorBuilder lobCreatorBuilder;
|
||||
|
||||
@Override
|
||||
public void injectServices(ServiceRegistryImplementor serviceRegistry) {
|
||||
|
@ -91,389 +65,17 @@ public class JdbcServicesImpl implements JdbcServices, ServiceRegistryAwareServi
|
|||
|
||||
@Override
|
||||
public void configure(Map configValues) {
|
||||
final JdbcConnectionAccess jdbcConnectionAccess = buildJdbcConnectionAccess( configValues );
|
||||
final DialectFactory dialectFactory = serviceRegistry.getService( DialectFactory.class );
|
||||
this.jdbcEnvironment = serviceRegistry.getService( JdbcEnvironment.class );
|
||||
|
||||
Dialect dialect = null;
|
||||
LobCreatorBuilder lobCreatorBuilder = null;
|
||||
|
||||
boolean metaSupportsRefCursors = false;
|
||||
boolean metaSupportsNamedParams = false;
|
||||
boolean metaSupportsScrollable = false;
|
||||
boolean metaSupportsGetGeneratedKeys = false;
|
||||
boolean metaSupportsBatchUpdates = false;
|
||||
boolean metaReportsDDLCausesTxnCommit = false;
|
||||
boolean metaReportsDDLInTxnSupported = true;
|
||||
String extraKeywordsString = "";
|
||||
int sqlStateType = -1;
|
||||
boolean lobLocatorUpdateCopy = false;
|
||||
String catalogName = null;
|
||||
String schemaName = null;
|
||||
final LinkedHashSet<TypeInfo> typeInfoSet = new LinkedHashSet<TypeInfo>();
|
||||
|
||||
// 'hibernate.temp.use_jdbc_metadata_defaults' is a temporary magic value.
|
||||
// The need for it is intended to be alleviated with future development, thus it is
|
||||
// not defined as an Environment constant...
|
||||
//
|
||||
// it is used to control whether we should consult the JDBC metadata to determine
|
||||
// certain Settings default values; it is useful to *not* do this when the database
|
||||
// may not be available (mainly in tools usage).
|
||||
final boolean useJdbcMetadata = ConfigurationHelper.getBoolean( "hibernate.temp.use_jdbc_metadata_defaults", configValues, true );
|
||||
if ( useJdbcMetadata ) {
|
||||
try {
|
||||
final Connection connection = jdbcConnectionAccess.obtainConnection();
|
||||
try {
|
||||
final DatabaseMetaData meta = connection.getMetaData();
|
||||
if ( LOG.isDebugEnabled() ) {
|
||||
LOG.debugf(
|
||||
"Database ->\n"
|
||||
+ " name : %s\n"
|
||||
+ " version : %s\n"
|
||||
+ " major : %s\n"
|
||||
+ " minor : %s",
|
||||
meta.getDatabaseProductName(),
|
||||
meta.getDatabaseProductVersion(),
|
||||
meta.getDatabaseMajorVersion(),
|
||||
meta.getDatabaseMinorVersion()
|
||||
);
|
||||
LOG.debugf(
|
||||
"Driver ->\n"
|
||||
+ " name : %s\n"
|
||||
+ " version : %s\n"
|
||||
+ " major : %s\n"
|
||||
+ " minor : %s",
|
||||
meta.getDriverName(),
|
||||
meta.getDriverVersion(),
|
||||
meta.getDriverMajorVersion(),
|
||||
meta.getDriverMinorVersion()
|
||||
);
|
||||
LOG.debugf( "JDBC version : %s.%s", meta.getJDBCMajorVersion(), meta.getJDBCMinorVersion() );
|
||||
}
|
||||
|
||||
metaSupportsRefCursors = StandardRefCursorSupport.supportsRefCursors( meta );
|
||||
metaSupportsNamedParams = meta.supportsNamedParameters();
|
||||
metaSupportsScrollable = meta.supportsResultSetType( ResultSet.TYPE_SCROLL_INSENSITIVE );
|
||||
metaSupportsBatchUpdates = meta.supportsBatchUpdates();
|
||||
metaReportsDDLCausesTxnCommit = meta.dataDefinitionCausesTransactionCommit();
|
||||
metaReportsDDLInTxnSupported = !meta.dataDefinitionIgnoredInTransactions();
|
||||
metaSupportsGetGeneratedKeys = meta.supportsGetGeneratedKeys();
|
||||
extraKeywordsString = meta.getSQLKeywords();
|
||||
sqlStateType = meta.getSQLStateType();
|
||||
lobLocatorUpdateCopy = meta.locatorsUpdateCopy();
|
||||
typeInfoSet.addAll( TypeInfo.extractTypeInfo( meta ) );
|
||||
|
||||
dialect = dialectFactory.buildDialect(
|
||||
configValues,
|
||||
new DialectResolutionInfoSource() {
|
||||
@Override
|
||||
public DialectResolutionInfo getDialectResolutionInfo() {
|
||||
try {
|
||||
return new DatabaseMetaDataDialectResolutionInfoAdapter( connection.getMetaData() );
|
||||
}
|
||||
catch ( SQLException sqlException ) {
|
||||
throw new HibernateException(
|
||||
"Unable to access java.sql.DatabaseMetaData to determine appropriate Dialect to use",
|
||||
sqlException
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
catalogName = connection.getCatalog();
|
||||
final SchemaNameResolver schemaNameResolver = determineExplicitSchemaNameResolver( configValues );
|
||||
if ( schemaNameResolver == null ) {
|
||||
// todo : add dialect method
|
||||
// schemaNameResolver = dialect.getSchemaNameResolver();
|
||||
}
|
||||
if ( schemaNameResolver != null ) {
|
||||
schemaName = schemaNameResolver.resolveSchemaName( connection );
|
||||
}
|
||||
lobCreatorBuilder = new LobCreatorBuilder( configValues, connection );
|
||||
}
|
||||
catch ( SQLException sqle ) {
|
||||
LOG.unableToObtainConnectionMetadata( sqle.getMessage() );
|
||||
}
|
||||
finally {
|
||||
if ( connection != null ) {
|
||||
jdbcConnectionAccess.releaseConnection( connection );
|
||||
}
|
||||
}
|
||||
}
|
||||
catch ( SQLException sqle ) {
|
||||
LOG.unableToObtainConnectionToQueryMetadata( sqle.getMessage() );
|
||||
dialect = dialectFactory.buildDialect( configValues, null );
|
||||
}
|
||||
catch ( UnsupportedOperationException uoe ) {
|
||||
// user supplied JDBC connections
|
||||
dialect = dialectFactory.buildDialect( configValues, null );
|
||||
}
|
||||
}
|
||||
else {
|
||||
dialect = dialectFactory.buildDialect( configValues, null );
|
||||
}
|
||||
final MultiTenancyStrategy multiTenancyStrategy = MultiTenancyStrategy.determineMultiTenancyStrategy( configValues );
|
||||
this.connectionProvider = MultiTenancyStrategy.NONE == multiTenancyStrategy ?
|
||||
serviceRegistry.getService( ConnectionProvider.class ) :
|
||||
null;
|
||||
|
||||
final boolean showSQL = ConfigurationHelper.getBoolean( Environment.SHOW_SQL, configValues, false );
|
||||
final boolean formatSQL = ConfigurationHelper.getBoolean( Environment.FORMAT_SQL, configValues, false );
|
||||
|
||||
this.dialect = dialect;
|
||||
this.lobCreatorBuilder = (
|
||||
lobCreatorBuilder == null ?
|
||||
new LobCreatorBuilder( configValues, null ) :
|
||||
lobCreatorBuilder
|
||||
);
|
||||
|
||||
this.sqlStatementLogger = new SqlStatementLogger( showSQL, formatSQL );
|
||||
|
||||
this.extractedMetaDataSupport = new ExtractedDatabaseMetaDataImpl(
|
||||
metaSupportsRefCursors,
|
||||
metaSupportsNamedParams,
|
||||
metaSupportsScrollable,
|
||||
metaSupportsGetGeneratedKeys,
|
||||
metaSupportsBatchUpdates,
|
||||
metaReportsDDLInTxnSupported,
|
||||
metaReportsDDLCausesTxnCommit,
|
||||
parseKeywords( extraKeywordsString ),
|
||||
parseSQLStateType( sqlStateType ),
|
||||
lobLocatorUpdateCopy,
|
||||
schemaName,
|
||||
catalogName,
|
||||
typeInfoSet
|
||||
);
|
||||
|
||||
SQLExceptionConverter sqlExceptionConverter = dialect.buildSQLExceptionConverter();
|
||||
if ( sqlExceptionConverter == null ) {
|
||||
final StandardSQLExceptionConverter converter = new StandardSQLExceptionConverter();
|
||||
sqlExceptionConverter = converter;
|
||||
converter.addDelegate( dialect.buildSQLExceptionConversionDelegate() );
|
||||
converter.addDelegate( new SQLExceptionTypeDelegate( dialect ) );
|
||||
// todo : vary this based on extractedMetaDataSupport.getSqlStateType()
|
||||
converter.addDelegate( new SQLStateConversionDelegate( dialect ) );
|
||||
}
|
||||
this.sqlExceptionHelper = new SqlExceptionHelper( sqlExceptionConverter );
|
||||
}
|
||||
|
||||
private JdbcConnectionAccess buildJdbcConnectionAccess(Map configValues) {
|
||||
final MultiTenancyStrategy multiTenancyStrategy = MultiTenancyStrategy.determineMultiTenancyStrategy( configValues );
|
||||
|
||||
if ( MultiTenancyStrategy.NONE == multiTenancyStrategy ) {
|
||||
connectionProvider = serviceRegistry.getService( ConnectionProvider.class );
|
||||
return new ConnectionProviderJdbcConnectionAccess( connectionProvider );
|
||||
}
|
||||
else {
|
||||
connectionProvider = null;
|
||||
final MultiTenantConnectionProvider multiTenantConnectionProvider = serviceRegistry.getService( MultiTenantConnectionProvider.class );
|
||||
return new MultiTenantConnectionProviderJdbcConnectionAccess( multiTenantConnectionProvider );
|
||||
}
|
||||
}
|
||||
|
||||
private static class ConnectionProviderJdbcConnectionAccess implements JdbcConnectionAccess {
|
||||
private final ConnectionProvider connectionProvider;
|
||||
|
||||
public ConnectionProviderJdbcConnectionAccess(ConnectionProvider connectionProvider) {
|
||||
this.connectionProvider = connectionProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection obtainConnection() throws SQLException {
|
||||
return connectionProvider.getConnection();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void releaseConnection(Connection connection) throws SQLException {
|
||||
connectionProvider.closeConnection( connection );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsAggressiveRelease() {
|
||||
return connectionProvider.supportsAggressiveRelease();
|
||||
}
|
||||
}
|
||||
|
||||
private static class MultiTenantConnectionProviderJdbcConnectionAccess implements JdbcConnectionAccess {
|
||||
private final MultiTenantConnectionProvider connectionProvider;
|
||||
|
||||
public MultiTenantConnectionProviderJdbcConnectionAccess(MultiTenantConnectionProvider connectionProvider) {
|
||||
this.connectionProvider = connectionProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection obtainConnection() throws SQLException {
|
||||
return connectionProvider.getAnyConnection();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void releaseConnection(Connection connection) throws SQLException {
|
||||
connectionProvider.releaseAnyConnection( connection );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsAggressiveRelease() {
|
||||
return connectionProvider.supportsAggressiveRelease();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A constant naming the setting used to identify the {@link SchemaNameResolver} to use
|
||||
* <p/>
|
||||
* TODO : add to Environment
|
||||
*/
|
||||
public static final String SCHEMA_NAME_RESOLVER = "hibernate.schema_name_resolver";
|
||||
|
||||
private SchemaNameResolver determineExplicitSchemaNameResolver(Map configValues) {
|
||||
final Object setting = configValues.get( SCHEMA_NAME_RESOLVER );
|
||||
if ( SchemaNameResolver.class.isInstance( setting ) ) {
|
||||
return (SchemaNameResolver) setting;
|
||||
}
|
||||
|
||||
final String resolverClassName = (String) setting;
|
||||
if ( resolverClassName != null ) {
|
||||
try {
|
||||
final Class resolverClass = ReflectHelper.classForName( resolverClassName, getClass() );
|
||||
return (SchemaNameResolver) ReflectHelper.getDefaultConstructor( resolverClass ).newInstance();
|
||||
}
|
||||
catch ( ClassNotFoundException e ) {
|
||||
LOG.unableToLocateConfiguredSchemaNameResolver( resolverClassName, e.toString() );
|
||||
}
|
||||
catch ( InvocationTargetException e ) {
|
||||
LOG.unableToInstantiateConfiguredSchemaNameResolver( resolverClassName, e.getTargetException().toString() );
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
LOG.unableToInstantiateConfiguredSchemaNameResolver( resolverClassName, e.toString() );
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Set<String> parseKeywords(String extraKeywordsString) {
|
||||
final Set<String> keywordSet = new HashSet<String>();
|
||||
keywordSet.addAll( Arrays.asList( extraKeywordsString.split( "," ) ) );
|
||||
return keywordSet;
|
||||
}
|
||||
|
||||
private ExtractedDatabaseMetaData.SQLStateType parseSQLStateType(int sqlStateType) {
|
||||
switch ( sqlStateType ) {
|
||||
case DatabaseMetaData.sqlStateSQL99 : {
|
||||
return ExtractedDatabaseMetaData.SQLStateType.SQL99;
|
||||
}
|
||||
case DatabaseMetaData.sqlStateXOpen : {
|
||||
return ExtractedDatabaseMetaData.SQLStateType.XOpen;
|
||||
}
|
||||
default : {
|
||||
return ExtractedDatabaseMetaData.SQLStateType.UNKOWN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class ExtractedDatabaseMetaDataImpl implements ExtractedDatabaseMetaData {
|
||||
private final boolean supportsRefCursors;
|
||||
private final boolean supportsNamedParameters;
|
||||
private final boolean supportsScrollableResults;
|
||||
private final boolean supportsGetGeneratedKeys;
|
||||
private final boolean supportsBatchUpdates;
|
||||
private final boolean supportsDataDefinitionInTransaction;
|
||||
private final boolean doesDataDefinitionCauseTransactionCommit;
|
||||
private final Set<String> extraKeywords;
|
||||
private final SQLStateType sqlStateType;
|
||||
private final boolean lobLocatorUpdateCopy;
|
||||
private final String connectionSchemaName;
|
||||
private final String connectionCatalogName;
|
||||
private final LinkedHashSet<TypeInfo> typeInfoSet;
|
||||
|
||||
private ExtractedDatabaseMetaDataImpl(
|
||||
boolean supportsRefCursors,
|
||||
boolean supportsNamedParameters,
|
||||
boolean supportsScrollableResults,
|
||||
boolean supportsGetGeneratedKeys,
|
||||
boolean supportsBatchUpdates,
|
||||
boolean supportsDataDefinitionInTransaction,
|
||||
boolean doesDataDefinitionCauseTransactionCommit,
|
||||
Set<String> extraKeywords,
|
||||
SQLStateType sqlStateType,
|
||||
boolean lobLocatorUpdateCopy,
|
||||
String connectionSchemaName,
|
||||
String connectionCatalogName,
|
||||
LinkedHashSet<TypeInfo> typeInfoSet) {
|
||||
this.supportsRefCursors = supportsRefCursors;
|
||||
this.supportsNamedParameters = supportsNamedParameters;
|
||||
this.supportsScrollableResults = supportsScrollableResults;
|
||||
this.supportsGetGeneratedKeys = supportsGetGeneratedKeys;
|
||||
this.supportsBatchUpdates = supportsBatchUpdates;
|
||||
this.supportsDataDefinitionInTransaction = supportsDataDefinitionInTransaction;
|
||||
this.doesDataDefinitionCauseTransactionCommit = doesDataDefinitionCauseTransactionCommit;
|
||||
this.extraKeywords = extraKeywords;
|
||||
this.sqlStateType = sqlStateType;
|
||||
this.lobLocatorUpdateCopy = lobLocatorUpdateCopy;
|
||||
this.connectionSchemaName = connectionSchemaName;
|
||||
this.connectionCatalogName = connectionCatalogName;
|
||||
this.typeInfoSet = typeInfoSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsRefCursors() {
|
||||
return supportsRefCursors;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsNamedParameters() {
|
||||
return supportsNamedParameters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsScrollableResults() {
|
||||
return supportsScrollableResults;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsGetGeneratedKeys() {
|
||||
return supportsGetGeneratedKeys;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsBatchUpdates() {
|
||||
return supportsBatchUpdates;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsDataDefinitionInTransaction() {
|
||||
return supportsDataDefinitionInTransaction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doesDataDefinitionCauseTransactionCommit() {
|
||||
return doesDataDefinitionCauseTransactionCommit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getExtraKeywords() {
|
||||
return extraKeywords;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLStateType getSqlStateType() {
|
||||
return sqlStateType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doesLobLocatorUpdateCopy() {
|
||||
return lobLocatorUpdateCopy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getConnectionSchemaName() {
|
||||
return connectionSchemaName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getConnectionCatalogName() {
|
||||
return connectionCatalogName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LinkedHashSet<TypeInfo> getTypeInfoSet() {
|
||||
return typeInfoSet;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -488,26 +90,30 @@ public class JdbcServicesImpl implements JdbcServices, ServiceRegistryAwareServi
|
|||
|
||||
@Override
|
||||
public SqlExceptionHelper getSqlExceptionHelper() {
|
||||
return sqlExceptionHelper;
|
||||
return jdbcEnvironment == null ? null : jdbcEnvironment.getSqlExceptionHelper();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialect getDialect() {
|
||||
return dialect;
|
||||
return jdbcEnvironment == null ? null : jdbcEnvironment.getDialect();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExtractedDatabaseMetaData getExtractedMetaDataSupport() {
|
||||
return extractedMetaDataSupport;
|
||||
}
|
||||
return jdbcEnvironment == null ? null : jdbcEnvironment.getExtractedDatabaseMetaData(); }
|
||||
|
||||
@Override
|
||||
public LobCreator getLobCreator(LobCreationContext lobCreationContext) {
|
||||
return lobCreatorBuilder.buildLobCreator( lobCreationContext );
|
||||
return jdbcEnvironment == null ? null : jdbcEnvironment.getLobCreatorBuilder().buildLobCreator( lobCreationContext );
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResultSetWrapper getResultSetWrapper() {
|
||||
return ResultSetWrapperImpl.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JdbcEnvironment getJdbcEnvironment() {
|
||||
return jdbcEnvironment;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,8 @@ import org.hibernate.dialect.Dialect;
|
|||
import org.hibernate.engine.jdbc.LobCreationContext;
|
||||
import org.hibernate.engine.jdbc.LobCreator;
|
||||
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
|
||||
import org.hibernate.engine.jdbc.env.spi.ExtractedDatabaseMetaData;
|
||||
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
||||
import org.hibernate.service.Service;
|
||||
|
||||
/**
|
||||
|
@ -90,4 +92,6 @@ public interface JdbcServices extends Service {
|
|||
* @return The ResultSet wrapper.
|
||||
*/
|
||||
public ResultSetWrapper getResultSetWrapper();
|
||||
|
||||
public JdbcEnvironment getJdbcEnvironment();
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ package org.hibernate.engine.spi;
|
|||
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.internal.CacheImpl;
|
||||
import org.hibernate.metamodel.source.MetadataImplementor;
|
||||
import org.hibernate.metamodel.spi.MetadataImplementor;
|
||||
import org.hibernate.service.spi.ServiceRegistryImplementor;
|
||||
import org.hibernate.service.spi.SessionFactoryServiceInitiator;
|
||||
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, Red Hat Inc. 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 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.engine.spi;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public class SyntheticAttributeHelper {
|
||||
public static final String SYNTHETIC_COMPOSITE_ID_ATTRIBUTE_NAME = "_identifierMapper";
|
||||
|
||||
private static final String BACKREF_ATTRIBUTE_NAME_PREFIX = "_";
|
||||
private static final String BACKREF_ATTRIBUTE_NAME_SUFFIX = "BackRef";
|
||||
private static final String INDEX_BACKREF_ATTRIBUTE_NAME_SUFFIX = "IndexBackRef";
|
||||
|
||||
|
||||
public static String createBackRefAttributeName(String pluralAttributeRole) {
|
||||
return createSyntheticAttributeName(
|
||||
pluralAttributeRole,
|
||||
BACKREF_ATTRIBUTE_NAME_PREFIX,
|
||||
BACKREF_ATTRIBUTE_NAME_SUFFIX
|
||||
);
|
||||
}
|
||||
|
||||
public static String createIndexBackRefAttributeName(String pluralAttributeRole) {
|
||||
return createSyntheticAttributeName(
|
||||
pluralAttributeRole,
|
||||
BACKREF_ATTRIBUTE_NAME_PREFIX,
|
||||
INDEX_BACKREF_ATTRIBUTE_NAME_SUFFIX
|
||||
);
|
||||
}
|
||||
|
||||
private static String createSyntheticAttributeName(String attributeRole, String prefix, String suffix) {
|
||||
return new StringBuilder(
|
||||
prefix.length() + attributeRole.length() + suffix.length() )
|
||||
.append( prefix )
|
||||
.append( attributeRole )
|
||||
.append( suffix )
|
||||
.toString();
|
||||
}
|
||||
|
||||
}
|
|
@ -211,14 +211,14 @@ public class DefaultMergeEventListener extends AbstractSaveEventListener impleme
|
|||
// copy created before we actually copy
|
||||
//cascadeOnMerge(event, persister, entity, copyCache, Cascades.CASCADE_BEFORE_MERGE);
|
||||
super.cascadeBeforeSave( source, persister, entity, copyCache );
|
||||
copyValues( persister, entity, copy, source, copyCache, ForeignKeyDirection.FOREIGN_KEY_FROM_PARENT );
|
||||
copyValues( persister, entity, copy, source, copyCache, ForeignKeyDirection.FROM_PARENT );
|
||||
|
||||
saveTransientEntity( copy, entityName, event.getRequestedId(), source, copyCache );
|
||||
|
||||
// cascade first, so that all unsaved objects get their
|
||||
// copy created before we actually copy
|
||||
super.cascadeAfterSave( source, persister, entity, copyCache );
|
||||
copyValues( persister, entity, copy, source, copyCache, ForeignKeyDirection.FOREIGN_KEY_TO_PARENT );
|
||||
copyValues( persister, entity, copy, source, copyCache, ForeignKeyDirection.TO_PARENT );
|
||||
|
||||
event.setResult( copy );
|
||||
}
|
||||
|
@ -391,7 +391,7 @@ public class DefaultMergeEventListener extends AbstractSaveEventListener impleme
|
|||
|
||||
final Object[] copiedValues;
|
||||
|
||||
if ( foreignKeyDirection == ForeignKeyDirection.FOREIGN_KEY_TO_PARENT ) {
|
||||
if ( foreignKeyDirection == ForeignKeyDirection.TO_PARENT ) {
|
||||
// this is the second pass through on a merge op, so here we limit the
|
||||
// replacement to associations types (value types were already replaced
|
||||
// during the first pass)
|
||||
|
|
|
@ -26,7 +26,7 @@ package org.hibernate.event.service.internal;
|
|||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.event.service.spi.EventListenerRegistry;
|
||||
import org.hibernate.metamodel.source.MetadataImplementor;
|
||||
import org.hibernate.metamodel.spi.MetadataImplementor;
|
||||
import org.hibernate.service.spi.ServiceRegistryImplementor;
|
||||
import org.hibernate.service.spi.SessionFactoryServiceInitiator;
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ import java.util.Properties;
|
|||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.type.Type;
|
||||
|
@ -57,7 +58,7 @@ public class Assigned implements IdentifierGenerator, Configurable {
|
|||
return id;
|
||||
}
|
||||
|
||||
public void configure(Type type, Properties params, Dialect d) throws MappingException {
|
||||
public void configure(Type type, Properties params, Dialect d, ClassLoaderService classLoaderService) throws MappingException {
|
||||
entityName = params.getProperty(ENTITY_NAME);
|
||||
if ( entityName == null ) {
|
||||
throw new MappingException("no entity name");
|
||||
|
|
|
@ -22,9 +22,9 @@
|
|||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.id;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -102,7 +102,7 @@ public class CompositeNestedGeneratedValueGenerator implements IdentifierGenerat
|
|||
}
|
||||
|
||||
private final GenerationContextLocator generationContextLocator;
|
||||
private List generationPlans = new ArrayList();
|
||||
private List<GenerationPlan> generationPlans = new ArrayList<GenerationPlan>();
|
||||
|
||||
public CompositeNestedGeneratedValueGenerator(GenerationContextLocator generationContextLocator) {
|
||||
this.generationContextLocator = generationContextLocator;
|
||||
|
@ -115,19 +115,15 @@ public class CompositeNestedGeneratedValueGenerator implements IdentifierGenerat
|
|||
@Override
|
||||
public Serializable generate(SessionImplementor session, Object object) throws HibernateException {
|
||||
final Serializable context = generationContextLocator.locateGenerationContext( session, object );
|
||||
|
||||
for ( Object generationPlan : generationPlans ) {
|
||||
final GenerationPlan plan = (GenerationPlan) generationPlan;
|
||||
for ( final GenerationPlan plan : generationPlans ) {
|
||||
plan.execute( session, object, context );
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerPersistentGenerators(Map generatorMap) {
|
||||
for ( Object generationPlan : generationPlans ) {
|
||||
final GenerationPlan plan = (GenerationPlan) generationPlan;
|
||||
for(final GenerationPlan plan : generationPlans){
|
||||
plan.registerPersistentGenerators( generatorMap );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ package org.hibernate.id;
|
|||
import java.util.Properties;
|
||||
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
|
@ -43,7 +44,8 @@ public interface Configurable {
|
|||
* This method is called just once, following instantiation.
|
||||
*
|
||||
* @param params param values, keyed by parameter name
|
||||
* @param classLoaderService
|
||||
*/
|
||||
public void configure(Type type, Properties params, Dialect d) throws MappingException;
|
||||
public void configure(Type type, Properties params, Dialect d, ClassLoaderService classLoaderService) throws MappingException;
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, Red Hat Inc. 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 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.id;
|
||||
|
||||
/**
|
||||
* Describes the nature of the entity-defined identifier.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public enum EntityIdentifierNature {
|
||||
/**
|
||||
* A simple identifier. Resolved as a basic type and mapped to a singular, basic attribute. Equivalent of:<ul>
|
||||
* <li>an {@code <id/>} mapping</li>
|
||||
* <li>a single {@code @Id} annotation</li>
|
||||
* </ul>
|
||||
*/
|
||||
SIMPLE,
|
||||
|
||||
/**
|
||||
* What Hibernate used to term an "embedded composite identifier", which is not to be confused with the JPA
|
||||
* term embedded. Resolved as a tuple of basic type values and mapped over multiple singular attributes.
|
||||
* Specifically a composite identifier where there is no single attribute representing the composite value.
|
||||
* Equivalent of:<ul>
|
||||
* <li>
|
||||
* a {@code <composite-id/>} mapping without a specified {@code name} XML-attribute (which would name
|
||||
* the single identifier attribute
|
||||
* </li>
|
||||
* <li>
|
||||
* multiple {@code @Id} annotations
|
||||
* </li>
|
||||
* </ul>
|
||||
*
|
||||
* NOTE : May or may not have a related "lookup identifier class" as indicated by a {@code @IdClass} annotation.
|
||||
*
|
||||
* @see javax.persistence.IdClass
|
||||
*/
|
||||
NON_AGGREGATED_COMPOSITE,
|
||||
|
||||
/**
|
||||
* Composite identifier mapped to a single entity attribute by means of an actual component class used to
|
||||
* aggregate the tuple values.
|
||||
* Equivalent of:<ul>
|
||||
* <li>
|
||||
* a {@code <composite-id/>} mapping naming a single identifier attribute via the {@code name} XML-attribute
|
||||
* </li>
|
||||
* <li>
|
||||
* an {@code @EmbeddedId} annotation
|
||||
* </li>
|
||||
* </ul>
|
||||
*
|
||||
* @see javax.persistence.EmbeddedId
|
||||
*/
|
||||
AGGREGATED_COMPOSITE
|
||||
}
|
|
@ -29,6 +29,7 @@ import java.util.Properties;
|
|||
import org.hibernate.MappingException;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.TransientObjectException;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.internal.ForeignKeys;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
|
@ -80,7 +81,7 @@ public class ForeignGenerator implements IdentifierGenerator, Configurable {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void configure(Type type, Properties params, Dialect d) {
|
||||
public void configure(Type type, Properties params, Dialect d, ClassLoaderService classLoaderService) {
|
||||
propertyName = params.getProperty( "property" );
|
||||
entityName = params.getProperty( ENTITY_NAME );
|
||||
if ( propertyName==null ) {
|
||||
|
|
|
@ -31,6 +31,7 @@ import java.util.Properties;
|
|||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.cfg.ObjectNameNormalizer;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
|
@ -71,7 +72,7 @@ public class IncrementGenerator implements IdentifierGenerator, Configurable {
|
|||
return previousValueHolder.makeValueThenIncrement();
|
||||
}
|
||||
|
||||
public void configure(Type type, Properties params, Dialect dialect) throws MappingException {
|
||||
public void configure(Type type, Properties params, Dialect dialect, ClassLoaderService classLoaderService) throws MappingException {
|
||||
returnClass = type.getReturnedClass();
|
||||
|
||||
ObjectNameNormalizer normalizer =
|
||||
|
|
|
@ -34,6 +34,7 @@ import java.util.Properties;
|
|||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.cfg.ObjectNameNormalizer;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.jdbc.internal.FormatStyle;
|
||||
|
@ -47,7 +48,12 @@ import org.hibernate.internal.CoreMessageLogger;
|
|||
import org.hibernate.internal.util.config.ConfigurationHelper;
|
||||
import org.hibernate.jdbc.AbstractReturningWork;
|
||||
import org.hibernate.jdbc.WorkExecutorVisitable;
|
||||
import org.hibernate.mapping.Table;
|
||||
import org.hibernate.metamodel.spi.relational.Column;
|
||||
import org.hibernate.metamodel.spi.relational.Database;
|
||||
import org.hibernate.metamodel.spi.relational.Identifier;
|
||||
import org.hibernate.metamodel.spi.relational.ObjectName;
|
||||
import org.hibernate.metamodel.spi.relational.Schema;
|
||||
import org.hibernate.metamodel.spi.relational.Table;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
@ -99,7 +105,12 @@ public class MultipleHiLoPerTableGenerator implements PersistentIdentifierGenera
|
|||
private static final String DEFAULT_PK_COLUMN = "sequence_name";
|
||||
private static final String DEFAULT_VALUE_COLUMN = "sequence_next_hi_value";
|
||||
|
||||
private ObjectName qualifiedTableName;
|
||||
private Identifier qualifiedPkColumnName;
|
||||
private Identifier qualifiedValueColumnName;
|
||||
|
||||
private String tableName;
|
||||
private Table table;
|
||||
private String pkColumnName;
|
||||
private String valueColumnName;
|
||||
private String query;
|
||||
|
@ -143,6 +154,15 @@ public class MultipleHiLoPerTableGenerator implements PersistentIdentifierGenera
|
|||
return tableName;
|
||||
}
|
||||
|
||||
/**
|
||||
* The bound Table for this generator.
|
||||
*
|
||||
* @return The table.
|
||||
*/
|
||||
public final Table getTable() {
|
||||
return table;
|
||||
}
|
||||
|
||||
public synchronized Serializable generate(final SessionImplementor session, Object obj) {
|
||||
final SqlStatementLogger statementLogger = session.getFactory().getServiceRegistry()
|
||||
.getService( JdbcServices.class )
|
||||
|
@ -268,35 +288,35 @@ public class MultipleHiLoPerTableGenerator implements PersistentIdentifierGenera
|
|||
}
|
||||
}
|
||||
|
||||
public void configure(Type type, Properties params, Dialect dialect) throws MappingException {
|
||||
public void configure(Type type, Properties params, Dialect dialect, ClassLoaderService classLoaderService) throws MappingException {
|
||||
ObjectNameNormalizer normalizer = ( ObjectNameNormalizer ) params.get( IDENTIFIER_NORMALIZER );
|
||||
|
||||
tableName = normalizer.normalizeIdentifierQuoting( ConfigurationHelper.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 );
|
||||
final String normalizedTableName = tableName;
|
||||
final String normalizedSchemaName = normalizer.normalizeIdentifierQuoting( params.getProperty( SCHEMA ) );
|
||||
final String normalizedCatalogName = normalizer.normalizeIdentifierQuoting( params.getProperty( CATALOG ) );
|
||||
qualifiedTableName = new ObjectName( normalizedCatalogName, normalizedSchemaName, normalizedTableName );
|
||||
tableName = qualifiedTableName.toText( dialect );
|
||||
}
|
||||
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.
|
||||
qualifiedTableName = ObjectName.parse( tableName );
|
||||
}
|
||||
|
||||
pkColumnName = dialect.quote(
|
||||
qualifiedPkColumnName = Identifier.toIdentifier(
|
||||
normalizer.normalizeIdentifierQuoting(
|
||||
ConfigurationHelper.getString( PK_COLUMN_NAME, params, DEFAULT_PK_COLUMN )
|
||||
)
|
||||
);
|
||||
valueColumnName = dialect.quote(
|
||||
pkColumnName = qualifiedPkColumnName.getText( dialect );
|
||||
|
||||
qualifiedValueColumnName = Identifier.toIdentifier(
|
||||
normalizer.normalizeIdentifierQuoting(
|
||||
ConfigurationHelper.getString( VALUE_COLUMN_NAME, params, DEFAULT_VALUE_COLUMN )
|
||||
)
|
||||
);
|
||||
valueColumnName = qualifiedValueColumnName.getText( dialect );
|
||||
|
||||
keySize = ConfigurationHelper.getInt(PK_LENGTH_NAME, params, DEFAULT_PK_LENGTH);
|
||||
String keyValue = ConfigurationHelper.getString(PK_VALUE_NAME, params, params.getProperty(TABLE) );
|
||||
|
||||
|
@ -332,4 +352,20 @@ public class MultipleHiLoPerTableGenerator implements PersistentIdentifierGenera
|
|||
hiloOptimizer = new LegacyHiLoAlgorithmOptimizer( returnClass, maxLo );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerExportables(Database database) {
|
||||
final Dialect dialect = database.getJdbcEnvironment().getDialect();
|
||||
|
||||
final Schema schema = database.getSchemaFor( qualifiedTableName );
|
||||
table = schema.createTable( qualifiedTableName.getName(), qualifiedTableName.getName() );
|
||||
|
||||
final Column pkColumn = table.createColumn( qualifiedPkColumnName );
|
||||
table.getPrimaryKey().addColumn( pkColumn );
|
||||
// todo : leverage TypeInfo-like info from JdbcEnvironment
|
||||
pkColumn.setSqlType( dialect.getTypeName( Types.VARCHAR, keySize, 0, 0 ) );
|
||||
|
||||
final Column valueColumn = table.createColumn( qualifiedValueColumnName );
|
||||
valueColumn.setSqlType( dialect.getTypeName( Types.INTEGER ) );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
package org.hibernate.id;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.metamodel.spi.relational.ExportableProducer;
|
||||
|
||||
/**
|
||||
* An <tt>IdentifierGenerator</tt> that requires creation of database objects.
|
||||
|
@ -35,7 +36,7 @@ import org.hibernate.dialect.Dialect;
|
|||
* @see Configurable
|
||||
* @author Gavin King
|
||||
*/
|
||||
public interface PersistentIdentifierGenerator extends IdentifierGenerator {
|
||||
public interface PersistentIdentifierGenerator extends IdentifierGenerator, ExportableProducer {
|
||||
|
||||
/**
|
||||
* The configuration parameter holding the schema name
|
||||
|
|
|
@ -32,6 +32,7 @@ import java.util.Properties;
|
|||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.id.insert.AbstractSelectingDelegate;
|
||||
|
@ -52,7 +53,7 @@ public class SelectGenerator extends AbstractPostInsertGenerator implements Conf
|
|||
|
||||
private String uniqueKeyPropertyName;
|
||||
|
||||
public void configure(Type type, Properties params, Dialect d) throws MappingException {
|
||||
public void configure(Type type, Properties params, Dialect d, ClassLoaderService classLoaderService) throws MappingException {
|
||||
uniqueKeyPropertyName = params.getProperty( "key" );
|
||||
}
|
||||
|
||||
|
|
|
@ -29,17 +29,20 @@ import java.sql.ResultSet;
|
|||
import java.sql.SQLException;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.cfg.ObjectNameNormalizer;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.internal.util.config.ConfigurationHelper;
|
||||
import org.hibernate.mapping.Table;
|
||||
import org.hibernate.metamodel.spi.relational.Database;
|
||||
import org.hibernate.metamodel.spi.relational.ObjectName;
|
||||
import org.hibernate.metamodel.spi.relational.Schema;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
* <b>sequence</b><br>
|
||||
* <br>
|
||||
|
@ -50,12 +53,19 @@ import org.jboss.logging.Logger;
|
|||
*
|
||||
* @see SequenceHiLoGenerator
|
||||
* @author Gavin King
|
||||
*
|
||||
* @deprecated Going away in 5.0, use {@link org.hibernate.id.enhanced.SequenceStyleGenerator} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public class SequenceGenerator
|
||||
implements PersistentIdentifierGenerator, BulkInsertionCapableIdentifierGenerator, Configurable {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger( SequenceGenerator.class.getName() );
|
||||
|
||||
public SequenceGenerator() {
|
||||
LOG.warn( "Encountered use of deprecated " + getClass().getName() + " class" );
|
||||
}
|
||||
|
||||
/**
|
||||
* The sequence parameter
|
||||
*/
|
||||
|
@ -67,6 +77,8 @@ public class SequenceGenerator
|
|||
*/
|
||||
public static final String PARAMETERS = "parameters";
|
||||
|
||||
private ObjectName qualifiedSequenceName;
|
||||
|
||||
private String sequenceName;
|
||||
private String parameters;
|
||||
private Type identifierType;
|
||||
|
@ -85,29 +97,24 @@ public class SequenceGenerator
|
|||
}
|
||||
|
||||
@Override
|
||||
public void configure(Type type, Properties params, Dialect dialect) throws MappingException {
|
||||
public void configure(Type type, Properties params, Dialect dialect, ClassLoaderService classLoaderService) throws MappingException {
|
||||
ObjectNameNormalizer normalizer = ( ObjectNameNormalizer ) params.get( IDENTIFIER_NORMALIZER );
|
||||
sequenceName = normalizer.normalizeIdentifierQuoting(
|
||||
ConfigurationHelper.getString( SEQUENCE, params, "hibernate_sequence" )
|
||||
);
|
||||
parameters = params.getProperty( PARAMETERS );
|
||||
|
||||
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 )
|
||||
);
|
||||
sequenceName = new ObjectName( catalogName, schemaName, sequenceName ).toText( dialect );
|
||||
this.qualifiedSequenceName = new ObjectName( catalogName, schemaName, 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.qualifiedSequenceName = ObjectName.parse( sequenceName );
|
||||
}
|
||||
|
||||
this.parameters = params.getProperty( PARAMETERS );
|
||||
this.identifierType = type;
|
||||
sql = dialect.getSequenceNextValString( sequenceName );
|
||||
this.sql = dialect.getSequenceNextValString( sequenceName );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -149,6 +156,14 @@ public class SequenceGenerator
|
|||
return IdentifierGeneratorHelper.getIntegralDataTypeHolder( identifierType.getReturnedClass() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerExportables(Database database) {
|
||||
final Schema schema = database.getSchemaFor( qualifiedSequenceName );
|
||||
if ( schema.locateSequence( qualifiedSequenceName.getName() ) == null ) {
|
||||
schema.createSequence( qualifiedSequenceName.getName(), 1, 1 );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings( {"deprecation"})
|
||||
public String[] sqlCreateStrings(Dialect dialect) throws HibernateException {
|
||||
|
|
|
@ -26,6 +26,7 @@ import java.io.Serializable;
|
|||
import java.util.Properties;
|
||||
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.id.enhanced.AccessCallback;
|
||||
|
@ -51,8 +52,8 @@ public class SequenceHiLoGenerator extends SequenceGenerator {
|
|||
|
||||
private LegacyHiLoAlgorithmOptimizer hiloOptimizer;
|
||||
|
||||
public void configure(Type type, Properties params, Dialect d) throws MappingException {
|
||||
super.configure(type, params, d);
|
||||
public void configure(Type type, Properties params, Dialect d, ClassLoaderService classLoaderService) throws MappingException {
|
||||
super.configure(type, params, d, classLoaderService );
|
||||
|
||||
maxLo = ConfigurationHelper.getInt( MAX_LO, params, 9 );
|
||||
|
||||
|
|
|
@ -26,10 +26,10 @@ package org.hibernate.id;
|
|||
import java.io.Serializable;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.id.insert.AbstractReturningDelegate;
|
||||
|
@ -37,9 +37,6 @@ import org.hibernate.id.insert.IdentifierGeneratingInsert;
|
|||
import org.hibernate.id.insert.InsertGeneratedIdentifierDelegate;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.sql.Insert;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
* A generator which combines sequence generation with immediate retrieval
|
||||
|
@ -75,11 +72,6 @@ public class SequenceIdentityGenerator
|
|||
return new Delegate( persister, dialect, getSequenceName() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(Type type, Properties params, Dialect dialect) throws MappingException {
|
||||
super.configure( type, params, dialect );
|
||||
}
|
||||
|
||||
public static class Delegate extends AbstractReturningDelegate {
|
||||
private final Dialect dialect;
|
||||
private final String sequenceNextValFragment;
|
||||
|
|
|
@ -33,6 +33,7 @@ import java.util.Properties;
|
|||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.cfg.ObjectNameNormalizer;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.jdbc.internal.FormatStyle;
|
||||
|
@ -44,7 +45,8 @@ import org.hibernate.id.enhanced.SequenceStyleGenerator;
|
|||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.config.ConfigurationHelper;
|
||||
import org.hibernate.jdbc.AbstractReturningWork;
|
||||
import org.hibernate.mapping.Table;
|
||||
import org.hibernate.metamodel.spi.relational.Database;
|
||||
import org.hibernate.metamodel.spi.relational.ObjectName;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
@ -73,8 +75,9 @@ import org.jboss.logging.Logger;
|
|||
*
|
||||
* @see TableHiLoGenerator
|
||||
* @author Gavin King
|
||||
*
|
||||
* @deprecated use {@link SequenceStyleGenerator} instead.
|
||||
*
|
||||
* @deprecated Going away in 5.0, use {@link org.hibernate.id.enhanced.SequenceStyleGenerator} or
|
||||
* {@link org.hibernate.id.enhanced.TableGenerator} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public class TableGenerator implements PersistentIdentifierGenerator, Configurable {
|
||||
|
@ -99,7 +102,7 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab
|
|||
private String query;
|
||||
private String update;
|
||||
|
||||
public void configure(Type type, Properties params, Dialect dialect) {
|
||||
public void configure(Type type, Properties params, Dialect dialect, ClassLoaderService classLoaderService) {
|
||||
identifierType = type;
|
||||
|
||||
ObjectNameNormalizer normalizer = ( ObjectNameNormalizer ) params.get( IDENTIFIER_NORMALIZER );
|
||||
|
@ -108,11 +111,7 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab
|
|||
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 )
|
||||
);
|
||||
tableName = new ObjectName(catalogName, schemaName, tableName).toText( dialect );
|
||||
}
|
||||
else {
|
||||
// if already qualified there is not much we can do in a portable manner so we pass it
|
||||
|
@ -160,40 +159,50 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab
|
|||
// The loop ensures atomicity of the select + update even for no transaction or
|
||||
// read committed isolation level
|
||||
do {
|
||||
final PreparedStatement qps = prepareStatement( connection, query, statementLogger, listeners );
|
||||
final PreparedStatement qps = prepareStatement(
|
||||
connection,
|
||||
query,
|
||||
statementLogger,
|
||||
listeners
|
||||
);
|
||||
try {
|
||||
ResultSet rs = executeQuery( qps, listeners );
|
||||
if ( !rs.next() ) {
|
||||
String err = "could not read a hi value - you need to populate the table: " + tableName;
|
||||
LOG.error(err);
|
||||
throw new IdentifierGenerationException(err);
|
||||
LOG.error( err );
|
||||
throw new IdentifierGenerationException( err );
|
||||
}
|
||||
value.initialize( rs, 1 );
|
||||
rs.close();
|
||||
}
|
||||
catch (SQLException e) {
|
||||
LOG.error("Could not read a hi value", e);
|
||||
catch ( SQLException e ) {
|
||||
LOG.error( "Could not read a hi value", e );
|
||||
throw e;
|
||||
}
|
||||
finally {
|
||||
qps.close();
|
||||
}
|
||||
|
||||
final PreparedStatement ups = prepareStatement( connection, update, statementLogger, listeners );
|
||||
final PreparedStatement ups = prepareStatement(
|
||||
connection,
|
||||
update,
|
||||
statementLogger,
|
||||
listeners
|
||||
);
|
||||
try {
|
||||
value.copy().increment().bind( ups, 1 );
|
||||
value.bind( ups, 2 );
|
||||
rows = executeUpdate( ups, listeners );
|
||||
}
|
||||
catch (SQLException sqle) {
|
||||
LOG.error(LOG.unableToUpdateHiValue(tableName), sqle);
|
||||
catch ( SQLException sqle ) {
|
||||
LOG.error( LOG.unableToUpdateHiValue( tableName ), sqle );
|
||||
throw sqle;
|
||||
}
|
||||
finally {
|
||||
ups.close();
|
||||
}
|
||||
}
|
||||
while (rows==0);
|
||||
while ( rows == 0 );
|
||||
return value;
|
||||
}
|
||||
},
|
||||
|
@ -237,6 +246,11 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerExportables(Database database) {
|
||||
// not doing anything here as I expect this to go away
|
||||
}
|
||||
|
||||
public String[] sqlCreateStrings(Dialect dialect) throws HibernateException {
|
||||
return new String[] {
|
||||
dialect.getCreateTableString() + " " + tableName + " ( "
|
||||
|
|
|
@ -25,6 +25,7 @@ package org.hibernate.id;
|
|||
import java.io.Serializable;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.id.enhanced.AccessCallback;
|
||||
|
@ -63,8 +64,8 @@ public class TableHiLoGenerator extends TableGenerator {
|
|||
private int maxLo;
|
||||
|
||||
@Override
|
||||
public void configure(Type type, Properties params, Dialect d) {
|
||||
super.configure( type, params, d );
|
||||
public void configure(Type type, Properties params, Dialect d, ClassLoaderService classLoaderService) {
|
||||
super.configure( type, params, d, classLoaderService );
|
||||
maxLo = ConfigurationHelper.getInt( MAX_LO, params, Short.MAX_VALUE );
|
||||
|
||||
if ( maxLo >= 1 ) {
|
||||
|
|
|
@ -29,6 +29,8 @@ import java.util.UUID;
|
|||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.id.uuid.StandardRandomStrategy;
|
||||
|
@ -36,7 +38,6 @@ import org.hibernate.internal.CoreMessageLogger;
|
|||
import org.hibernate.internal.util.ReflectHelper;
|
||||
import org.hibernate.type.Type;
|
||||
import org.hibernate.type.descriptor.java.UUIDTypeDescriptor;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
|
@ -72,7 +73,7 @@ public class UUIDGenerator implements IdentifierGenerator, Configurable {
|
|||
return generator;
|
||||
}
|
||||
|
||||
public void configure(Type type, Properties params, Dialect d) throws MappingException {
|
||||
public void configure(Type type, Properties params, Dialect d, ClassLoaderService classLoaderService) throws MappingException {
|
||||
// check first for the strategy instance
|
||||
strategy = (UUIDGenerationStrategy) params.get( UUID_GEN_STRATEGY );
|
||||
if ( strategy == null ) {
|
||||
|
@ -80,7 +81,14 @@ public class UUIDGenerator implements IdentifierGenerator, Configurable {
|
|||
final String strategyClassName = params.getProperty( UUID_GEN_STRATEGY_CLASS );
|
||||
if ( strategyClassName != null ) {
|
||||
try {
|
||||
final Class strategyClass = ReflectHelper.classForName( strategyClassName );
|
||||
final Class strategyClass;
|
||||
// TODO: Exists purely for testing using the old .mappings. Eventually remove.
|
||||
if (classLoaderService == null) {
|
||||
strategyClass = ReflectHelper.classForName( strategyClassName );
|
||||
}
|
||||
else {
|
||||
strategyClass = classLoaderService.classForName( strategyClassName );
|
||||
}
|
||||
try {
|
||||
strategy = (UUIDGenerationStrategy) strategyClass.newInstance();
|
||||
}
|
||||
|
@ -88,9 +96,12 @@ public class UUIDGenerator implements IdentifierGenerator, Configurable {
|
|||
LOG.unableToInstantiateUuidGenerationStrategy(ignore);
|
||||
}
|
||||
}
|
||||
catch ( ClassNotFoundException ignore ) {
|
||||
catch ( ClassLoadingException ignore ) {
|
||||
LOG.unableToLocateUuidGenerationStrategy(strategyClassName);
|
||||
}
|
||||
catch ( ClassNotFoundException ignore ) {
|
||||
LOG.unableToLocateUuidGenerationStrategy(strategyClassName);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( strategy == null ) {
|
||||
|
|
|
@ -26,6 +26,7 @@ package org.hibernate.id;
|
|||
import java.io.Serializable;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
|
@ -61,7 +62,7 @@ public class UUIDHexGenerator extends AbstractUUIDGenerator implements Configura
|
|||
}
|
||||
|
||||
@Override
|
||||
public void configure(Type type, Properties params, Dialect d) {
|
||||
public void configure(Type type, Properties params, Dialect d, ClassLoaderService classLoaderService) {
|
||||
sep = ConfigurationHelper.getString( "separator", params, "" );
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ package org.hibernate.id.enhanced;
|
|||
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.metamodel.spi.relational.ExportableProducer;
|
||||
|
||||
/**
|
||||
* Encapsulates definition of the underlying data structure backing a
|
||||
|
@ -32,7 +33,7 @@ import org.hibernate.engine.spi.SessionImplementor;
|
|||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface DatabaseStructure {
|
||||
public interface DatabaseStructure extends ExportableProducer {
|
||||
/**
|
||||
* The name of the database structure (table or sequence).
|
||||
* @return The structure name.
|
||||
|
|
|
@ -25,9 +25,8 @@ package org.hibernate.id.enhanced;
|
|||
|
||||
import java.lang.reflect.Constructor;
|
||||
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.ReflectHelper;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
|
@ -61,13 +60,15 @@ public class OptimizerFactory {
|
|||
* @param type The optimizer type, either a short-hand name or the {@link Optimizer} class name.
|
||||
* @param returnClass The generated value java type
|
||||
* @param incrementSize The increment size.
|
||||
* @param classLoaderService ClassLoaderService
|
||||
*
|
||||
* @return The built optimizer
|
||||
*
|
||||
* @deprecated Use {@link #buildOptimizer(String, Class, int, long)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public static Optimizer buildOptimizer(String type, Class returnClass, int incrementSize) {
|
||||
public static Optimizer buildOptimizer(String type, Class returnClass, int incrementSize,
|
||||
ClassLoaderService classLoaderService) {
|
||||
final Class<? extends Optimizer> optimizerClass;
|
||||
|
||||
final StandardOptimizerDescriptor standardDescriptor = StandardOptimizerDescriptor.fromExternalName( type );
|
||||
|
@ -76,7 +77,7 @@ public class OptimizerFactory {
|
|||
}
|
||||
else {
|
||||
try {
|
||||
optimizerClass = ReflectHelper.classForName( type );
|
||||
optimizerClass = classLoaderService.classForName( type );
|
||||
}
|
||||
catch( Throwable ignore ) {
|
||||
LOG.unableToLocateCustomOptimizerClass( type );
|
||||
|
@ -106,11 +107,12 @@ public class OptimizerFactory {
|
|||
* @param returnClass The generated value java type
|
||||
* @param incrementSize The increment size.
|
||||
* @param explicitInitialValue The user supplied initial-value (-1 indicates the user did not specify).
|
||||
* @param classLoaderService ClassLoaderService
|
||||
*
|
||||
* @return The built optimizer
|
||||
*/
|
||||
public static Optimizer buildOptimizer(String type, Class returnClass, int incrementSize, long explicitInitialValue) {
|
||||
final Optimizer optimizer = buildOptimizer( type, returnClass, incrementSize );
|
||||
public static Optimizer buildOptimizer(String type, Class returnClass, int incrementSize, long explicitInitialValue, ClassLoaderService classLoaderService) {
|
||||
final Optimizer optimizer = buildOptimizer( type, returnClass, incrementSize, classLoaderService );
|
||||
if ( InitialValueAwareOptimizer.class.isInstance( optimizer ) ) {
|
||||
( (InitialValueAwareOptimizer) optimizer ).injectInitialValue( explicitInitialValue );
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, 2013, Red Hat Inc. or third-party contributors as
|
||||
* Copyright (c) 2008, 2012, 2013, Red Hat Inc. 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 Inc.
|
||||
|
@ -22,19 +22,22 @@
|
|||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.id.enhanced;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.id.IdentifierGeneratorHelper;
|
||||
import org.hibernate.id.IntegralDataTypeHolder;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.hibernate.metamodel.spi.relational.Database;
|
||||
import org.hibernate.metamodel.spi.relational.ObjectName;
|
||||
import org.hibernate.metamodel.spi.relational.Schema;
|
||||
import org.hibernate.metamodel.spi.relational.Sequence;
|
||||
|
||||
/**
|
||||
* Describes a sequence.
|
||||
|
@ -47,6 +50,7 @@ public class SequenceStructure implements DatabaseStructure {
|
|||
SequenceStructure.class.getName()
|
||||
);
|
||||
|
||||
private ObjectName qualifiedSequenceName;
|
||||
private final String sequenceName;
|
||||
private final int initialValue;
|
||||
private final int incrementSize;
|
||||
|
@ -57,11 +61,12 @@ public class SequenceStructure implements DatabaseStructure {
|
|||
|
||||
public SequenceStructure(
|
||||
Dialect dialect,
|
||||
String sequenceName,
|
||||
ObjectName qualifiedSequenceName,
|
||||
int initialValue,
|
||||
int incrementSize,
|
||||
Class numberType) {
|
||||
this.sequenceName = sequenceName;
|
||||
this.qualifiedSequenceName = qualifiedSequenceName;
|
||||
this.sequenceName = qualifiedSequenceName.toText( dialect );
|
||||
this.initialValue = initialValue;
|
||||
this.incrementSize = incrementSize;
|
||||
this.numberType = numberType;
|
||||
|
@ -142,6 +147,19 @@ public class SequenceStructure implements DatabaseStructure {
|
|||
applyIncrementSizeToSourceValues = optimizer.applyIncrementSizeToSourceValues();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerExportables(Database database) {
|
||||
final int sourceIncrementSize = applyIncrementSizeToSourceValues ? incrementSize : 1;
|
||||
final Schema schema = database.getSchemaFor( qualifiedSequenceName );
|
||||
Sequence sequence = schema.locateSequence( qualifiedSequenceName.getName() );
|
||||
if ( sequence != null ) {
|
||||
sequence.validate( initialValue, sourceIncrementSize );
|
||||
}
|
||||
else {
|
||||
schema.createSequence( qualifiedSequenceName.getName(), initialValue, sourceIncrementSize );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] sqlCreateStrings(Dialect dialect) throws HibernateException {
|
||||
final int sourceIncrementSize = applyIncrementSizeToSourceValues ? incrementSize : 1;
|
||||
|
|
|
@ -26,8 +26,11 @@ package org.hibernate.id.enhanced;
|
|||
import java.io.Serializable;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.cfg.ObjectNameNormalizer;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
|
@ -37,11 +40,11 @@ import org.hibernate.id.Configurable;
|
|||
import org.hibernate.id.PersistentIdentifierGenerator;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.config.ConfigurationHelper;
|
||||
import org.hibernate.mapping.Table;
|
||||
import org.hibernate.metamodel.spi.relational.Database;
|
||||
import org.hibernate.metamodel.spi.relational.Identifier;
|
||||
import org.hibernate.metamodel.spi.relational.ObjectName;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
* Generates identifier values based on an sequence-style database structure.
|
||||
* Variations range from actually using a sequence to using a table to mimic
|
||||
|
@ -227,11 +230,12 @@ public class SequenceStyleGenerator
|
|||
// Configurable implementation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@Override
|
||||
public void configure(Type type, Properties params, Dialect dialect) throws MappingException {
|
||||
public void configure(Type type, Properties params, Dialect dialect, ClassLoaderService classLoaderService) throws MappingException {
|
||||
this.identifierType = type;
|
||||
boolean forceTableUse = ConfigurationHelper.getBoolean( FORCE_TBL_PARAM, params, false );
|
||||
|
||||
final String sequenceName = determineSequenceName( params, dialect );
|
||||
final ObjectName qualifiedSequenceName = determineSequenceName( params, dialect );
|
||||
final String sequenceNameText = qualifiedSequenceName.toText( dialect );
|
||||
|
||||
final int initialValue = determineInitialValue( params );
|
||||
int incrementSize = determineIncrementSize( params );
|
||||
|
@ -251,7 +255,7 @@ public class SequenceStyleGenerator
|
|||
params,
|
||||
dialect,
|
||||
forceTableUse,
|
||||
sequenceName,
|
||||
qualifiedSequenceName,
|
||||
initialValue,
|
||||
incrementSize
|
||||
);
|
||||
|
@ -259,7 +263,8 @@ public class SequenceStyleGenerator
|
|||
optimizationStrategy,
|
||||
identifierType.getReturnedClass(),
|
||||
incrementSize,
|
||||
ConfigurationHelper.getInt( INITIAL_PARAM, params, -1 )
|
||||
ConfigurationHelper.getInt( INITIAL_PARAM, params, -1 ),
|
||||
classLoaderService
|
||||
);
|
||||
this.databaseStructure.prepare( optimizer );
|
||||
}
|
||||
|
@ -274,28 +279,25 @@ public class SequenceStyleGenerator
|
|||
* @param dialect The dialect in effect
|
||||
* @return The sequence name
|
||||
*/
|
||||
protected String determineSequenceName(Properties params, Dialect dialect) {
|
||||
final String sequencePerEntitySuffix = ConfigurationHelper.getString( CONFIG_SEQUENCE_PER_ENTITY_SUFFIX, params, DEF_SEQUENCE_SUFFIX );
|
||||
protected ObjectName determineSequenceName(Properties params, Dialect dialect) {
|
||||
String sequencePerEntitySuffix = ConfigurationHelper.getString( CONFIG_SEQUENCE_PER_ENTITY_SUFFIX, params, DEF_SEQUENCE_SUFFIX );
|
||||
// JPA_ENTITY_NAME value honors <class ... entity-name="..."> (HBM) and @Entity#name (JPA) overrides.
|
||||
String sequenceName = ConfigurationHelper.getBoolean( CONFIG_PREFER_SEQUENCE_PER_ENTITY, params, false )
|
||||
? params.getProperty( JPA_ENTITY_NAME ) + sequencePerEntitySuffix
|
||||
: DEF_SEQUENCE_NAME;
|
||||
final ObjectNameNormalizer normalizer = (ObjectNameNormalizer) params.get( IDENTIFIER_NORMALIZER );
|
||||
sequenceName = ConfigurationHelper.getString( SEQUENCE_PARAM, params, sequenceName );
|
||||
final ObjectNameNormalizer normalizer = ( ObjectNameNormalizer ) params.get( IDENTIFIER_NORMALIZER );
|
||||
sequenceName = normalizer.normalizeIdentifierQuoting(
|
||||
ConfigurationHelper.getString( SEQUENCE_PARAM, params, sequenceName )
|
||||
);
|
||||
if ( sequenceName.indexOf( '.' ) < 0 ) {
|
||||
sequenceName = normalizer.normalizeIdentifierQuoting( sequenceName );
|
||||
final String schemaName = params.getProperty( SCHEMA );
|
||||
final String catalogName = params.getProperty( CATALOG );
|
||||
sequenceName = Table.qualify(
|
||||
dialect.quote( catalogName ),
|
||||
dialect.quote( schemaName ),
|
||||
dialect.quote( sequenceName )
|
||||
);
|
||||
}
|
||||
// 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.
|
||||
final String schemaName = normalizer.normalizeIdentifierQuoting( params.getProperty( SCHEMA ) );
|
||||
final String catalogName = normalizer.normalizeIdentifierQuoting( params.getProperty( CATALOG ) );
|
||||
|
||||
return sequenceName;
|
||||
return new ObjectName( catalogName, schemaName, sequenceName );
|
||||
}
|
||||
else {
|
||||
return ObjectName.parse( sequenceName );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -309,10 +311,10 @@ public class SequenceStyleGenerator
|
|||
* @param dialect The dialect in effect.
|
||||
* @return The value column name
|
||||
*/
|
||||
protected String determineValueColumnName(Properties params, Dialect dialect) {
|
||||
final ObjectNameNormalizer normalizer = (ObjectNameNormalizer) params.get( IDENTIFIER_NORMALIZER );
|
||||
protected Identifier determineValueColumnName(Properties params, Dialect dialect) {
|
||||
final ObjectNameNormalizer normalizer = ( ObjectNameNormalizer ) params.get( IDENTIFIER_NORMALIZER );
|
||||
final String name = ConfigurationHelper.getString( VALUE_COLUMN_PARAM, params, DEF_VALUE_COLUMN );
|
||||
return dialect.quote( normalizer.normalizeIdentifierQuoting( name ) );
|
||||
return Identifier.toIdentifier( normalizer.normalizeIdentifierQuoting( name ) );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -401,7 +403,7 @@ public class SequenceStyleGenerator
|
|||
Properties params,
|
||||
Dialect dialect,
|
||||
boolean forceTableUse,
|
||||
String sequenceName,
|
||||
ObjectName sequenceName,
|
||||
int initialValue,
|
||||
int incrementSize) {
|
||||
final boolean useSequence = dialect.supportsSequences() && !forceTableUse;
|
||||
|
@ -409,7 +411,7 @@ public class SequenceStyleGenerator
|
|||
return new SequenceStructure( dialect, sequenceName, initialValue, incrementSize, type.getReturnedClass() );
|
||||
}
|
||||
else {
|
||||
final String valueColumnName = determineValueColumnName( params, dialect );
|
||||
Identifier valueColumnName = determineValueColumnName( params, dialect );
|
||||
return new TableStructure( dialect, sequenceName, valueColumnName, initialValue, incrementSize, type.getReturnedClass() );
|
||||
}
|
||||
}
|
||||
|
@ -430,6 +432,11 @@ public class SequenceStyleGenerator
|
|||
return databaseStructure.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerExportables(Database database) {
|
||||
databaseStructure.registerExportables( database );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] sqlCreateStrings(Dialect dialect) throws HibernateException {
|
||||
return databaseStructure.sqlCreateStrings( dialect );
|
||||
|
|
|
@ -37,6 +37,7 @@ import org.hibernate.HibernateException;
|
|||
import org.hibernate.LockMode;
|
||||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.cfg.ObjectNameNormalizer;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
|
@ -53,7 +54,11 @@ import org.hibernate.internal.CoreMessageLogger;
|
|||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.internal.util.config.ConfigurationHelper;
|
||||
import org.hibernate.jdbc.AbstractReturningWork;
|
||||
import org.hibernate.mapping.Table;
|
||||
import org.hibernate.metamodel.spi.relational.Column;
|
||||
import org.hibernate.metamodel.spi.relational.Database;
|
||||
import org.hibernate.metamodel.spi.relational.Identifier;
|
||||
import org.hibernate.metamodel.spi.relational.ObjectName;
|
||||
import org.hibernate.metamodel.spi.relational.Table;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
@ -226,7 +231,12 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab
|
|||
|
||||
private Type identifierType;
|
||||
|
||||
private ObjectName qualifiedTableName;
|
||||
private Identifier qualifiedSegmentColumnName;
|
||||
private Identifier qualifiedValueColumnName;
|
||||
|
||||
private String tableName;
|
||||
private Table table;
|
||||
|
||||
private String segmentColumnName;
|
||||
private String segmentValue;
|
||||
|
@ -266,6 +276,15 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab
|
|||
return tableName;
|
||||
}
|
||||
|
||||
/**
|
||||
* The bound Table for this generator.
|
||||
*
|
||||
* @return The table.
|
||||
*/
|
||||
public final Table getTable() {
|
||||
return table;
|
||||
}
|
||||
|
||||
/**
|
||||
* The name of the column in which we store the segment to which each row
|
||||
* belongs. The value here acts as PK.
|
||||
|
@ -349,7 +368,7 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab
|
|||
}
|
||||
|
||||
@Override
|
||||
public void configure(Type type, Properties params, Dialect dialect) throws MappingException {
|
||||
public void configure(Type type, Properties params, Dialect dialect, ClassLoaderService classLoaderService) throws MappingException {
|
||||
identifierType = type;
|
||||
|
||||
tableName = determineGeneratorTableName( params, dialect );
|
||||
|
@ -379,14 +398,15 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab
|
|||
optimizationStrategy,
|
||||
identifierType.getReturnedClass(),
|
||||
incrementSize,
|
||||
ConfigurationHelper.getInt( INITIAL_PARAM, params, -1 )
|
||||
ConfigurationHelper.getInt( INITIAL_PARAM, params, -1 ),
|
||||
classLoaderService
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the table name to use for the generator values.
|
||||
* <p/>
|
||||
* Called during {@link #configure configuration}.
|
||||
* Called during {@link org.hibernate.id.Configurable#configure configuration}.
|
||||
*
|
||||
* @see #getTableName()
|
||||
* @param params The params supplied in the generator config (plus some standard useful extras).
|
||||
|
@ -394,22 +414,23 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab
|
|||
* @return The table name to use.
|
||||
*/
|
||||
protected String determineGeneratorTableName(Properties params, Dialect dialect) {
|
||||
String name = ConfigurationHelper.getString( TABLE_PARAM, params, DEF_TABLE );
|
||||
final ObjectNameNormalizer normalizer = ( ObjectNameNormalizer ) params.get( IDENTIFIER_NORMALIZER );
|
||||
String name = normalizer.normalizeIdentifierQuoting(
|
||||
ConfigurationHelper.getString( TABLE_PARAM, params, DEF_TABLE )
|
||||
);
|
||||
final boolean isGivenNameUnqualified = name.indexOf( '.' ) < 0;
|
||||
if ( isGivenNameUnqualified ) {
|
||||
final ObjectNameNormalizer normalizer = (ObjectNameNormalizer) params.get( IDENTIFIER_NORMALIZER );
|
||||
name = normalizer.normalizeIdentifierQuoting( name );
|
||||
// if the given name is un-qualified we may neen to qualify it
|
||||
final String schemaName = normalizer.normalizeIdentifierQuoting( params.getProperty( SCHEMA ) );
|
||||
final String catalogName = normalizer.normalizeIdentifierQuoting( params.getProperty( CATALOG ) );
|
||||
name = Table.qualify(
|
||||
dialect.quote( catalogName ),
|
||||
dialect.quote( schemaName ),
|
||||
dialect.quote( name)
|
||||
);
|
||||
|
||||
qualifiedTableName = new ObjectName( catalogName, schemaName, name );
|
||||
|
||||
name = qualifiedTableName.toText( dialect );
|
||||
}
|
||||
else {
|
||||
qualifiedTableName = ObjectName.parse( name );
|
||||
}
|
||||
// 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;
|
||||
}
|
||||
|
@ -418,7 +439,7 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab
|
|||
* Determine the name of the column used to indicate the segment for each
|
||||
* row. This column acts as the primary key.
|
||||
* <p/>
|
||||
* Called during {@link #configure configuration}.
|
||||
* Called during {@link org.hibernate.id.Configurable#configure configuration}.
|
||||
*
|
||||
* @see #getSegmentColumnName()
|
||||
* @param params The params supplied in the generator config (plus some standard useful extras).
|
||||
|
@ -428,13 +449,14 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab
|
|||
protected String determineSegmentColumnName(Properties params, Dialect dialect) {
|
||||
final ObjectNameNormalizer normalizer = (ObjectNameNormalizer) params.get( IDENTIFIER_NORMALIZER );
|
||||
final String name = ConfigurationHelper.getString( SEGMENT_COLUMN_PARAM, params, DEF_SEGMENT_COLUMN );
|
||||
return dialect.quote( normalizer.normalizeIdentifierQuoting( name ) );
|
||||
qualifiedSegmentColumnName = Identifier.toIdentifier( normalizer.normalizeIdentifierQuoting( name ) );
|
||||
return qualifiedSegmentColumnName.getText( dialect );
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the name of the column in which we will store the generator persistent value.
|
||||
* <p/>
|
||||
* Called during {@link #configure configuration}.
|
||||
* Called during {@link org.hibernate.id.Configurable#configure configuration}.
|
||||
*
|
||||
* @see #getValueColumnName()
|
||||
* @param params The params supplied in the generator config (plus some standard useful extras).
|
||||
|
@ -444,13 +466,14 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab
|
|||
protected String determineValueColumnName(Properties params, Dialect dialect) {
|
||||
final ObjectNameNormalizer normalizer = (ObjectNameNormalizer) params.get( IDENTIFIER_NORMALIZER );
|
||||
final String name = ConfigurationHelper.getString( VALUE_COLUMN_PARAM, params, DEF_VALUE_COLUMN );
|
||||
return dialect.quote( normalizer.normalizeIdentifierQuoting( name ) );
|
||||
qualifiedValueColumnName = Identifier.toIdentifier( normalizer.normalizeIdentifierQuoting( name ) );
|
||||
return qualifiedValueColumnName.getText( dialect );
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the segment value corresponding to this generator instance.
|
||||
* <p/>
|
||||
* Called during {@link #configure configuration}.
|
||||
* Called during {@link org.hibernate.id.Configurable#configure configuration}.
|
||||
*
|
||||
* @see #getSegmentValue()
|
||||
* @param params The params supplied in the generator config (plus some standard useful extras).
|
||||
|
@ -472,16 +495,20 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab
|
|||
* @return The default segment value to use.
|
||||
*/
|
||||
protected String determineDefaultSegmentValue(Properties params) {
|
||||
final boolean preferSegmentPerEntity = ConfigurationHelper.getBoolean( CONFIG_PREFER_SEGMENT_PER_ENTITY, params, false );
|
||||
final boolean preferSegmentPerEntity = ConfigurationHelper.getBoolean(
|
||||
CONFIG_PREFER_SEGMENT_PER_ENTITY,
|
||||
params,
|
||||
false
|
||||
);
|
||||
final String defaultToUse = preferSegmentPerEntity ? params.getProperty( TABLE ) : DEF_SEGMENT_VALUE;
|
||||
LOG.usingDefaultIdGeneratorSegmentValue( tableName, segmentColumnName, defaultToUse );
|
||||
LOG.usingDefaultIdGeneratorSegmentValue( qualifiedTableName.toString(), segmentColumnName, defaultToUse );
|
||||
return defaultToUse;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the size of the {@link #getSegmentColumnName segment column}
|
||||
* <p/>
|
||||
* Called during {@link #configure configuration}.
|
||||
* Called during {@link org.hibernate.id.Configurable#configure configuration}.
|
||||
*
|
||||
* @see #getSegmentValueLength()
|
||||
* @param params The params supplied in the generator config (plus some standard useful extras).
|
||||
|
@ -502,7 +529,7 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab
|
|||
protected String buildSelectQuery(Dialect dialect) {
|
||||
final String alias = "tbl";
|
||||
final String query = "select " + StringHelper.qualify( alias, valueColumnName ) +
|
||||
" from " + tableName + ' ' + alias +
|
||||
" from " + qualifiedTableName.toText( dialect ) + ' ' + alias +
|
||||
" where " + StringHelper.qualify( alias, segmentColumnName ) + "=?";
|
||||
final LockOptions lockOptions = new LockOptions( LockMode.PESSIMISTIC_WRITE );
|
||||
lockOptions.setAliasSpecificLockMode( alias, LockMode.PESSIMISTIC_WRITE );
|
||||
|
@ -511,7 +538,7 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab
|
|||
}
|
||||
|
||||
protected String buildUpdateQuery() {
|
||||
return "update " + tableName +
|
||||
return "update " + qualifiedTableName.toText( ) +
|
||||
" set " + valueColumnName + "=? " +
|
||||
" where " + valueColumnName + "=? and " + segmentColumnName + "=?";
|
||||
}
|
||||
|
@ -535,76 +562,98 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab
|
|||
new AccessCallback() {
|
||||
@Override
|
||||
public IntegralDataTypeHolder getNextValue() {
|
||||
return session.getTransactionCoordinator().getTransaction().createIsolationDelegate().delegateWork(
|
||||
new AbstractReturningWork<IntegralDataTypeHolder>() {
|
||||
@Override
|
||||
public IntegralDataTypeHolder execute(Connection connection) throws SQLException {
|
||||
final IntegralDataTypeHolder value = makeValue();
|
||||
int rows;
|
||||
do {
|
||||
final PreparedStatement selectPS = prepareStatement( connection, selectQuery, statementLogger, statsCollector );
|
||||
return session.getTransactionCoordinator()
|
||||
.getTransaction()
|
||||
.createIsolationDelegate()
|
||||
.delegateWork(
|
||||
new AbstractReturningWork<IntegralDataTypeHolder>() {
|
||||
@Override
|
||||
public IntegralDataTypeHolder execute(Connection connection)
|
||||
throws SQLException {
|
||||
final IntegralDataTypeHolder value = makeValue();
|
||||
int rows;
|
||||
do {
|
||||
final PreparedStatement selectPS = prepareStatement(
|
||||
connection,
|
||||
selectQuery,
|
||||
statementLogger,
|
||||
statsCollector
|
||||
);
|
||||
|
||||
try {
|
||||
selectPS.setString( 1, segmentValue );
|
||||
final ResultSet selectRS = executeQuery( selectPS, statsCollector );
|
||||
if ( !selectRS.next() ) {
|
||||
value.initialize( initialValue );
|
||||
|
||||
final PreparedStatement insertPS = prepareStatement( connection, insertQuery, statementLogger, statsCollector );
|
||||
try {
|
||||
insertPS.setString( 1, segmentValue );
|
||||
value.bind( insertPS, 2 );
|
||||
executeUpdate( insertPS, statsCollector );
|
||||
selectPS.setString( 1, segmentValue );
|
||||
final ResultSet selectRS = executeQuery(
|
||||
selectPS,
|
||||
statsCollector
|
||||
);
|
||||
if ( !selectRS.next() ) {
|
||||
value.initialize( initialValue );
|
||||
|
||||
final PreparedStatement insertPS = prepareStatement(
|
||||
connection,
|
||||
insertQuery,
|
||||
statementLogger,
|
||||
statsCollector
|
||||
);
|
||||
try {
|
||||
insertPS.setString( 1, segmentValue );
|
||||
value.bind( insertPS, 2 );
|
||||
executeUpdate( insertPS, statsCollector );
|
||||
}
|
||||
finally {
|
||||
insertPS.close();
|
||||
}
|
||||
}
|
||||
else {
|
||||
value.initialize( selectRS, 1 );
|
||||
}
|
||||
selectRS.close();
|
||||
}
|
||||
catch ( SQLException e ) {
|
||||
LOG.unableToReadOrInitHiValue( e );
|
||||
throw e;
|
||||
}
|
||||
finally {
|
||||
insertPS.close();
|
||||
selectPS.close();
|
||||
}
|
||||
|
||||
|
||||
final PreparedStatement updatePS = prepareStatement(
|
||||
connection,
|
||||
updateQuery,
|
||||
statementLogger,
|
||||
statsCollector
|
||||
);
|
||||
try {
|
||||
final IntegralDataTypeHolder updateValue = value.copy();
|
||||
if ( optimizer.applyIncrementSizeToSourceValues() ) {
|
||||
updateValue.add( incrementSize );
|
||||
}
|
||||
else {
|
||||
updateValue.increment();
|
||||
}
|
||||
updateValue.bind( updatePS, 1 );
|
||||
value.bind( updatePS, 2 );
|
||||
updatePS.setString( 3, segmentValue );
|
||||
rows = executeUpdate( updatePS, statsCollector );
|
||||
}
|
||||
catch ( SQLException e ) {
|
||||
LOG.unableToUpdateQueryHiValue( tableName, e );
|
||||
throw e;
|
||||
}
|
||||
finally {
|
||||
updatePS.close();
|
||||
}
|
||||
}
|
||||
else {
|
||||
value.initialize( selectRS, 1 );
|
||||
}
|
||||
selectRS.close();
|
||||
}
|
||||
catch (SQLException e) {
|
||||
LOG.unableToReadOrInitHiValue( e );
|
||||
throw e;
|
||||
}
|
||||
finally {
|
||||
selectPS.close();
|
||||
}
|
||||
while ( rows == 0 );
|
||||
|
||||
accessCount++;
|
||||
|
||||
final PreparedStatement updatePS = prepareStatement( connection, updateQuery, statementLogger, statsCollector );
|
||||
try {
|
||||
final IntegralDataTypeHolder updateValue = value.copy();
|
||||
if ( optimizer.applyIncrementSizeToSourceValues() ) {
|
||||
updateValue.add( incrementSize );
|
||||
}
|
||||
else {
|
||||
updateValue.increment();
|
||||
}
|
||||
updateValue.bind( updatePS, 1 );
|
||||
value.bind( updatePS, 2 );
|
||||
updatePS.setString( 3, segmentValue );
|
||||
rows = executeUpdate( updatePS, statsCollector );
|
||||
return value;
|
||||
}
|
||||
catch (SQLException e) {
|
||||
LOG.unableToUpdateQueryHiValue( tableName, e );
|
||||
throw e;
|
||||
}
|
||||
finally {
|
||||
updatePS.close();
|
||||
}
|
||||
}
|
||||
while ( rows == 0 );
|
||||
|
||||
accessCount++;
|
||||
|
||||
return value;
|
||||
}
|
||||
},
|
||||
true
|
||||
);
|
||||
},
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -651,6 +700,24 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerExportables(Database database) {
|
||||
final Dialect dialect = database.getJdbcEnvironment().getDialect();
|
||||
|
||||
table = database.getSchemaFor( qualifiedTableName )
|
||||
.createTable( qualifiedTableName.getName(), qualifiedTableName.getName() );
|
||||
|
||||
Column segmentColumn = table.createColumn( qualifiedSegmentColumnName );
|
||||
table.getPrimaryKey().addColumn( segmentColumn );
|
||||
// todo : leverage TypeInfo-like info from JdbcEnvironment
|
||||
segmentColumn.setSqlType( dialect.getTypeName( Types.VARCHAR, segmentValueLength, 0, 0 ) );
|
||||
segmentColumn.setNullable( false );
|
||||
|
||||
Column valueColumn = table.createColumn( qualifiedValueColumnName );
|
||||
valueColumn.setSqlType( dialect.getTypeName( Types.BIGINT ) );
|
||||
valueColumn.setNullable( false );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] sqlCreateStrings(Dialect dialect) throws HibernateException {
|
||||
return new String[] {
|
||||
|
|
|
@ -42,6 +42,13 @@ import org.hibernate.id.IdentifierGeneratorHelper;
|
|||
import org.hibernate.id.IntegralDataTypeHolder;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.jdbc.AbstractReturningWork;
|
||||
import org.hibernate.metamodel.spi.relational.Column;
|
||||
import org.hibernate.metamodel.spi.relational.Database;
|
||||
import org.hibernate.metamodel.spi.relational.Identifier;
|
||||
import org.hibernate.metamodel.spi.relational.InitCommand;
|
||||
import org.hibernate.metamodel.spi.relational.ObjectName;
|
||||
import org.hibernate.metamodel.spi.relational.Schema;
|
||||
import org.hibernate.metamodel.spi.relational.Table;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
|
@ -56,8 +63,10 @@ public class TableStructure implements DatabaseStructure {
|
|||
TableStructure.class.getName()
|
||||
);
|
||||
|
||||
private final ObjectName qualifiedTableName;
|
||||
private final Identifier valueColumnName;
|
||||
|
||||
private final String tableName;
|
||||
private final String valueColumnName;
|
||||
private final int initialValue;
|
||||
private final int incrementSize;
|
||||
private final Class numberType;
|
||||
|
@ -69,24 +78,27 @@ public class TableStructure implements DatabaseStructure {
|
|||
|
||||
public TableStructure(
|
||||
Dialect dialect,
|
||||
String tableName,
|
||||
String valueColumnName,
|
||||
ObjectName qualifiedTableName,
|
||||
Identifier valueColumnName,
|
||||
int initialValue,
|
||||
int incrementSize,
|
||||
Class numberType) {
|
||||
this.tableName = tableName;
|
||||
this.qualifiedTableName = qualifiedTableName;
|
||||
this.valueColumnName = valueColumnName;
|
||||
this.tableName = qualifiedTableName.toText( dialect );
|
||||
this.initialValue = initialValue;
|
||||
this.incrementSize = incrementSize;
|
||||
this.valueColumnName = valueColumnName;
|
||||
this.numberType = numberType;
|
||||
|
||||
selectQuery = "select " + valueColumnName + " as id_val" +
|
||||
String valueColumnNameText = valueColumnName.getText( dialect );
|
||||
|
||||
selectQuery = "select " + valueColumnNameText + " as id_val" +
|
||||
" from " + dialect.appendLockHint( LockMode.PESSIMISTIC_WRITE, tableName ) +
|
||||
dialect.getForUpdateString();
|
||||
|
||||
updateQuery = "update " + tableName +
|
||||
" set " + valueColumnName + "= ?" +
|
||||
" where " + valueColumnName + "=?";
|
||||
" set " + valueColumnNameText + "= ?" +
|
||||
" where " + valueColumnNameText + "=?";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -224,6 +236,25 @@ public class TableStructure implements DatabaseStructure {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerExportables(Database database) {
|
||||
final Dialect dialect = database.getJdbcEnvironment().getDialect();
|
||||
final Schema schema = database.getSchemaFor( qualifiedTableName );
|
||||
Table table = schema.locateTable( qualifiedTableName.getName() );
|
||||
if ( table != null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
table = schema.createTable( qualifiedTableName.getName(), qualifiedTableName.getName() );
|
||||
|
||||
Column valueColumn = table.createColumn( valueColumnName );
|
||||
valueColumn.setSqlType( dialect.getTypeName( Types.BIGINT ) );
|
||||
|
||||
database.addInitCommand(
|
||||
new InitCommand( "insert into " + tableName + " values ( " + initialValue + " )" )
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] sqlCreateStrings(Dialect dialect) throws HibernateException {
|
||||
return new String[] {
|
||||
|
|
|
@ -28,6 +28,8 @@ import java.util.Properties;
|
|||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||
import org.hibernate.id.Assigned;
|
||||
|
@ -52,7 +54,6 @@ import org.hibernate.internal.util.ReflectHelper;
|
|||
import org.hibernate.service.spi.ServiceRegistryAwareService;
|
||||
import org.hibernate.service.spi.ServiceRegistryImplementor;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
|
@ -66,6 +67,7 @@ public class DefaultIdentifierGeneratorFactory implements MutableIdentifierGener
|
|||
DefaultIdentifierGeneratorFactory.class.getName());
|
||||
|
||||
private transient Dialect dialect;
|
||||
private transient ClassLoaderService classLoaderService;
|
||||
private ConcurrentHashMap<String, Class> generatorStrategyToClassNameMap = new ConcurrentHashMap<String, Class>();
|
||||
|
||||
/**
|
||||
|
@ -88,7 +90,7 @@ public class DefaultIdentifierGeneratorFactory implements MutableIdentifierGener
|
|||
register( "enhanced-sequence", SequenceStyleGenerator.class );
|
||||
register( "enhanced-table", TableGenerator.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(String strategy, Class generatorClass) {
|
||||
LOG.debugf( "Registering IdentifierGenerator strategy [%s] -> [%s]", strategy, generatorClass.getName() );
|
||||
final Class previous = generatorStrategyToClassNameMap.put( strategy, generatorClass );
|
||||
|
@ -114,7 +116,7 @@ public class DefaultIdentifierGeneratorFactory implements MutableIdentifierGener
|
|||
Class clazz = getIdentifierGeneratorClass( strategy );
|
||||
IdentifierGenerator identifierGenerator = ( IdentifierGenerator ) clazz.newInstance();
|
||||
if ( identifierGenerator instanceof Configurable ) {
|
||||
( ( Configurable ) identifierGenerator ).configure( type, config, dialect );
|
||||
( ( Configurable ) identifierGenerator ).configure( type, config, dialect, classLoaderService );
|
||||
}
|
||||
return identifierGenerator;
|
||||
}
|
||||
|
@ -133,9 +135,19 @@ public class DefaultIdentifierGeneratorFactory implements MutableIdentifierGener
|
|||
Class generatorClass = generatorStrategyToClassNameMap.get( strategy );
|
||||
try {
|
||||
if ( generatorClass == null ) {
|
||||
generatorClass = ReflectHelper.classForName( strategy );
|
||||
// TODO: Exists purely for testing using the old .mappings. Eventually remove.
|
||||
if (classLoaderService == null) {
|
||||
generatorClass = ReflectHelper.classForName( strategy );
|
||||
}
|
||||
else {
|
||||
generatorClass = classLoaderService.classForName( strategy );
|
||||
}
|
||||
register( strategy, generatorClass );
|
||||
}
|
||||
}
|
||||
catch ( ClassLoadingException e ) {
|
||||
throw new MappingException( String.format( "Could not interpret id generator strategy [%s]", strategy ) );
|
||||
}
|
||||
catch ( ClassNotFoundException e ) {
|
||||
throw new MappingException( String.format( "Could not interpret id generator strategy [%s]", strategy ) );
|
||||
}
|
||||
|
@ -145,5 +157,6 @@ public class DefaultIdentifierGeneratorFactory implements MutableIdentifierGener
|
|||
@Override
|
||||
public void injectServices(ServiceRegistryImplementor serviceRegistry) {
|
||||
this.dialect = serviceRegistry.getService( JdbcServices.class ).getDialect();
|
||||
this.classLoaderService = serviceRegistry.getService( ClassLoaderService.class );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ package org.hibernate.integrator.spi;
|
|||
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.metamodel.source.MetadataImplementor;
|
||||
import org.hibernate.metamodel.spi.MetadataImplementor;
|
||||
import org.hibernate.service.spi.SessionFactoryServiceRegistry;
|
||||
|
||||
/**
|
||||
|
|
|
@ -1674,4 +1674,46 @@ public interface CoreMessageLogger extends BasicLogger {
|
|||
"(%2$s=true)"
|
||||
)
|
||||
void applyingExplicitDiscriminatorColumnForJoined(String className, String overrideSetting);
|
||||
|
||||
@Message(value = "@CollectionTable and @JoinTable specified on the same attribute. Check %s#%s", id = 458)
|
||||
String collectionTableAndJoinTableUsedTogether(String entityName, String propertyName);
|
||||
|
||||
@Message(value = "@CollectionTable annotation without a @ElementCollection. Check %s#%s", id = 459)
|
||||
String collectionTableWithoutElementCollection(String entityName, String propertyName);
|
||||
|
||||
@Message(value = "@JoinTable annotation without an association. Check %s#%s", id = 460)
|
||||
String joinTableForNonAssociationAttribute(String entityName, String propertyName);
|
||||
|
||||
@LogMessage( level = ERROR )
|
||||
@Message( value = "Illegal argument on static metamodel field injection : %s#%s; expected type : %s; encountered type : %s", id = 461 )
|
||||
void illegalArgumentOnStaticMetamodelFieldInjection( String metamodelClassName,
|
||||
String attributeName,
|
||||
String attributeJavaType,
|
||||
String metamodelFieldJavaType );
|
||||
// moved from EntityManagerMessageLogger w/ id 15007
|
||||
|
||||
@LogMessage( level = ERROR )
|
||||
@Message( value = "Unable to locate static metamodel field : %s#%s", id = 462 )
|
||||
void unableToLocateStaticMetamodelField( String metamodelClassName,
|
||||
String attributeName );
|
||||
// moved from EntityManagerMessageLogger w/ id 15011
|
||||
|
||||
|
||||
@Message(value = "The access type of class %s is AccessType.FIELD. To override the access for an attribute " +
|
||||
"@Access has to be placed on the property (getter)", id = 463)
|
||||
String accessTypeOverrideShouldBeAnnotatedOnProperty( String className );
|
||||
|
||||
@Message(value = "The access type of class %s is AccessType.FIELD. To override the access for an attribute " +
|
||||
"@Access has to be placed on the property (getter) with an access type of AccessType.PROPERTY. " +
|
||||
"Using AccessType.FIELD on the property has no effect", id = 464)
|
||||
String accessTypeOverrideShouldBeProperty( String className );
|
||||
|
||||
@Message(value = "The access type of class %s is AccessType.PROPERTY. To override the access for a field " +
|
||||
"@Access has to be placed on the field ", id = 465)
|
||||
String accessTypeOverrideShouldBeAnnotatedOnField( String className );
|
||||
|
||||
@Message(value = "The access type of class %s is AccessType.PROPERTY. To override the access for a field " +
|
||||
"@Access has to be placed on the field with an access type of AccessType.FIELD. " +
|
||||
"Using AccessType.PROPERTY on the field has no effect", id = 466)
|
||||
String accessTypeOverrideShouldBeField( String className );
|
||||
}
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, Red Hat Inc. 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 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.internal;
|
||||
|
||||
import org.hibernate.CustomEntityDirtinessStrategy;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
|
||||
/**
|
||||
* The default implementation of {@link CustomEntityDirtinessStrategy} which does nada.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class DefaultCustomEntityDirtinessStrategy implements CustomEntityDirtinessStrategy {
|
||||
public static final DefaultCustomEntityDirtinessStrategy INSTANCE = new DefaultCustomEntityDirtinessStrategy();
|
||||
|
||||
@Override
|
||||
public boolean canDirtyCheck(Object entity, EntityPersister persister, Session session) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDirty(Object entity, EntityPersister persister, Session session) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetDirty(Object entity, EntityPersister persister, Session session) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void findDirty(
|
||||
Object entity,
|
||||
EntityPersister persister,
|
||||
Session session,
|
||||
DirtyCheckContext dirtyCheckContext) {
|
||||
}
|
||||
}
|
|
@ -29,9 +29,11 @@ import java.util.Map;
|
|||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.metamodel.spi.binding.EntityBinding;
|
||||
import org.hibernate.persister.entity.Joinable;
|
||||
|
||||
/**
|
||||
* Captures all relevant metadata specified as part of defining the filter.
|
||||
*
|
||||
* @author Rob Worsnop
|
||||
*/
|
||||
|
@ -42,14 +44,52 @@ public class FilterConfiguration {
|
|||
private final Map<String, String> aliasTableMap;
|
||||
private final Map<String, String> aliasEntityMap;
|
||||
private final PersistentClass persistentClass;
|
||||
|
||||
public FilterConfiguration(String name, String condition, boolean autoAliasInjection, Map<String, String> aliasTableMap, Map<String, String> aliasEntityMap, PersistentClass persistentClass) {
|
||||
private final EntityBinding entityBinding;
|
||||
public FilterConfiguration(
|
||||
String name,
|
||||
String condition,
|
||||
boolean autoAliasInjection,
|
||||
Map<String, String> aliasTableMap,
|
||||
Map<String, String> aliasEntityMap){
|
||||
this.name = name;
|
||||
this.condition = condition;
|
||||
this.autoAliasInjection = autoAliasInjection;
|
||||
this.aliasTableMap = aliasTableMap;
|
||||
this.aliasEntityMap = aliasEntityMap;
|
||||
this.entityBinding = null;
|
||||
this.persistentClass = null;
|
||||
}
|
||||
|
||||
public FilterConfiguration(
|
||||
String name,
|
||||
String condition,
|
||||
boolean autoAliasInjection,
|
||||
Map<String, String> aliasTableMap,
|
||||
Map<String, String> aliasEntityMap,
|
||||
PersistentClass persistentClass) {
|
||||
this.name = name;
|
||||
this.condition = condition;
|
||||
this.autoAliasInjection = autoAliasInjection;
|
||||
this.aliasTableMap = aliasTableMap;
|
||||
this.aliasEntityMap = aliasEntityMap;
|
||||
this.persistentClass = persistentClass;
|
||||
this.entityBinding = null;
|
||||
}
|
||||
|
||||
public FilterConfiguration(
|
||||
String name,
|
||||
String condition,
|
||||
boolean autoAliasInjection,
|
||||
Map<String, String> aliasTableMap,
|
||||
Map<String, String> aliasEntityMap,
|
||||
EntityBinding entityBinding) {
|
||||
this.name = name;
|
||||
this.condition = condition;
|
||||
this.autoAliasInjection = autoAliasInjection;
|
||||
this.aliasTableMap = aliasTableMap;
|
||||
this.aliasEntityMap = aliasEntityMap;
|
||||
this.persistentClass = null;
|
||||
this.entityBinding = entityBinding;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
|
@ -65,28 +105,38 @@ public class FilterConfiguration {
|
|||
}
|
||||
|
||||
public Map<String, String> getAliasTableMap(SessionFactoryImplementor factory) {
|
||||
Map<String,String> mergedAliasTableMap = mergeAliasMaps(factory);
|
||||
if (!mergedAliasTableMap.isEmpty()){
|
||||
Map<String, String> mergedAliasTableMap = mergeAliasMaps( factory );
|
||||
if ( !mergedAliasTableMap.isEmpty() ) {
|
||||
return mergedAliasTableMap;
|
||||
} else if (persistentClass != null){
|
||||
String table = persistentClass.getTable().getQualifiedName(factory.getDialect(),
|
||||
}
|
||||
else if ( persistentClass != null ) {
|
||||
String table = persistentClass.getTable().getQualifiedName(
|
||||
factory.getDialect(),
|
||||
factory.getSettings().getDefaultCatalogName(),
|
||||
factory.getSettings().getDefaultSchemaName());
|
||||
return Collections.singletonMap(null, table);
|
||||
} else{
|
||||
factory.getSettings().getDefaultSchemaName()
|
||||
);
|
||||
return Collections.singletonMap( null, table );
|
||||
}
|
||||
else if ( entityBinding != null ) {
|
||||
String table = entityBinding.getPrimaryTable().getQualifiedName( factory.getDialect() );
|
||||
return Collections.singletonMap( null, table );
|
||||
}
|
||||
else {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String,String> mergeAliasMaps(SessionFactoryImplementor factory){
|
||||
Map<String,String> ret = new HashMap<String, String>();
|
||||
if (aliasTableMap != null){
|
||||
ret.putAll(aliasTableMap);
|
||||
|
||||
private Map<String, String> mergeAliasMaps(SessionFactoryImplementor factory) {
|
||||
Map<String, String> ret = new HashMap<String, String>();
|
||||
if ( aliasTableMap != null ) {
|
||||
ret.putAll( aliasTableMap );
|
||||
}
|
||||
if (aliasEntityMap != null){
|
||||
for (Map.Entry<String, String> entry : aliasEntityMap.entrySet()){
|
||||
ret.put(entry.getKey(),
|
||||
Joinable.class.cast(factory.getEntityPersister(entry.getValue())).getTableName());
|
||||
if ( aliasEntityMap != null ) {
|
||||
for ( Map.Entry<String, String> entry : aliasEntityMap.entrySet() ) {
|
||||
ret.put(
|
||||
entry.getKey(),
|
||||
Joinable.class.cast( factory.getEntityPersister( entry.getValue() ) ).getTableName()
|
||||
);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
|
|
|
@ -43,6 +43,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||
|
||||
import javax.naming.Reference;
|
||||
import javax.naming.StringRefAddr;
|
||||
import javax.persistence.metamodel.Metamodel;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.Cache;
|
||||
|
@ -66,6 +67,7 @@ import org.hibernate.TypeHelper;
|
|||
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
|
||||
import org.hibernate.boot.registry.selector.spi.StrategySelector;
|
||||
import org.hibernate.cache.internal.CacheDataDescriptionImpl;
|
||||
import org.hibernate.cache.spi.CollectionRegion;
|
||||
import org.hibernate.cache.spi.EntityRegion;
|
||||
|
@ -83,7 +85,6 @@ import org.hibernate.cfg.AvailableSettings;
|
|||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.cfg.Settings;
|
||||
import org.hibernate.cfg.SettingsFactory;
|
||||
import org.hibernate.cfg.annotations.NamedProcedureCallDefinition;
|
||||
import org.hibernate.context.internal.JTASessionContext;
|
||||
import org.hibernate.context.internal.ManagedSessionContext;
|
||||
|
@ -125,14 +126,16 @@ import org.hibernate.id.UUIDGenerator;
|
|||
import org.hibernate.id.factory.IdentifierGeneratorFactory;
|
||||
import org.hibernate.integrator.spi.Integrator;
|
||||
import org.hibernate.integrator.spi.IntegratorService;
|
||||
import org.hibernate.jpa.metamodel.internal.JpaMetaModelPopulationSetting;
|
||||
import org.hibernate.jpa.metamodel.internal.builder.MetamodelBuilder;
|
||||
import org.hibernate.mapping.Collection;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.mapping.RootClass;
|
||||
import org.hibernate.metadata.ClassMetadata;
|
||||
import org.hibernate.metadata.CollectionMetadata;
|
||||
import org.hibernate.metamodel.binding.EntityBinding;
|
||||
import org.hibernate.metamodel.binding.PluralAttributeBinding;
|
||||
import org.hibernate.metamodel.source.MetadataImplementor;
|
||||
import org.hibernate.metamodel.spi.binding.EntityBinding;
|
||||
import org.hibernate.metamodel.spi.binding.PluralAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.MetadataImplementor;
|
||||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.persister.entity.Loadable;
|
||||
|
@ -216,20 +219,53 @@ public final class SessionFactoryImpl
|
|||
private final transient TypeHelper typeHelper;
|
||||
private final transient TransactionEnvironment transactionEnvironment;
|
||||
private final transient SessionFactoryOptions sessionFactoryOptions;
|
||||
private final transient CustomEntityDirtinessStrategy customEntityDirtinessStrategy;
|
||||
private final transient CurrentTenantIdentifierResolver currentTenantIdentifierResolver;
|
||||
private final transient Metamodel jpaMetamodel;
|
||||
|
||||
@SuppressWarnings( {"unchecked", "ThrowableResultOfMethodCallIgnored"})
|
||||
public SessionFactoryImpl(
|
||||
final Configuration cfg,
|
||||
Mapping mapping,
|
||||
final ServiceRegistry serviceRegistry,
|
||||
Settings settings,
|
||||
SessionFactoryObserver observer) throws HibernateException {
|
||||
final Settings settings,
|
||||
final SessionFactoryObserver userObserver) throws HibernateException {
|
||||
LOG.debug( "Building session factory" );
|
||||
|
||||
sessionFactoryOptions = new SessionFactoryOptions() {
|
||||
private EntityNotFoundDelegate entityNotFoundDelegate;
|
||||
private final Interceptor interceptor;
|
||||
private final CustomEntityDirtinessStrategy customEntityDirtinessStrategy;
|
||||
private final CurrentTenantIdentifierResolver currentTenantIdentifierResolver;
|
||||
private final EntityNotFoundDelegate entityNotFoundDelegate;
|
||||
|
||||
{
|
||||
interceptor = cfg.getInterceptor();
|
||||
|
||||
customEntityDirtinessStrategy = serviceRegistry.getService( StrategySelector.class ).resolveDefaultableStrategy(
|
||||
CustomEntityDirtinessStrategy.class,
|
||||
cfg.getProperties().get( AvailableSettings.CUSTOM_ENTITY_DIRTINESS_STRATEGY ),
|
||||
DefaultCustomEntityDirtinessStrategy.INSTANCE
|
||||
);
|
||||
|
||||
if ( cfg.getCurrentTenantIdentifierResolver() != null ) {
|
||||
currentTenantIdentifierResolver = cfg.getCurrentTenantIdentifierResolver();
|
||||
}
|
||||
else {
|
||||
currentTenantIdentifierResolver =serviceRegistry.getService( StrategySelector.class ).resolveStrategy(
|
||||
CurrentTenantIdentifierResolver.class,
|
||||
cfg.getProperties().get( AvailableSettings.MULTI_TENANT_IDENTIFIER_RESOLVER )
|
||||
);
|
||||
}
|
||||
|
||||
if ( cfg.getEntityNotFoundDelegate() != null ) {
|
||||
entityNotFoundDelegate = cfg.getEntityNotFoundDelegate();
|
||||
}
|
||||
else {
|
||||
entityNotFoundDelegate = new EntityNotFoundDelegate() {
|
||||
public void handleEntityNotFound(String entityName, Serializable id) {
|
||||
throw new ObjectNotFoundException( id, entityName );
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public StandardServiceRegistry getServiceRegistry() {
|
||||
|
@ -238,22 +274,39 @@ public final class SessionFactoryImpl
|
|||
|
||||
@Override
|
||||
public Interceptor getInterceptor() {
|
||||
return cfg.getInterceptor();
|
||||
return interceptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustomEntityDirtinessStrategy getCustomEntityDirtinessStrategy() {
|
||||
return customEntityDirtinessStrategy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CurrentTenantIdentifierResolver getCurrentTenantIdentifierResolver() {
|
||||
return currentTenantIdentifierResolver;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SessionFactoryObserver[] getSessionFactoryObservers() {
|
||||
return userObserver == null
|
||||
? new SessionFactoryObserver[0]
|
||||
: new SessionFactoryObserver[] { userObserver };
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityNameResolver[] getEntityNameResolvers() {
|
||||
return new EntityNameResolver[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Settings getSettings() {
|
||||
return settings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityNotFoundDelegate getEntityNotFoundDelegate() {
|
||||
if ( entityNotFoundDelegate == null ) {
|
||||
if ( cfg.getEntityNotFoundDelegate() != null ) {
|
||||
entityNotFoundDelegate = cfg.getEntityNotFoundDelegate();
|
||||
}
|
||||
else {
|
||||
entityNotFoundDelegate = new EntityNotFoundDelegate() {
|
||||
public void handleEntityNotFound(String entityName, Serializable id) {
|
||||
throw new ObjectNotFoundException( id, entityName );
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
return entityNotFoundDelegate;
|
||||
}
|
||||
|
@ -272,7 +325,7 @@ public final class SessionFactoryImpl
|
|||
this.dialect = this.jdbcServices.getDialect();
|
||||
this.cacheAccess = this.serviceRegistry.getService( CacheImplementor.class );
|
||||
this.sqlFunctionRegistry = new SQLFunctionRegistry( getDialect(), cfg.getSqlFunctions() );
|
||||
if ( observer != null ) {
|
||||
for ( SessionFactoryObserver observer : sessionFactoryOptions.getSessionFactoryObservers() ) {
|
||||
this.observer.addObserver( observer );
|
||||
}
|
||||
|
||||
|
@ -481,6 +534,12 @@ public final class SessionFactoryImpl
|
|||
persister.postInstantiate();
|
||||
registerEntityNameResolvers( persister );
|
||||
}
|
||||
if ( sessionFactoryOptions.getEntityNameResolvers() != null ) {
|
||||
for ( EntityNameResolver resolver : sessionFactoryOptions.getEntityNameResolvers() ) {
|
||||
registerEntityNameResolver( resolver );
|
||||
}
|
||||
}
|
||||
|
||||
for ( CollectionPersister persister : collectionPersisters.values() ) {
|
||||
persister.postInstantiate();
|
||||
}
|
||||
|
@ -582,10 +641,20 @@ public final class SessionFactoryImpl
|
|||
fetchProfiles.put( fetchProfile.getName(), fetchProfile );
|
||||
}
|
||||
|
||||
this.customEntityDirtinessStrategy = determineCustomEntityDirtinessStrategy();
|
||||
this.currentTenantIdentifierResolver = determineCurrentTenantIdentifierResolver( cfg.getCurrentTenantIdentifierResolver() );
|
||||
this.transactionEnvironment = new TransactionEnvironmentImpl( this );
|
||||
this.observer.sessionFactoryCreated( this );
|
||||
|
||||
final JpaMetaModelPopulationSetting jpaMetaModelPopulationSetting = determineJpaMetaModelPopulationSetting( cfg );
|
||||
if ( jpaMetaModelPopulationSetting != JpaMetaModelPopulationSetting.DISABLED ) {
|
||||
this.jpaMetamodel = org.hibernate.jpa.metamodel.internal.legacy.MetamodelImpl.buildMetamodel(
|
||||
cfg.getClassMappings(),
|
||||
this,
|
||||
jpaMetaModelPopulationSetting == JpaMetaModelPopulationSetting.IGNORE_UNSUPPORTED
|
||||
);
|
||||
}
|
||||
else {
|
||||
jpaMetamodel = null;
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, ProcedureCallMemento> toProcedureCallMementos(
|
||||
|
@ -626,59 +695,16 @@ public final class SessionFactoryImpl
|
|||
};
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
private CustomEntityDirtinessStrategy determineCustomEntityDirtinessStrategy() {
|
||||
CustomEntityDirtinessStrategy defaultValue = new CustomEntityDirtinessStrategy() {
|
||||
@Override
|
||||
public boolean canDirtyCheck(Object entity, EntityPersister persister, Session session) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDirty(Object entity, EntityPersister persister, Session session) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetDirty(Object entity, EntityPersister persister, Session session) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void findDirty(
|
||||
Object entity,
|
||||
EntityPersister persister,
|
||||
Session session,
|
||||
DirtyCheckContext dirtyCheckContext) {
|
||||
// todo : implement proper method body
|
||||
}
|
||||
};
|
||||
return serviceRegistry.getService( ConfigurationService.class ).getSetting(
|
||||
AvailableSettings.CUSTOM_ENTITY_DIRTINESS_STRATEGY,
|
||||
CustomEntityDirtinessStrategy.class,
|
||||
defaultValue
|
||||
);
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
private CurrentTenantIdentifierResolver determineCurrentTenantIdentifierResolver(
|
||||
CurrentTenantIdentifierResolver explicitResolver) {
|
||||
if ( explicitResolver != null ) {
|
||||
return explicitResolver;
|
||||
}
|
||||
return serviceRegistry.getService( ConfigurationService.class )
|
||||
.getSetting(
|
||||
AvailableSettings.MULTI_TENANT_IDENTIFIER_RESOLVER,
|
||||
CurrentTenantIdentifierResolver.class,
|
||||
null
|
||||
);
|
||||
|
||||
protected JpaMetaModelPopulationSetting determineJpaMetaModelPopulationSetting(Configuration cfg) {
|
||||
final String setting = cfg.getProperties().getProperty( AvailableSettings.JPA_METAMODEL_POPULATION );
|
||||
return JpaMetaModelPopulationSetting.parse( setting );
|
||||
}
|
||||
|
||||
@SuppressWarnings( {"ThrowableResultOfMethodCallIgnored"})
|
||||
public SessionFactoryImpl(
|
||||
MetadataImplementor metadata,
|
||||
SessionFactoryOptions sessionFactoryOptions,
|
||||
SessionFactoryObserver observer) throws HibernateException {
|
||||
SessionFactoryOptions providedSessionFactoryOptions) throws HibernateException {
|
||||
|
||||
final boolean traceEnabled = LOG.isTraceEnabled();
|
||||
final boolean debugEnabled = traceEnabled || LOG.isDebugEnabled();
|
||||
|
@ -686,17 +712,13 @@ public final class SessionFactoryImpl
|
|||
LOG.debug( "Building session factory" );
|
||||
}
|
||||
|
||||
this.sessionFactoryOptions = sessionFactoryOptions;
|
||||
this.sessionFactoryOptions = providedSessionFactoryOptions;
|
||||
|
||||
this.properties = createPropertiesFromMap(
|
||||
metadata.getServiceRegistry().getService( ConfigurationService.class ).getSettings()
|
||||
);
|
||||
|
||||
// TODO: these should be moved into SessionFactoryOptions
|
||||
this.settings = new SettingsFactory().buildSettings(
|
||||
properties,
|
||||
metadata.getServiceRegistry()
|
||||
);
|
||||
this.settings = sessionFactoryOptions.getSettings();
|
||||
|
||||
this.serviceRegistry =
|
||||
sessionFactoryOptions.getServiceRegistry()
|
||||
|
@ -714,17 +736,16 @@ public final class SessionFactoryImpl
|
|||
// TODO: get SQL functions from a new service
|
||||
// this.sqlFunctionRegistry = new SQLFunctionRegistry( getDialect(), cfg.getSqlFunctions() );
|
||||
|
||||
if ( observer != null ) {
|
||||
this.observer.addObserver( observer );
|
||||
if ( sessionFactoryOptions.getSessionFactoryObservers() != null ) {
|
||||
for ( SessionFactoryObserver observer : sessionFactoryOptions.getSessionFactoryObservers() ) {
|
||||
this.observer.addObserver( observer );
|
||||
}
|
||||
}
|
||||
|
||||
this.typeResolver = metadata.getTypeResolver().scope( this );
|
||||
this.typeHelper = new TypeLocatorImpl( typeResolver );
|
||||
|
||||
this.filters = new HashMap<String, FilterDefinition>();
|
||||
for ( FilterDefinition filterDefinition : metadata.getFilterDefinitions() ) {
|
||||
filters.put( filterDefinition.getFilterName(), filterDefinition );
|
||||
}
|
||||
this.filters = Collections.unmodifiableMap( metadata.getFilterDefinitions() );
|
||||
|
||||
if ( debugEnabled ) {
|
||||
LOG.debugf( "Session factory constructed with filter configurations : %s", filters );
|
||||
|
@ -772,14 +793,21 @@ public final class SessionFactoryImpl
|
|||
// Prepare persisters and link them up with their cache
|
||||
// region/access-strategy
|
||||
|
||||
final MetamodelBuilder jpaMetamodelBuilder = new MetamodelBuilder(
|
||||
this,
|
||||
JpaMetaModelPopulationSetting.parse(
|
||||
properties.getProperty( AvailableSettings.JPA_METAMODEL_POPULATION )
|
||||
)
|
||||
);
|
||||
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
if ( settings.getCacheRegionPrefix() != null) {
|
||||
stringBuilder
|
||||
.append( settings.getCacheRegionPrefix() )
|
||||
.append( '.' );
|
||||
}
|
||||
RegionFactory regionFactory = cacheAccess.getRegionFactory();
|
||||
final String cacheRegionPrefix = stringBuilder.toString();
|
||||
|
||||
entityPersisters = new HashMap<String,EntityPersister>();
|
||||
Map<String, RegionAccessStrategy> entityAccessStrategies = new HashMap<String, RegionAccessStrategy>();
|
||||
Map<String,ClassMetadata> classMeta = new HashMap<String,ClassMetadata>();
|
||||
|
@ -791,16 +819,18 @@ public final class SessionFactoryImpl
|
|||
EntityRegionAccessStrategy accessStrategy = null;
|
||||
if ( settings.isSecondLevelCacheEnabled() &&
|
||||
rootEntityBinding.getHierarchyDetails().getCaching() != null &&
|
||||
model.getHierarchyDetails().getCaching() != null &&
|
||||
model.getHierarchyDetails().getCaching().getAccessType() != null ) {
|
||||
model.getHierarchyDetails().getCaching() != null ) {
|
||||
final String cacheRegionName = cacheRegionPrefix + rootEntityBinding.getHierarchyDetails().getCaching().getRegion();
|
||||
accessStrategy = EntityRegionAccessStrategy.class.cast( entityAccessStrategies.get( cacheRegionName ) );
|
||||
if ( accessStrategy == null ) {
|
||||
final AccessType accessType = model.getHierarchyDetails().getCaching().getAccessType();
|
||||
AccessType accessType = model.getHierarchyDetails().getCaching().getAccessType();
|
||||
if ( accessType == null ) {
|
||||
accessType = regionFactory.getDefaultAccessType();
|
||||
}
|
||||
if ( traceEnabled ) {
|
||||
LOG.tracev( "Building cache for entity data [{0}]", model.getEntity().getName() );
|
||||
}
|
||||
EntityRegion entityRegion = settings.getRegionFactory().buildEntityRegion(
|
||||
EntityRegion entityRegion = regionFactory.buildEntityRegion(
|
||||
cacheRegionName, properties, CacheDataDescriptionImpl.decode( model )
|
||||
);
|
||||
accessStrategy = entityRegion.buildAccessStrategy( accessType );
|
||||
|
@ -808,11 +838,47 @@ public final class SessionFactoryImpl
|
|||
cacheAccess.addCacheRegion( cacheRegionName, entityRegion );
|
||||
}
|
||||
}
|
||||
NaturalIdRegionAccessStrategy naturalIdAccessStrategy = null;
|
||||
if ( settings.isSecondLevelCacheEnabled() &&
|
||||
rootEntityBinding.getHierarchyDetails().getNaturalIdCaching() != null &&
|
||||
model.getHierarchyDetails().getNaturalIdCaching() != null ) {
|
||||
final String naturalIdCacheRegionName = cacheRegionPrefix + rootEntityBinding.getHierarchyDetails()
|
||||
.getNaturalIdCaching()
|
||||
.getRegion();
|
||||
naturalIdAccessStrategy = (NaturalIdRegionAccessStrategy) entityAccessStrategies.get(
|
||||
naturalIdCacheRegionName
|
||||
);
|
||||
if ( naturalIdAccessStrategy == null ) {
|
||||
final CacheDataDescriptionImpl naturaIdCacheDataDescription = CacheDataDescriptionImpl.decode( model );
|
||||
NaturalIdRegion naturalIdRegion = null;
|
||||
try {
|
||||
naturalIdRegion = regionFactory.buildNaturalIdRegion(
|
||||
naturalIdCacheRegionName,
|
||||
properties,
|
||||
naturaIdCacheDataDescription
|
||||
);
|
||||
}
|
||||
catch ( UnsupportedOperationException e ) {
|
||||
LOG.warnf(
|
||||
"Shared cache region factory [%s] does not support natural id caching; " +
|
||||
"shared NaturalId caching will be disabled for not be enabled for %s",
|
||||
regionFactory.getClass().getName(),
|
||||
model.getEntity().getName()
|
||||
);
|
||||
}
|
||||
if ( naturalIdRegion != null ) {
|
||||
naturalIdAccessStrategy = naturalIdRegion.buildAccessStrategy( regionFactory.getDefaultAccessType() );
|
||||
entityAccessStrategies.put( naturalIdCacheRegionName, naturalIdAccessStrategy );
|
||||
cacheAccess.addCacheRegion( naturalIdCacheRegionName, naturalIdRegion );
|
||||
}
|
||||
}
|
||||
}
|
||||
EntityPersister cp = serviceRegistry.getService( PersisterFactory.class ).createEntityPersister(
|
||||
model, accessStrategy, this, metadata
|
||||
model, accessStrategy, naturalIdAccessStrategy, this, metadata
|
||||
);
|
||||
entityPersisters.put( model.getEntity().getName(), cp );
|
||||
classMeta.put( model.getEntity().getName(), cp.getClassMetadata() );
|
||||
jpaMetamodelBuilder.add( model );
|
||||
}
|
||||
this.classMetadata = Collections.unmodifiableMap(classMeta);
|
||||
|
||||
|
@ -828,19 +894,32 @@ public final class SessionFactoryImpl
|
|||
"AbstractPluralAttributeBinding has a Singular attribute defined: " + model.getAttribute().getName()
|
||||
);
|
||||
}
|
||||
final String cacheRegionName = cacheRegionPrefix + model.getCaching().getRegion();
|
||||
final AccessType accessType = model.getCaching().getAccessType();
|
||||
CollectionRegionAccessStrategy accessStrategy = null;
|
||||
if ( accessType != null && settings.isSecondLevelCacheEnabled() ) {
|
||||
if ( traceEnabled ) {
|
||||
LOG.tracev( "Building cache for collection data [{0}]", model.getAttribute().getRole() );
|
||||
if ( settings.isSecondLevelCacheEnabled() &&
|
||||
model.getCaching() != null ) {
|
||||
|
||||
final String cacheRegionName = cacheRegionPrefix + model.getCaching().getRegion();
|
||||
AccessType accessType = model.getCaching().getAccessType();
|
||||
if( accessType == null ){
|
||||
accessType = regionFactory.getDefaultAccessType();
|
||||
}
|
||||
CollectionRegion collectionRegion = settings.getRegionFactory().buildCollectionRegion(
|
||||
if ( accessType != null && settings.isSecondLevelCacheEnabled() ) {
|
||||
if ( traceEnabled ) {
|
||||
LOG.tracev( "Building cache for collection data [{0}]", model.getAttribute().getRole() );
|
||||
}
|
||||
CollectionRegion collectionRegion = regionFactory.buildCollectionRegion(
|
||||
cacheRegionName, properties, CacheDataDescriptionImpl.decode( model )
|
||||
);
|
||||
accessStrategy = collectionRegion.buildAccessStrategy( accessType );
|
||||
entityAccessStrategies.put( cacheRegionName, accessStrategy );
|
||||
cacheAccess.addCacheRegion( cacheRegionName, collectionRegion );
|
||||
}
|
||||
CollectionRegion collectionRegion = regionFactory.buildCollectionRegion(
|
||||
cacheRegionName, properties, CacheDataDescriptionImpl.decode( model )
|
||||
);
|
||||
accessStrategy = collectionRegion.buildAccessStrategy( accessType );
|
||||
entityAccessStrategies.put( cacheRegionName, accessStrategy );
|
||||
cacheAccess.addCacheRegion( cacheRegionName, collectionRegion );
|
||||
cacheAccess.addCacheRegion( cacheRegionName, collectionRegion );
|
||||
}
|
||||
CollectionPersister persister = serviceRegistry
|
||||
.getService( PersisterFactory.class )
|
||||
|
@ -879,26 +958,32 @@ public final class SessionFactoryImpl
|
|||
namedQueryRepository = new NamedQueryRepository(
|
||||
metadata.getNamedQueryDefinitions(),
|
||||
metadata.getNamedNativeQueryDefinitions(),
|
||||
metadata.getResultSetMappingDefinitions(),
|
||||
metadata.getResultSetMappingDefinitions().values(),
|
||||
new HashMap<String, ProcedureCallMemento>( )
|
||||
);
|
||||
|
||||
imports = new HashMap<String,String>();
|
||||
for ( Map.Entry<String,String> importEntry : metadata.getImports() ) {
|
||||
for ( Map.Entry<String,String> importEntry : metadata.getImports().entrySet() ) {
|
||||
imports.put( importEntry.getKey(), importEntry.getValue() );
|
||||
}
|
||||
|
||||
// after *all* persisters and named queries are registered
|
||||
Iterator iter = entityPersisters.values().iterator();
|
||||
while ( iter.hasNext() ) {
|
||||
final EntityPersister persister = ( ( EntityPersister ) iter.next() );
|
||||
for ( EntityPersister persister : entityPersisters.values() ) {
|
||||
persister.generateEntityDefinition();
|
||||
}
|
||||
|
||||
for ( EntityPersister persister : entityPersisters.values() ) {
|
||||
persister.postInstantiate();
|
||||
registerEntityNameResolvers( persister );
|
||||
|
||||
}
|
||||
iter = collectionPersisters.values().iterator();
|
||||
while ( iter.hasNext() ) {
|
||||
final CollectionPersister persister = ( ( CollectionPersister ) iter.next() );
|
||||
|
||||
if ( sessionFactoryOptions.getEntityNameResolvers() != null ) {
|
||||
for ( EntityNameResolver resolver : sessionFactoryOptions.getEntityNameResolvers() ) {
|
||||
registerEntityNameResolver( resolver );
|
||||
}
|
||||
}
|
||||
|
||||
for ( CollectionPersister persister : collectionPersisters.values() ) {
|
||||
persister.postInstantiate();
|
||||
}
|
||||
|
||||
|
@ -923,12 +1008,29 @@ public final class SessionFactoryImpl
|
|||
LOG.debug("Instantiated session factory");
|
||||
}
|
||||
|
||||
// TODO: FIX this
|
||||
//settings.getMultiTableBulkIdStrategy().prepare(
|
||||
// jdbcServices,
|
||||
// buildLocalConnectionAccess(),
|
||||
// mapp,
|
||||
// metadata,
|
||||
// properties
|
||||
//);
|
||||
|
||||
|
||||
if ( settings.isAutoCreateSchema() ) {
|
||||
new SchemaExport( metadata )
|
||||
.setImportSqlCommandExtractor( serviceRegistry.getService( ImportSqlCommandExtractor.class ) )
|
||||
.create( false, true );
|
||||
}
|
||||
|
||||
// TODO: implement these for new metamodel
|
||||
//if ( settings.isAutoUpdateSchema() ) {
|
||||
// new SchemaUpdate( metadata ).execute( false, true );
|
||||
//}
|
||||
//if ( settings.isAutoValidateSchema() ) {
|
||||
// new SchemaValidator( metadata ).validate();
|
||||
//}
|
||||
if ( settings.isAutoDropSchema() ) {
|
||||
schemaExport = new SchemaExport( metadata )
|
||||
.setImportSqlCommandExtractor( serviceRegistry.getService( ImportSqlCommandExtractor.class ) );
|
||||
|
@ -953,9 +1055,9 @@ public final class SessionFactoryImpl
|
|||
|
||||
// this needs to happen after persisters are all ready to go...
|
||||
this.fetchProfiles = new HashMap<String,FetchProfile>();
|
||||
for ( org.hibernate.metamodel.binding.FetchProfile mappingProfile : metadata.getFetchProfiles() ) {
|
||||
for ( org.hibernate.metamodel.spi.binding.FetchProfile mappingProfile : metadata.getFetchProfiles() ) {
|
||||
final FetchProfile fetchProfile = new FetchProfile( mappingProfile.getName() );
|
||||
for ( org.hibernate.metamodel.binding.FetchProfile.Fetch mappingFetch : mappingProfile.getFetches() ) {
|
||||
for ( org.hibernate.metamodel.spi.binding.FetchProfile.Fetch mappingFetch : mappingProfile.getFetches() ) {
|
||||
// resolve the persister owning the fetch
|
||||
final String entityName = getImportedClassName( mappingFetch.getEntity() );
|
||||
final EntityPersister owner = entityName == null ? null : entityPersisters.get( entityName );
|
||||
|
@ -982,10 +1084,10 @@ public final class SessionFactoryImpl
|
|||
fetchProfiles.put( fetchProfile.getName(), fetchProfile );
|
||||
}
|
||||
|
||||
this.customEntityDirtinessStrategy = determineCustomEntityDirtinessStrategy();
|
||||
this.currentTenantIdentifierResolver = determineCurrentTenantIdentifierResolver( null );
|
||||
this.transactionEnvironment = new TransactionEnvironmentImpl( this );
|
||||
this.observer.sessionFactoryCreated( this );
|
||||
|
||||
this.jpaMetamodel = jpaMetamodelBuilder.buildMetamodel();
|
||||
}
|
||||
|
||||
@SuppressWarnings( {"unchecked"} )
|
||||
|
@ -1708,12 +1810,12 @@ public final class SessionFactoryImpl
|
|||
|
||||
@Override
|
||||
public CustomEntityDirtinessStrategy getCustomEntityDirtinessStrategy() {
|
||||
return customEntityDirtinessStrategy;
|
||||
return sessionFactoryOptions.getCustomEntityDirtinessStrategy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CurrentTenantIdentifierResolver getCurrentTenantIdentifierResolver() {
|
||||
return currentTenantIdentifierResolver;
|
||||
return sessionFactoryOptions.getCurrentTenantIdentifierResolver();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -24,10 +24,22 @@
|
|||
*/
|
||||
package org.hibernate.internal.util;
|
||||
|
||||
import java.beans.Introspector;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Member;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.fasterxml.classmate.MemberResolver;
|
||||
import com.fasterxml.classmate.ResolvedType;
|
||||
import com.fasterxml.classmate.ResolvedTypeWithMembers;
|
||||
import com.fasterxml.classmate.TypeResolver;
|
||||
import com.fasterxml.classmate.members.ResolvedField;
|
||||
import com.fasterxml.classmate.members.ResolvedMethod;
|
||||
import com.fasterxml.classmate.types.ResolvedArrayType;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.MappingException;
|
||||
|
@ -60,6 +72,9 @@ public final class ReflectHelper {
|
|||
private static final Method OBJECT_EQUALS;
|
||||
private static final Method OBJECT_HASHCODE;
|
||||
|
||||
private static final TypeResolver TYPE_RESOLVER = new TypeResolver();
|
||||
private static final MemberResolver MEMBER_RESOLVER = new MemberResolver( TYPE_RESOLVER );
|
||||
|
||||
static {
|
||||
Method eq;
|
||||
Method hash;
|
||||
|
@ -378,4 +393,92 @@ public final class ReflectHelper {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process bean properties getter by applying the JavaBean naming conventions.
|
||||
*
|
||||
* @param member the member for which to get the property name.
|
||||
*
|
||||
* @return The bean method name with the "is" or "get" prefix stripped off, {@code null}
|
||||
* the method name id not according to the JavaBeans standard.
|
||||
*/
|
||||
public static String getPropertyName(Member member) {
|
||||
String name = null;
|
||||
|
||||
if ( member instanceof Field ) {
|
||||
name = member.getName();
|
||||
}
|
||||
|
||||
if ( member instanceof Method ) {
|
||||
String methodName = member.getName();
|
||||
if ( methodName.startsWith( "is" ) ) {
|
||||
name = Introspector.decapitalize( methodName.substring( 2 ) );
|
||||
}
|
||||
else if ( methodName.startsWith( "has" ) ) {
|
||||
name = Introspector.decapitalize( methodName.substring( 3 ) );
|
||||
}
|
||||
else if ( methodName.startsWith( "get" ) ) {
|
||||
name = Introspector.decapitalize( methodName.substring( 3 ) );
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
public static boolean isProperty(Member m) {
|
||||
if ( m instanceof Method ) {
|
||||
Method method = (Method) m;
|
||||
return !method.isSynthetic()
|
||||
&& !method.isBridge()
|
||||
&& !Modifier.isStatic( method.getModifiers() )
|
||||
&& method.getParameterTypes().length == 0
|
||||
&& ( method.getName().startsWith( "get" ) || method.getName().startsWith( "is" ) );
|
||||
}
|
||||
else {
|
||||
return !Modifier.isTransient( m.getModifiers() ) && !m.isSynthetic();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Set of field types in the given class. However, for Collection
|
||||
* and Map fields, the value and key types are returned instead of the
|
||||
* Iterable class itself.
|
||||
*
|
||||
* @param clazz
|
||||
* @return Set<Class<?>>
|
||||
*/
|
||||
// TODO: This should be moved out of ReflectHelper. Partial duplication with
|
||||
// AnnotationBindingContextImpl#resolveMemberTypes
|
||||
public static Set<Class<?>> getMemberTypes( Class<?> clazz ) {
|
||||
Set<Class<?>> fieldTypes = new HashSet<Class<?>>();
|
||||
|
||||
ResolvedType resolvedType = TYPE_RESOLVER.resolve( clazz );
|
||||
ResolvedTypeWithMembers resolvedTypes = MEMBER_RESOLVER.resolve( resolvedType, null, null );
|
||||
ResolvedField[] resolvedFields = resolvedTypes.getMemberFields();
|
||||
|
||||
for ( ResolvedField resolvedField : resolvedFields ) {
|
||||
resolveAllTypes( resolvedField.getType(), fieldTypes );
|
||||
}
|
||||
|
||||
// TODO: This should really just be checking getters, but for now do everything.
|
||||
ResolvedMethod[] resolvedMethods = resolvedTypes.getMemberMethods();
|
||||
for ( ResolvedMethod resolvedMethod : resolvedMethods ) {
|
||||
if ( resolvedMethod.getReturnType() != null ) {
|
||||
resolveAllTypes( resolvedMethod.getReturnType(), fieldTypes );
|
||||
}
|
||||
}
|
||||
|
||||
return fieldTypes;
|
||||
}
|
||||
|
||||
private static void resolveAllTypes(ResolvedType fieldType, Set<Class<?>> fieldTypes) {
|
||||
if ( fieldType instanceof ResolvedArrayType ) {
|
||||
ResolvedArrayType arrayType = (ResolvedArrayType) fieldType;
|
||||
resolveAllTypes( arrayType.getArrayElementType(), fieldTypes );
|
||||
} else {
|
||||
fieldTypes.add( fieldType.getErasedType() );
|
||||
}
|
||||
|
||||
for ( ResolvedType typeParameter : fieldType.getTypeBindings().getTypeParameters() ) {
|
||||
resolveAllTypes( typeParameter, fieldTypes );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ public final class StringHelper {
|
|||
|
||||
private static final int ALIAS_TRUNCATE_LENGTH = 10;
|
||||
public static final String WHITESPACE = " \n\r\f\t";
|
||||
public static final String [] EMPTY_STRINGS = new String[0];
|
||||
|
||||
private StringHelper() { /* static methods only - hide constructor */
|
||||
}
|
||||
|
@ -454,6 +455,10 @@ public final class StringHelper {
|
|||
return string == null || string.length() == 0;
|
||||
}
|
||||
|
||||
public static boolean isEmptyOrWhiteSpace(String string){
|
||||
return isEmpty( string ) || isEmpty( string.trim() );
|
||||
}
|
||||
|
||||
public static String qualify(String prefix, String name) {
|
||||
if ( name == null || prefix == null ) {
|
||||
throw new NullPointerException( "prefix or name were null attempting to build qualified name" );
|
||||
|
|
|
@ -339,6 +339,17 @@ public final class ArrayHelper {
|
|||
return PRIME_NUMER * seed + i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the specified array is {@code null} or empty.
|
||||
*
|
||||
* @param array the array to check.
|
||||
* @return {@code true} if the specified array is {@code null} or empty.
|
||||
*/
|
||||
|
||||
public static boolean isEmpty(final Object[] array) {
|
||||
return array == null || array.length == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare 2 arrays only at the first level
|
||||
*/
|
||||
|
|
|
@ -156,7 +156,11 @@ public final class CollectionHelper {
|
|||
return collection == null || collection.isEmpty();
|
||||
}
|
||||
|
||||
public static boolean isEmpty(Map map) {
|
||||
public static boolean isEmpty(Iterable iterable){
|
||||
return iterable == null || !iterable.iterator().hasNext();
|
||||
}
|
||||
|
||||
public static boolean isEmpty(Map map) {
|
||||
return map == null || map.isEmpty();
|
||||
}
|
||||
|
||||
|
@ -172,6 +176,23 @@ public final class CollectionHelper {
|
|||
return objects == null || objects.length==0;
|
||||
}
|
||||
|
||||
public static boolean isCollectionOrArray(Class clazz) {
|
||||
if ( clazz == null ) {
|
||||
return false;
|
||||
}
|
||||
if ( Collection.class.isAssignableFrom( clazz ) ) {
|
||||
return true;
|
||||
}
|
||||
if ( Map.class.isAssignableFrom( clazz ) ) {
|
||||
return true;
|
||||
}
|
||||
// TODO: why is the next block commented out???
|
||||
// if ( clazz.isArray() ) {
|
||||
// return true;
|
||||
// }
|
||||
return false;
|
||||
}
|
||||
|
||||
public static <X,Y> Map<X, Y> makeCopy(Map<X, Y> map) {
|
||||
final Map<X,Y> copy = mapOfSize( map.size() + 1 );
|
||||
copy.putAll( map );
|
||||
|
|
|
@ -224,7 +224,8 @@ public class MappingReader {
|
|||
public static enum SupportedOrmXsdVersion {
|
||||
ORM_1_0( "org/hibernate/jpa/orm_1_0.xsd" ),
|
||||
ORM_2_0( "org/hibernate/jpa/orm_2_0.xsd" ),
|
||||
ORM_2_1( "org/hibernate/jpa/orm_2_1.xsd" );
|
||||
ORM_2_1( "org/hibernate/jpa/orm_2_1.xsd" ),
|
||||
HBM_4_0( "org/hibernate/hibernate-mapping-4.0.xsd");
|
||||
|
||||
private final String schemaResourceName;
|
||||
|
||||
|
@ -242,6 +243,9 @@ public class MappingReader {
|
|||
else if ( "2.1".equals( name ) ) {
|
||||
return ORM_2_1;
|
||||
}
|
||||
else if ( "4.0".equals( name ) ) {
|
||||
return HBM_4_0;
|
||||
}
|
||||
throw new UnsupportedOrmXsdVersionException( name, origin );
|
||||
}
|
||||
|
||||
|
@ -264,7 +268,7 @@ public class MappingReader {
|
|||
}
|
||||
}
|
||||
|
||||
private static URL resolveLocalSchemaUrl(String schemaName) {
|
||||
public static URL resolveLocalSchemaUrl(String schemaName) {
|
||||
URL url = MappingReader.class.getClassLoader().getResource( schemaName );
|
||||
if ( url == null ) {
|
||||
throw new XmlInfrastructureException( "Unable to locate schema [" + schemaName + "] via classpath" );
|
||||
|
@ -272,7 +276,11 @@ public class MappingReader {
|
|||
return url;
|
||||
}
|
||||
|
||||
private static Schema resolveLocalSchema(URL schemaUrl) {
|
||||
public static Schema resolveLocalSchema(String schemaName){
|
||||
return resolveLocalSchema( resolveLocalSchemaUrl( schemaName ) );
|
||||
}
|
||||
|
||||
public static Schema resolveLocalSchema(URL schemaUrl) {
|
||||
|
||||
try {
|
||||
InputStream schemaStream = schemaUrl.openStream();
|
||||
|
@ -326,7 +334,7 @@ public class MappingReader {
|
|||
if ( errorHandler.hasErrors() ) {
|
||||
throw errorHandler.getErrors().get( 0 );
|
||||
}
|
||||
return new XmlDocumentImpl( document, origin.getType(), origin.getName() );
|
||||
return new XmlDocumentImpl( document, origin );
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
if ( LOG.isDebugEnabled() ) {
|
||||
|
@ -344,7 +352,7 @@ public class MappingReader {
|
|||
errorHandler.logErrors();
|
||||
throw errorHandler.getErrors().get( 0 );
|
||||
}
|
||||
return new XmlDocumentImpl( document, origin.getType(), origin.getName() );
|
||||
return new XmlDocumentImpl( document, origin );
|
||||
}
|
||||
catch ( Exception e2 ) {
|
||||
if ( LOG.isDebugEnabled() ) {
|
||||
|
@ -361,7 +369,7 @@ public class MappingReader {
|
|||
errorHandler.logErrors();
|
||||
throw errorHandler.getErrors().get( 0 );
|
||||
}
|
||||
return new XmlDocumentImpl( document, origin.getType(), origin.getName() );
|
||||
return new XmlDocumentImpl( document, origin );
|
||||
}
|
||||
catch ( Exception e3 ) {
|
||||
if ( LOG.isDebugEnabled() ) {
|
||||
|
@ -382,13 +390,13 @@ public class MappingReader {
|
|||
if ( "orm_2_1.xsd".equals( xsd ) ) {
|
||||
saxReader.setProperty(
|
||||
"http://apache.org/xml/properties/schema/external-schemaLocation",
|
||||
"http://xmlns.jcp.org/xml/ns/persistence/orm " + xsd
|
||||
LocalXmlResourceResolver.SECOND_JPA_ORM_NS + " " + xsd
|
||||
);
|
||||
}
|
||||
else {
|
||||
saxReader.setProperty(
|
||||
"http://apache.org/xml/properties/schema/external-schemaLocation",
|
||||
"http://java.sun.com/xml/ns/persistence/orm " + xsd
|
||||
LocalXmlResourceResolver.INITIAL_JPA_ORM_NS + " " + xsd
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,190 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2013, Red Hat Inc. 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 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.jaxb.internal;
|
||||
|
||||
import java.io.InputStream;
|
||||
import javax.xml.bind.JAXBContext;
|
||||
import javax.xml.bind.JAXBException;
|
||||
import javax.xml.bind.Unmarshaller;
|
||||
import javax.xml.bind.ValidationEvent;
|
||||
import javax.xml.bind.ValidationEventHandler;
|
||||
import javax.xml.bind.ValidationEventLocator;
|
||||
import javax.xml.stream.XMLEventReader;
|
||||
import javax.xml.stream.XMLInputFactory;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import javax.xml.stream.events.StartElement;
|
||||
import javax.xml.stream.events.XMLEvent;
|
||||
import javax.xml.validation.Schema;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.internal.util.xml.BufferedXMLEventReader;
|
||||
import org.hibernate.internal.util.xml.LocalXmlResourceResolver;
|
||||
import org.hibernate.jaxb.spi.JaxbRoot;
|
||||
import org.hibernate.jaxb.spi.Origin;
|
||||
import org.hibernate.metamodel.spi.source.MappingException;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
|
||||
/**
|
||||
* @author Strong Liu <stliu@hibernate.org>
|
||||
*/
|
||||
abstract class AbstractJaxbProcessor {
|
||||
protected static final Logger log = Logger.getLogger( AbstractJaxbProcessor.class );
|
||||
|
||||
// public static final String VALIDATE_XML_SETTING = "hibernate.xml.validate";
|
||||
|
||||
protected final ServiceRegistry serviceRegistry;
|
||||
protected final boolean validateXml;
|
||||
|
||||
public AbstractJaxbProcessor(ServiceRegistry serviceRegistry) {
|
||||
this( serviceRegistry, true );
|
||||
// this(
|
||||
// serviceRegistry,
|
||||
// serviceRegistry.getService( ConfigurationService.class ).getSetting(
|
||||
// VALIDATE_XML_SETTING,
|
||||
// StandardConverters.BOOLEAN,
|
||||
// true
|
||||
// )
|
||||
// );
|
||||
}
|
||||
|
||||
public AbstractJaxbProcessor(ServiceRegistry serviceRegistry, boolean validateXml) {
|
||||
this.serviceRegistry = serviceRegistry;
|
||||
this.validateXml = validateXml;
|
||||
}
|
||||
|
||||
public JaxbRoot unmarshal(InputStream stream, Origin origin) {
|
||||
try {
|
||||
BufferedXMLEventReader staxReader = new BufferedXMLEventReader(staxFactory().createXMLEventReader( stream ), 100);
|
||||
try {
|
||||
return unmarshal( staxReader, origin );
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
staxReader.close();
|
||||
}
|
||||
catch ( Exception ignore ) {
|
||||
}
|
||||
}
|
||||
}
|
||||
catch ( XMLStreamException e ) {
|
||||
throw new MappingException( "Unable to create stax reader", e, origin );
|
||||
}
|
||||
}
|
||||
|
||||
private XMLInputFactory staxFactory;
|
||||
|
||||
private XMLInputFactory staxFactory() {
|
||||
if ( staxFactory == null ) {
|
||||
staxFactory = buildStaxFactory();
|
||||
}
|
||||
return staxFactory;
|
||||
}
|
||||
|
||||
@SuppressWarnings( { "UnnecessaryLocalVariable" })
|
||||
private XMLInputFactory buildStaxFactory() {
|
||||
XMLInputFactory staxFactory = XMLInputFactory.newInstance();
|
||||
staxFactory.setXMLResolver( LocalXmlResourceResolver.INSTANCE );
|
||||
return staxFactory;
|
||||
}
|
||||
|
||||
@SuppressWarnings( { "unchecked" })
|
||||
private JaxbRoot unmarshal(XMLEventReader staxEventReader, final Origin origin) {
|
||||
XMLEvent event;
|
||||
try {
|
||||
event = staxEventReader.peek();
|
||||
while ( event != null && !event.isStartElement() ) {
|
||||
staxEventReader.nextEvent();
|
||||
event = staxEventReader.peek();
|
||||
}
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
throw new MappingException( "Error accessing stax stream", e, origin );
|
||||
}
|
||||
|
||||
if ( event == null ) {
|
||||
throw new MappingException( "Could not locate root element", origin );
|
||||
}
|
||||
|
||||
|
||||
|
||||
final ContextProvidingValidationEventHandler handler = new ContextProvidingValidationEventHandler();
|
||||
try {
|
||||
Schema schema = getSchema(event, origin);
|
||||
staxEventReader = wrapReader( staxEventReader, event );
|
||||
JAXBContext jaxbContext =getJaxbContext(event);
|
||||
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
|
||||
unmarshaller.setSchema( schema );
|
||||
unmarshaller.setEventHandler( handler );
|
||||
final Object target = unmarshaller.unmarshal( staxEventReader );
|
||||
return new JaxbRoot( target, origin );
|
||||
}
|
||||
catch ( JAXBException e ) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append( "Unable to perform unmarshalling at line number " );
|
||||
builder.append( handler.getLineNumber() );
|
||||
builder.append( " and column " );
|
||||
builder.append( handler.getColumnNumber() );
|
||||
builder.append( ". Message: " );
|
||||
builder.append( handler.getMessage() );
|
||||
throw new MappingException( builder.toString(), e, origin );
|
||||
}
|
||||
}
|
||||
protected abstract JAXBContext getJaxbContext(XMLEvent event) throws JAXBException;
|
||||
protected abstract Schema getSchema(XMLEvent event, Origin origin) throws JAXBException;
|
||||
protected XMLEventReader wrapReader(XMLEventReader xmlEventReader, XMLEvent event){
|
||||
return xmlEventReader;
|
||||
}
|
||||
protected static boolean isNamespaced(StartElement startElement) {
|
||||
return ! "".equals( startElement.getName().getNamespaceURI() );
|
||||
}
|
||||
|
||||
|
||||
static class ContextProvidingValidationEventHandler implements ValidationEventHandler {
|
||||
private int lineNumber;
|
||||
private int columnNumber;
|
||||
private String message;
|
||||
|
||||
@Override
|
||||
public boolean handleEvent(ValidationEvent validationEvent) {
|
||||
ValidationEventLocator locator = validationEvent.getLocator();
|
||||
lineNumber = locator.getLineNumber();
|
||||
columnNumber = locator.getColumnNumber();
|
||||
message = validationEvent.getMessage();
|
||||
return false;
|
||||
}
|
||||
|
||||
public int getLineNumber() {
|
||||
return lineNumber;
|
||||
}
|
||||
|
||||
public int getColumnNumber() {
|
||||
return columnNumber;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, Red Hat Inc. 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 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.jaxb.internal;
|
||||
|
||||
import javax.xml.bind.JAXBContext;
|
||||
import javax.xml.bind.JAXBException;
|
||||
import javax.xml.stream.XMLEventReader;
|
||||
import javax.xml.stream.events.XMLEvent;
|
||||
import javax.xml.validation.Schema;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.internal.util.xml.MappingReader;
|
||||
import org.hibernate.jaxb.spi.Origin;
|
||||
import org.hibernate.jaxb.spi.cfg.JaxbHibernateConfiguration;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class JaxbConfigurationProcessor extends AbstractJaxbProcessor {
|
||||
private static final Logger log = Logger.getLogger( JaxbConfigurationProcessor.class );
|
||||
|
||||
public static final String HIBERNATE_CONFIGURATION_URI = "http://www.hibernate.org/xsd/hibernate-configuration";
|
||||
|
||||
|
||||
public JaxbConfigurationProcessor(ServiceRegistry serviceRegistry) {
|
||||
this( serviceRegistry, true );
|
||||
}
|
||||
|
||||
public JaxbConfigurationProcessor(ServiceRegistry serviceRegistry, boolean validateXml) {
|
||||
super(serviceRegistry, validateXml);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected XMLEventReader wrapReader(XMLEventReader xmlEventReader, XMLEvent event) {
|
||||
if ( !isNamespaced( event.asStartElement() ) ) {
|
||||
// if the elements are not namespaced, wrap the reader in a reader which will namespace them as pulled.
|
||||
log.debug( "cfg.xml document did not define namespaces; wrapping in custom event reader to introduce namespace information" );
|
||||
return new NamespaceAddingEventReader( xmlEventReader, HIBERNATE_CONFIGURATION_URI );
|
||||
}
|
||||
return super.wrapReader( xmlEventReader, event );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JAXBContext getJaxbContext(XMLEvent event) throws JAXBException{
|
||||
return JAXBContext.newInstance( JaxbHibernateConfiguration.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Schema getSchema(XMLEvent event, Origin origin) throws JAXBException {
|
||||
if ( schema == null ) {
|
||||
schema = MappingReader.resolveLocalSchema( "org/hibernate/hibernate-configuration-4.0.xsd" );
|
||||
}
|
||||
return schema;
|
||||
}
|
||||
|
||||
private Schema schema;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,184 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, Red Hat Inc. 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 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.jaxb.internal;
|
||||
|
||||
import javax.xml.bind.JAXBContext;
|
||||
import javax.xml.bind.JAXBException;
|
||||
import javax.xml.bind.Unmarshaller;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.stream.XMLEventReader;
|
||||
import javax.xml.stream.events.Attribute;
|
||||
import javax.xml.stream.events.XMLEvent;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.validation.Schema;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.internal.util.xml.LocalXmlResourceResolver;
|
||||
import org.hibernate.internal.util.xml.MappingReader;
|
||||
import org.hibernate.internal.util.xml.OriginImpl;
|
||||
import org.hibernate.jaxb.spi.JaxbRoot;
|
||||
import org.hibernate.jaxb.spi.Origin;
|
||||
import org.hibernate.jaxb.spi.hbm.JaxbHibernateMapping;
|
||||
import org.hibernate.jaxb.spi.orm.JaxbEntityMappings;
|
||||
import org.hibernate.metamodel.spi.source.MappingException;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
|
||||
/**
|
||||
* Loads {@code hbm.xml} and {@code orm.xml} files and processes them using StAX and JAXB.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
* @author Hardy Ferentschik
|
||||
*/
|
||||
public class JaxbMappingProcessor extends AbstractJaxbProcessor{
|
||||
private static final Logger log = Logger.getLogger( JaxbMappingProcessor.class );
|
||||
public static final String HIBERNATE_MAPPING_URI = "http://www.hibernate.org/xsd/hibernate-mapping";
|
||||
|
||||
public JaxbMappingProcessor(ServiceRegistry serviceRegistry) {
|
||||
this( serviceRegistry, true );
|
||||
}
|
||||
|
||||
public JaxbMappingProcessor(ServiceRegistry serviceRegistry, boolean validateXml) {
|
||||
super(serviceRegistry, validateXml);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JAXBContext getJaxbContext(XMLEvent event) throws JAXBException {
|
||||
final String elementName = event.asStartElement().getName().getLocalPart();
|
||||
final Class jaxbTarget;
|
||||
if ( "entity-mappings".equals( elementName ) ) {
|
||||
jaxbTarget = JaxbEntityMappings.class;
|
||||
}
|
||||
else {
|
||||
jaxbTarget = JaxbHibernateMapping.class;
|
||||
}
|
||||
return JAXBContext.newInstance( jaxbTarget );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Schema getSchema(XMLEvent event, Origin origin) throws JAXBException {
|
||||
final String elementName = event.asStartElement().getName().getLocalPart();
|
||||
final Schema validationSchema;
|
||||
if ( "entity-mappings".equals( elementName ) ) {
|
||||
final Attribute attribute = event.asStartElement().getAttributeByName( ORM_VERSION_ATTRIBUTE_QNAME );
|
||||
final String explicitVersion = attribute == null ? null : attribute.getValue();
|
||||
validationSchema = validateXml ? resolveSupportedOrmXsd( explicitVersion, origin ) : null;
|
||||
}
|
||||
else {
|
||||
validationSchema = validateXml ? MappingReader.SupportedOrmXsdVersion.HBM_4_0.getSchema() : null;
|
||||
}
|
||||
return validationSchema;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected XMLEventReader wrapReader(XMLEventReader staxEventReader, XMLEvent event) {
|
||||
final String elementName = event.asStartElement().getName().getLocalPart();
|
||||
if ( "entity-mappings".equals( elementName ) ) {
|
||||
final Attribute attribute = event.asStartElement().getAttributeByName( ORM_VERSION_ATTRIBUTE_QNAME );
|
||||
final String explicitVersion = attribute == null ? null : attribute.getValue();
|
||||
if ( !"2.1".equals( explicitVersion ) ) {
|
||||
return new LegacyJPAEventReader(
|
||||
staxEventReader,
|
||||
LocalXmlResourceResolver.SECOND_JPA_ORM_NS
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ( !isNamespaced( event.asStartElement() ) ) {
|
||||
// if the elements are not namespaced, wrap the reader in a reader which will namespace them as pulled.
|
||||
log.debug( "HBM mapping document did not define namespaces; wrapping in custom event reader to introduce namespace information" );
|
||||
return new NamespaceAddingEventReader( staxEventReader, HIBERNATE_MAPPING_URI );
|
||||
}
|
||||
}
|
||||
return super.wrapReader( staxEventReader, event );
|
||||
}
|
||||
|
||||
private static final QName ORM_VERSION_ATTRIBUTE_QNAME = new QName( "version" );
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@SuppressWarnings( { "unchecked" })
|
||||
public JaxbRoot unmarshal(Document document, Origin origin) {
|
||||
Element rootElement = document.getDocumentElement();
|
||||
if ( rootElement == null ) {
|
||||
throw new MappingException( "No root element found", origin );
|
||||
}
|
||||
|
||||
final Schema validationSchema;
|
||||
final Class jaxbTarget;
|
||||
|
||||
if ( "entity-mappings".equals( rootElement.getNodeName() ) ) {
|
||||
final String explicitVersion = rootElement.getAttribute( "version" );
|
||||
validationSchema = validateXml ? resolveSupportedOrmXsd( explicitVersion, origin ) : null;
|
||||
jaxbTarget = JaxbEntityMappings.class;
|
||||
}
|
||||
else {
|
||||
validationSchema = validateXml ? MappingReader.SupportedOrmXsdVersion.HBM_4_0.getSchema() : null;
|
||||
jaxbTarget = JaxbHibernateMapping.class;
|
||||
}
|
||||
|
||||
final Object target;
|
||||
try {
|
||||
JAXBContext jaxbContext = JAXBContext.newInstance( jaxbTarget );
|
||||
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
|
||||
unmarshaller.setSchema( validationSchema );
|
||||
target = unmarshaller.unmarshal( new DOMSource( document ) );
|
||||
}
|
||||
catch ( JAXBException e ) {
|
||||
throw new MappingException( "Unable to perform unmarshalling", e, origin );
|
||||
}
|
||||
|
||||
return new JaxbRoot( target, origin );
|
||||
}
|
||||
|
||||
private Schema resolveSupportedOrmXsd(String explicitVersion, Origin origin) {
|
||||
|
||||
if ( StringHelper.isEmpty( explicitVersion ) ) {
|
||||
return MappingReader.SupportedOrmXsdVersion.ORM_2_1.getSchema();
|
||||
}
|
||||
|
||||
// Here we always use JPA 2.1 schema to do the validation, since the {@link LegacyJPAEventReader} already
|
||||
// transforms the legacy orm.xml to JPA 2.1 namespace and version.
|
||||
//
|
||||
// This may cause some problems, like a jpa 1.0 orm.xml having some element which is only available in the later
|
||||
// version. It is "invalid" but due to the fact we're using the latest schema to do the validation, then
|
||||
// it is "valid". Don't know if this will cause any problems, but let's do it for now.
|
||||
//
|
||||
// However, still check for the validity of the version by calling #parse. If someone explicitly uses a value
|
||||
// that doesn't exist, we still need to throw the exception.
|
||||
@SuppressWarnings("unused")
|
||||
MappingReader.SupportedOrmXsdVersion version =
|
||||
MappingReader.SupportedOrmXsdVersion.parse(
|
||||
explicitVersion,
|
||||
new OriginImpl( origin.getType().name(), origin.getName() )
|
||||
);
|
||||
// return version.getSchema();
|
||||
return MappingReader.SupportedOrmXsdVersion.ORM_2_1.getSchema();
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,140 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2013, Red Hat Inc. 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 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.jaxb.internal;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.stream.XMLEventFactory;
|
||||
import javax.xml.stream.XMLEventReader;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import javax.xml.stream.events.Attribute;
|
||||
import javax.xml.stream.events.Namespace;
|
||||
import javax.xml.stream.events.StartElement;
|
||||
import javax.xml.stream.events.XMLEvent;
|
||||
import javax.xml.stream.util.EventReaderDelegate;
|
||||
|
||||
import org.hibernate.internal.util.xml.LocalXmlResourceResolver;
|
||||
|
||||
/**
|
||||
*
|
||||
* We're lying to the xml validator here :D
|
||||
* <p/>
|
||||
*
|
||||
* Since JPA 2.1 changed its orm.xml namespace, so to support all versions
|
||||
* <ul>
|
||||
* <li>1.0</li>
|
||||
* <li>2.0</li>
|
||||
* <li>2.1</li>
|
||||
* </ul>
|
||||
*
|
||||
* the validator must recognize all of these two namespaces.
|
||||
*
|
||||
* but it is very hard to do that, so we're making an assumption (because I really don't konw if this is true or not)
|
||||
* here that JPA 2.1 is backward compatible w/ the old releases.
|
||||
*
|
||||
* So, there it comes, we just simply remove all legacy namespaces if it is an orm.xml and add the expected namespace
|
||||
* , here is it JPA 2.1, to every elements in the xml.
|
||||
*
|
||||
* Finally, for the xml validator, it always see the JPA 2.1 namespace only, and it would be happy to do the validation.
|
||||
*
|
||||
* <p/>
|
||||
* {@see HHH-8108} for more discussion.
|
||||
*
|
||||
* @author Strong Liu <stliu@hibernate.org>
|
||||
*/
|
||||
public class LegacyJPAEventReader extends EventReaderDelegate {
|
||||
private final XMLEventFactory xmlEventFactory;
|
||||
private final String namespaceUri;
|
||||
|
||||
public LegacyJPAEventReader(XMLEventReader reader, String namespaceUri) {
|
||||
this( reader, XMLEventFactory.newInstance(), namespaceUri );
|
||||
}
|
||||
|
||||
public LegacyJPAEventReader(XMLEventReader reader, XMLEventFactory xmlEventFactory, String namespaceUri) {
|
||||
super( reader );
|
||||
this.xmlEventFactory = xmlEventFactory;
|
||||
this.namespaceUri = namespaceUri;
|
||||
}
|
||||
|
||||
private StartElement withNamespace(StartElement startElement) {
|
||||
|
||||
Iterator<?> attributes;
|
||||
Iterator<?> namespacesItr;
|
||||
if ( "entity-mappings".equals( startElement.getName().getLocalPart() ) ) {
|
||||
List<Attribute> st = new ArrayList<Attribute>();
|
||||
Iterator itr = startElement.getAttributes();
|
||||
while ( itr.hasNext() ) {
|
||||
Attribute obj = (Attribute) itr.next();
|
||||
if ( "version".equals( obj.getName().getLocalPart() ) ) {
|
||||
if ( "".equals( obj.getName().getPrefix() ) ) {
|
||||
st.add( xmlEventFactory.createAttribute( obj.getName(), "2.1" ) );
|
||||
}
|
||||
}
|
||||
else {
|
||||
st.add( obj );
|
||||
}
|
||||
}
|
||||
attributes = st.iterator();
|
||||
// otherwise, wrap the start element event to provide a default namespace mapping
|
||||
final List<Namespace> namespaces = new ArrayList<Namespace>();
|
||||
namespaces.add( xmlEventFactory.createNamespace( "", namespaceUri ) );
|
||||
Iterator<?> originalNamespaces = startElement.getNamespaces();
|
||||
while ( originalNamespaces.hasNext() ) {
|
||||
Namespace ns = (Namespace) originalNamespaces.next();
|
||||
if ( !LocalXmlResourceResolver.INITIAL_JPA_ORM_NS.equals( ns.getNamespaceURI() ) ) {
|
||||
namespaces.add( ns );
|
||||
}
|
||||
}
|
||||
namespacesItr = namespaces.iterator();
|
||||
} else {
|
||||
attributes = startElement.getAttributes();
|
||||
namespacesItr = startElement.getNamespaces();
|
||||
}
|
||||
|
||||
return xmlEventFactory.createStartElement(
|
||||
new QName( namespaceUri, startElement.getName().getLocalPart() ),
|
||||
attributes,
|
||||
namespacesItr
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public XMLEvent nextEvent() throws XMLStreamException {
|
||||
return wrap( super.nextEvent() );
|
||||
}
|
||||
private XMLEvent wrap(XMLEvent event) {
|
||||
if ( event!=null && event.isStartElement() ) {
|
||||
return withNamespace( event.asStartElement() );
|
||||
}
|
||||
return event;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XMLEvent peek() throws XMLStreamException {
|
||||
return wrap( super.peek() );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, Red Hat Inc. 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 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.jaxb.internal;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.stream.XMLEventFactory;
|
||||
import javax.xml.stream.XMLEventReader;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import javax.xml.stream.events.Namespace;
|
||||
import javax.xml.stream.events.StartElement;
|
||||
import javax.xml.stream.events.XMLEvent;
|
||||
import javax.xml.stream.util.EventReaderDelegate;
|
||||
|
||||
import org.hibernate.internal.util.xml.LocalXmlResourceResolver;
|
||||
|
||||
/**
|
||||
* Used to wrap a StAX {@link XMLEventReader} in order to introduce namespaces into the underlying document. This
|
||||
* is intended for temporary migration feature to allow legacy HBM mapping documents (DTD-based) to continue to
|
||||
* parse correctly. This feature will go away eventually.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class NamespaceAddingEventReader extends EventReaderDelegate {
|
||||
private final XMLEventFactory xmlEventFactory;
|
||||
private final String namespaceUri;
|
||||
|
||||
public NamespaceAddingEventReader(XMLEventReader reader, String namespaceUri) {
|
||||
this( reader, XMLEventFactory.newInstance(), namespaceUri );
|
||||
}
|
||||
|
||||
public NamespaceAddingEventReader(XMLEventReader reader, XMLEventFactory xmlEventFactory, String namespaceUri) {
|
||||
super( reader );
|
||||
this.xmlEventFactory = xmlEventFactory;
|
||||
this.namespaceUri = namespaceUri;
|
||||
}
|
||||
|
||||
private StartElement withNamespace(StartElement startElement) {
|
||||
// otherwise, wrap the start element event to provide a default namespace mapping
|
||||
final List<Namespace> namespaces = new ArrayList<Namespace>();
|
||||
namespaces.add( xmlEventFactory.createNamespace( "", namespaceUri ) );
|
||||
Iterator<?> originalNamespaces = startElement.getNamespaces();
|
||||
while ( originalNamespaces.hasNext() ) {
|
||||
Namespace ns = (Namespace) originalNamespaces.next();
|
||||
namespaces.add( ns );
|
||||
}
|
||||
return xmlEventFactory.createStartElement(
|
||||
new QName( namespaceUri, startElement.getName().getLocalPart() ),
|
||||
startElement.getAttributes(),
|
||||
namespaces.iterator()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public XMLEvent nextEvent() throws XMLStreamException {
|
||||
return wrap( super.nextEvent() );
|
||||
}
|
||||
|
||||
private XMLEvent wrap(XMLEvent event) {
|
||||
if ( event.isStartElement() ) {
|
||||
return withNamespace( event.asStartElement() );
|
||||
}
|
||||
return event;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XMLEvent peek() throws XMLStreamException {
|
||||
return wrap( super.peek() );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package org.hibernate.jaxb;
|
||||
|
||||
/**
|
||||
* Defines Hibernate's JAXB usage.
|
||||
*/
|
|
@ -21,7 +21,9 @@
|
|||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.internal.jaxb;
|
||||
package org.hibernate.jaxb.spi;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Holds information about a JAXB-unmarshalled XML document.
|
||||
|
@ -29,7 +31,7 @@ package org.hibernate.internal.jaxb;
|
|||
* @author Hardy Ferentschik
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class JaxbRoot<T> {
|
||||
public class JaxbRoot<T> implements Serializable {
|
||||
private final T root;
|
||||
private final Origin origin;
|
||||
|
|
@ -21,7 +21,7 @@
|
|||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.internal.jaxb;
|
||||
package org.hibernate.jaxb.spi;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
|
@ -57,4 +57,40 @@ public class Origin implements Serializable {
|
|||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( !( o instanceof Origin ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Origin origin = (Origin) o;
|
||||
|
||||
if ( name != null ? !name.equals( origin.name ) : origin.name != null ) {
|
||||
return false;
|
||||
}
|
||||
if ( type != origin.type ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = type != null ? type.hashCode() : 0;
|
||||
result = 31 * result + ( name != null ? name.hashCode() : 0 );
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Origin{" +
|
||||
"name='" + name + '\'' +
|
||||
", type=" + type +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -22,7 +22,7 @@
|
|||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package org.hibernate.internal.jaxb;
|
||||
package org.hibernate.jaxb.spi;
|
||||
|
||||
/**
|
||||
* From what type of source did we obtain the data
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||
* Copyright (c) 2012, Red Hat Inc. 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 Inc.
|
||||
|
@ -21,13 +21,13 @@
|
|||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.internal.jaxb.mapping.hbm;
|
||||
package org.hibernate.jaxb.spi.hbm;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface CustomSqlElement {
|
||||
public String getValue();
|
||||
public boolean isCallable();
|
||||
public JaxbCheckAttribute getCheck();
|
||||
public interface ComponentSourceElement extends MetaAttributeContainer {
|
||||
public String getAccess();
|
||||
public String getClazz();
|
||||
public String getName();
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue