Merge remote-tracking branch 'upstream5/master' into wip/6.0_merged_6
This commit is contained in:
commit
567eb38069
|
@ -47,7 +47,7 @@ public class LoadedConfig {
|
|||
private List<MappingReference> mappingReferences;
|
||||
private Map<EventType,Set<String>> eventListenerMap;
|
||||
|
||||
private LoadedConfig(String sessionFactoryName) {
|
||||
public LoadedConfig(String sessionFactoryName) {
|
||||
this.sessionFactoryName = sessionFactoryName;
|
||||
}
|
||||
|
||||
|
@ -259,7 +259,7 @@ public class LoadedConfig {
|
|||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void addConfigurationValues(Map configurationValues) {
|
||||
protected void addConfigurationValues(Map configurationValues) {
|
||||
if ( configurationValues == null ) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ import org.hibernate.boot.MappingException;
|
|||
import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmFilterAliasMappingType;
|
||||
import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmFilterType;
|
||||
import org.hibernate.boot.model.source.spi.FilterSource;
|
||||
import org.hibernate.internal.util.NullnessHelper;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
|
||||
/**
|
||||
|
@ -63,7 +64,7 @@ public class FilterSourceImpl
|
|||
}
|
||||
}
|
||||
|
||||
this.condition = Helper.coalesce( conditionContent, conditionAttribute );
|
||||
this.condition = NullnessHelper.coalesce( conditionContent, conditionAttribute );
|
||||
this.autoAliasInjection = StringHelper.isNotEmpty( explicitAutoAliasInjectionSetting )
|
||||
? Boolean.valueOf( explicitAutoAliasInjectionSetting )
|
||||
: true;
|
||||
|
|
|
@ -123,33 +123,6 @@ public class Helper {
|
|||
return params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Operates like SQL coalesce expression, except empty strings are treated as null. Return the first non-empty value
|
||||
*
|
||||
* @param values The list of values.
|
||||
* @param <T> Generic type of values to coalesce
|
||||
*
|
||||
* @return The first non-empty value, or null if all values were empty
|
||||
*/
|
||||
public static <T> T coalesce(T... values) {
|
||||
if ( values == null ) {
|
||||
return null;
|
||||
}
|
||||
for ( T value : values ) {
|
||||
if ( value != null ) {
|
||||
if ( String.class.isInstance( value ) ) {
|
||||
if ( StringHelper.isNotEmpty( (String) value ) ) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static ToolingHintContext collectToolingHints(
|
||||
ToolingHintContext baseline,
|
||||
ToolingHintContainer toolingHintContainer) {
|
||||
|
|
|
@ -36,6 +36,35 @@ import org.hibernate.service.spi.ServiceContributor;
|
|||
* @see org.hibernate.boot.registry.BootstrapServiceRegistryBuilder
|
||||
*/
|
||||
public class StandardServiceRegistryBuilder {
|
||||
/**
|
||||
* Intended only for use from {@link org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl}.
|
||||
*
|
||||
* Creates a StandardServiceRegistryBuilder specific to the needs of JPA bootstrapping.
|
||||
* Specifically we ignore properties found in `cfg.xml` files in terms of adding them to
|
||||
* the builder immediately. EntityManagerFactoryBuilderImpl handles collecting these
|
||||
* properties itself.
|
||||
*/
|
||||
public static StandardServiceRegistryBuilder forJpa(BootstrapServiceRegistry bootstrapServiceRegistry) {
|
||||
final LoadedConfig loadedConfig = new LoadedConfig( null ) {
|
||||
@Override
|
||||
protected void addConfigurationValues(Map configurationValues) {
|
||||
// here, do nothing
|
||||
}
|
||||
};
|
||||
return new StandardServiceRegistryBuilder(
|
||||
bootstrapServiceRegistry,
|
||||
new HashMap(),
|
||||
loadedConfig
|
||||
) {
|
||||
@Override
|
||||
public StandardServiceRegistryBuilder configure(LoadedConfig loadedConfig) {
|
||||
getAggregatedCfgXml().merge( loadedConfig );
|
||||
// super also collects the properties - here we skip that part
|
||||
return this;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* The default resource name for a hibernate configuration xml file.
|
||||
*/
|
||||
|
@ -43,7 +72,7 @@ public class StandardServiceRegistryBuilder {
|
|||
|
||||
private final Map settings;
|
||||
private final List<StandardServiceInitiator> initiators = standardInitiatorList();
|
||||
private final List<ProvidedService> providedServices = new ArrayList<ProvidedService>();
|
||||
private final List<ProvidedService> providedServices = new ArrayList<>();
|
||||
|
||||
private boolean autoCloseRegistry = true;
|
||||
|
||||
|
@ -67,6 +96,21 @@ public class StandardServiceRegistryBuilder {
|
|||
this( bootstrapServiceRegistry, LoadedConfig.baseline() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Intended for use exclusively from JPA boot-strapping.
|
||||
*
|
||||
* @see #forJpa
|
||||
*/
|
||||
private StandardServiceRegistryBuilder(
|
||||
BootstrapServiceRegistry bootstrapServiceRegistry,
|
||||
Map settings,
|
||||
LoadedConfig loadedConfig) {
|
||||
this.bootstrapServiceRegistry = bootstrapServiceRegistry;
|
||||
this.configLoader = new ConfigLoader( bootstrapServiceRegistry );
|
||||
this.settings = settings;
|
||||
this.aggregatedCfgXml = loadedConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a builder with the specified bootstrap services.
|
||||
*
|
||||
|
@ -81,6 +125,10 @@ public class StandardServiceRegistryBuilder {
|
|||
this.aggregatedCfgXml = loadedConfigBaseline;
|
||||
}
|
||||
|
||||
public ConfigLoader getConfigLoader() {
|
||||
return configLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Intended for internal testing use only!!
|
||||
*/
|
||||
|
@ -94,11 +142,12 @@ public class StandardServiceRegistryBuilder {
|
|||
* @return List of standard initiators
|
||||
*/
|
||||
private static List<StandardServiceInitiator> standardInitiatorList() {
|
||||
final List<StandardServiceInitiator> initiators = new ArrayList<StandardServiceInitiator>( StandardServiceInitiators.LIST.size() );
|
||||
final List<StandardServiceInitiator> initiators = new ArrayList<>( StandardServiceInitiators.LIST.size() );
|
||||
initiators.addAll( StandardServiceInitiators.LIST );
|
||||
return initiators;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public BootstrapServiceRegistry getBootstrapServiceRegistry() {
|
||||
return bootstrapServiceRegistry;
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
*/
|
||||
package org.hibernate.bytecode.enhance.spi.interceptor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
@ -40,6 +39,8 @@ public class EnhancementAsProxyLazinessInterceptor extends AbstractLazyLoadInter
|
|||
|
||||
private boolean initialized;
|
||||
|
||||
private boolean initializeBeforeWrite;
|
||||
|
||||
public EnhancementAsProxyLazinessInterceptor(
|
||||
String entityName,
|
||||
Set<String> identifierAttributeNames,
|
||||
|
@ -59,6 +60,9 @@ public class EnhancementAsProxyLazinessInterceptor extends AbstractLazyLoadInter
|
|||
final EntityPersister entityPersister = session.getFactory().getMetamodel().entityPersister( entityName );
|
||||
this.inLineDirtyChecking = entityPersister.getEntityMode() == EntityMode.POJO
|
||||
&& SelfDirtinessTracker.class.isAssignableFrom( entityPersister.getMappedClass() );
|
||||
// if self-dirty tracking is enabled but DynamicUpdate is not enabled then we need to initialise the entity
|
||||
// because the pre-computed update statement contains even not dirty properties and so we need all the values
|
||||
initializeBeforeWrite = !inLineDirtyChecking || !entityPersister.getEntityMetamodel().isDynamicUpdate();
|
||||
}
|
||||
|
||||
public EntityKey getEntityKey() {
|
||||
|
@ -89,7 +93,7 @@ public class EnhancementAsProxyLazinessInterceptor extends AbstractLazyLoadInter
|
|||
.entityPersister( getEntityName() );
|
||||
final EntityTuplizer entityTuplizer = entityPersister.getEntityTuplizer();
|
||||
|
||||
if ( inLineDirtyChecking && writtenFieldNames != null && !writtenFieldNames.isEmpty() ) {
|
||||
if ( writtenFieldNames != null && !writtenFieldNames.isEmpty() ) {
|
||||
|
||||
// enhancement has dirty-tracking available and at least one attribute was explicitly set
|
||||
|
||||
|
@ -241,7 +245,7 @@ public class EnhancementAsProxyLazinessInterceptor extends AbstractLazyLoadInter
|
|||
return newValue;
|
||||
}
|
||||
|
||||
if ( ! inLineDirtyChecking ) {
|
||||
if ( initializeBeforeWrite ) {
|
||||
// we need to force-initialize the proxy - the fetch group to which the `attributeName` belongs
|
||||
try {
|
||||
forceInitialize( target, attributeName );
|
||||
|
@ -249,6 +253,10 @@ public class EnhancementAsProxyLazinessInterceptor extends AbstractLazyLoadInter
|
|||
finally {
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
if ( inLineDirtyChecking ) {
|
||||
( (SelfDirtinessTracker) target ).$$_hibernate_trackChange( attributeName );
|
||||
}
|
||||
}
|
||||
else {
|
||||
// because of the entity being enhanced with `org.hibernate.engine.spi.SelfDirtinessTracker`
|
||||
|
|
|
@ -241,8 +241,9 @@ public class DefaultLoadEventListener implements LoadEventListener {
|
|||
|
||||
final EventSource session = event.getSession();
|
||||
final SessionFactoryImplementor factory = session.getFactory();
|
||||
final boolean traceEnabled = LOG.isTraceEnabled();
|
||||
|
||||
if ( LOG.isTraceEnabled() ) {
|
||||
if ( traceEnabled ) {
|
||||
LOG.tracev(
|
||||
"Loading entity: {0}",
|
||||
MessageHelper.infoString( persister, event.getEntityId(), factory )
|
||||
|
@ -281,17 +282,12 @@ public class DefaultLoadEventListener implements LoadEventListener {
|
|||
final Object proxy = persistenceContext.getProxy( keyToLoad );
|
||||
|
||||
if ( proxy != null ) {
|
||||
LOG.trace( "Entity proxy found in session cache" );
|
||||
if( traceEnabled ) {
|
||||
LOG.trace( "Entity proxy found in session cache" );
|
||||
}
|
||||
|
||||
LazyInitializer li = ( (HibernateProxy) proxy ).getHibernateLazyInitializer();
|
||||
|
||||
if ( li.isUnwrap() ) {
|
||||
if ( entityMetamodel.hasSubclasses() ) {
|
||||
LOG.debug( "Ignoring NO_PROXY for to-one association with subclasses to honor laziness" );
|
||||
}
|
||||
else {
|
||||
return li.getImplementation();
|
||||
}
|
||||
if ( LOG.isDebugEnabled() && ( (HibernateProxy) proxy ).getHibernateLazyInitializer().isUnwrap() ) {
|
||||
LOG.debug( "Ignoring NO_PROXY to honor laziness" );
|
||||
}
|
||||
|
||||
return persistenceContext.narrowProxy( proxy, persister, keyToLoad, null );
|
||||
|
|
|
@ -65,7 +65,7 @@ public class NullnessHelper {
|
|||
* @return The first non-empty value, or null if all values were empty
|
||||
*/
|
||||
@SafeVarargs
|
||||
public static <T> T coalesce(Supplier<T>... valueSuppliers) {
|
||||
public static <T> T coalesceSuppliedValues(Supplier<T>... valueSuppliers) {
|
||||
if ( valueSuppliers == null ) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -27,11 +27,9 @@ import javax.sql.DataSource;
|
|||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.SessionFactoryObserver;
|
||||
import org.hibernate.boot.CacheRegionDefinition;
|
||||
import org.hibernate.boot.MetadataBuilder;
|
||||
import org.hibernate.boot.MetadataSources;
|
||||
import org.hibernate.boot.SessionFactoryBuilder;
|
||||
import org.hibernate.boot.archive.scan.internal.StandardScanOptions;
|
||||
import org.hibernate.boot.cfgxml.internal.ConfigLoader;
|
||||
import org.hibernate.boot.cfgxml.spi.CfgXmlAccessService;
|
||||
import org.hibernate.boot.cfgxml.spi.LoadedConfig;
|
||||
import org.hibernate.boot.cfgxml.spi.MappingReference;
|
||||
|
@ -61,7 +59,9 @@ import org.hibernate.engine.spi.SessionFactoryImplementor;
|
|||
import org.hibernate.id.factory.spi.MutableIdentifierGeneratorFactory;
|
||||
import org.hibernate.integrator.spi.Integrator;
|
||||
import org.hibernate.internal.EntityManagerMessageLogger;
|
||||
import org.hibernate.internal.util.NullnessHelper;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.internal.util.config.ConfigurationHelper;
|
||||
import org.hibernate.jpa.AvailableSettings;
|
||||
import org.hibernate.jpa.boot.spi.EntityManagerFactoryBuilder;
|
||||
import org.hibernate.jpa.boot.spi.IntegratorProvider;
|
||||
|
@ -74,6 +74,7 @@ import org.hibernate.jpa.spi.IdentifierGeneratorStrategyProvider;
|
|||
import org.hibernate.proxy.EntityNotFoundDelegate;
|
||||
import org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorBuilderImpl;
|
||||
import org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionCoordinatorBuilderImpl;
|
||||
import org.hibernate.resource.transaction.spi.TransactionCoordinatorBuilder;
|
||||
import org.hibernate.secure.spi.GrantedPermission;
|
||||
import org.hibernate.secure.spi.JaccPermissionDeclarations;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
|
@ -200,24 +201,31 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
|
|||
final BootstrapServiceRegistry bsr = buildBootstrapServiceRegistry( integrationSettings, providedClassLoader, providedClassLoaderService);
|
||||
|
||||
// merge configuration sources and build the "standard" service registry
|
||||
final StandardServiceRegistryBuilder ssrBuilder = new StandardServiceRegistryBuilder( bsr );
|
||||
final StandardServiceRegistryBuilder ssrBuilder = StandardServiceRegistryBuilder.forJpa( bsr );
|
||||
|
||||
final MergedSettings mergedSettings = mergeSettings( persistenceUnit, integrationSettings, ssrBuilder );
|
||||
|
||||
// flush before completion validation
|
||||
if ( "true".equals( mergedSettings.configurationValues.get( Environment.FLUSH_BEFORE_COMPLETION ) ) ) {
|
||||
LOG.definingFlushBeforeCompletionIgnoredInHem( Environment.FLUSH_BEFORE_COMPLETION );
|
||||
mergedSettings.configurationValues.put( Environment.FLUSH_BEFORE_COMPLETION, "false" );
|
||||
}
|
||||
|
||||
// keep the merged config values for phase-2
|
||||
this.configurationValues = mergedSettings.getConfigurationValues();
|
||||
|
||||
// Build the "standard" service registry
|
||||
ssrBuilder.applySettings( configurationValues );
|
||||
configure( ssrBuilder );
|
||||
|
||||
this.standardServiceRegistry = ssrBuilder.build();
|
||||
configure( standardServiceRegistry, mergedSettings );
|
||||
|
||||
configureIdentifierGenerators( standardServiceRegistry );
|
||||
|
||||
final MetadataSources metadataSources = new MetadataSources( bsr );
|
||||
List<ConverterDescriptor> attributeConverterDefinitions = populate(
|
||||
metadataSources,
|
||||
mergedSettings,
|
||||
standardServiceRegistry
|
||||
);
|
||||
List<ConverterDescriptor> attributeConverterDefinitions = applyMappingResources( metadataSources );
|
||||
|
||||
this.metamodelBuilder = (MetadataBuilderImplementor) metadataSources.getMetadataBuilder( standardServiceRegistry );
|
||||
populate( metamodelBuilder, mergedSettings, standardServiceRegistry, attributeConverterDefinitions );
|
||||
applyMetamodelBuilderSettings( mergedSettings, attributeConverterDefinitions );
|
||||
|
||||
applyMetadataBuilderContributor();
|
||||
|
||||
|
@ -308,7 +316,6 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
|
|||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// temporary!
|
||||
@SuppressWarnings("unchecked")
|
||||
public Map getConfigurationValues() {
|
||||
return Collections.unmodifiableMap( configurationValues );
|
||||
}
|
||||
|
@ -327,7 +334,10 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
|
|||
* @param associationManagementEnabled To enable association management feature
|
||||
* @return An enhancement context for classes managed by this EM
|
||||
*/
|
||||
protected EnhancementContext getEnhancementContext(final boolean dirtyTrackingEnabled, final boolean lazyInitializationEnabled, final boolean associationManagementEnabled ) {
|
||||
protected EnhancementContext getEnhancementContext(
|
||||
final boolean dirtyTrackingEnabled,
|
||||
final boolean lazyInitializationEnabled,
|
||||
final boolean associationManagementEnabled ) {
|
||||
return new DefaultEnhancementContext() {
|
||||
|
||||
@Override
|
||||
|
@ -455,21 +465,12 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
|
|||
return bsrBuilder.build();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private MergedSettings mergeSettings(
|
||||
PersistenceUnitDescriptor persistenceUnit,
|
||||
Map<?,?> integrationSettings,
|
||||
StandardServiceRegistryBuilder ssrBuilder) {
|
||||
final MergedSettings mergedSettings = new MergedSettings();
|
||||
|
||||
// first, apply persistence.xml-defined settings
|
||||
if ( persistenceUnit.getProperties() != null ) {
|
||||
mergedSettings.configurationValues.putAll( persistenceUnit.getProperties() );
|
||||
}
|
||||
|
||||
mergedSettings.configurationValues.put( PERSISTENCE_UNIT_NAME, persistenceUnit.getName() );
|
||||
|
||||
final ConfigLoader configLoader = new ConfigLoader( ssrBuilder.getBootstrapServiceRegistry() );
|
||||
mergedSettings.processPersistenceUnitDescriptorProperties( persistenceUnit );
|
||||
|
||||
// see if the persistence.xml settings named a Hibernate config file....
|
||||
String cfgXmlResourceName = (String) mergedSettings.configurationValues.remove( CFG_FILE );
|
||||
|
@ -479,35 +480,10 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
|
|||
}
|
||||
|
||||
if ( StringHelper.isNotEmpty( cfgXmlResourceName ) ) {
|
||||
final LoadedConfig loadedCfg = configLoader.loadConfigXmlResource( cfgXmlResourceName );
|
||||
processConfigXml( loadedCfg, mergedSettings, ssrBuilder );
|
||||
processHibernateConfigXmlResources( ssrBuilder, mergedSettings, cfgXmlResourceName );
|
||||
}
|
||||
|
||||
// finally, apply integration-supplied settings (per JPA spec, integration settings should override other sources)
|
||||
for ( Map.Entry<?,?> entry : integrationSettings.entrySet() ) {
|
||||
if ( entry.getKey() == null ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( entry.getValue() == null ) {
|
||||
mergedSettings.configurationValues.remove( entry.getKey() );
|
||||
}
|
||||
else {
|
||||
mergedSettings.configurationValues.put( entry.getKey(), entry.getValue() );
|
||||
}
|
||||
}
|
||||
|
||||
if ( !mergedSettings.configurationValues.containsKey( JPA_VALIDATION_MODE ) ) {
|
||||
if ( persistenceUnit.getValidationMode() != null ) {
|
||||
mergedSettings.configurationValues.put( JPA_VALIDATION_MODE, persistenceUnit.getValidationMode() );
|
||||
}
|
||||
}
|
||||
|
||||
if ( !mergedSettings.configurationValues.containsKey( JPA_SHARED_CACHE_MODE ) ) {
|
||||
if ( persistenceUnit.getSharedCacheMode() != null ) {
|
||||
mergedSettings.configurationValues.put( JPA_SHARED_CACHE_MODE, persistenceUnit.getSharedCacheMode() );
|
||||
}
|
||||
}
|
||||
normalizeSettings( persistenceUnit, integrationSettings, mergedSettings );
|
||||
|
||||
final String jaccContextId = (String) mergedSettings.configurationValues.get( JACC_CONTEXT_ID );
|
||||
|
||||
|
@ -568,22 +544,446 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
|
|||
return mergedSettings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles normalizing the settings coming from multiple sources, applying proper precedences
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private void processConfigXml(
|
||||
LoadedConfig loadedConfig,
|
||||
MergedSettings mergedSettings,
|
||||
StandardServiceRegistryBuilder ssrBuilder) {
|
||||
if ( ! mergedSettings.configurationValues.containsKey( SESSION_FACTORY_NAME ) ) {
|
||||
// there is not already a SF-name in the merged settings
|
||||
final String sfName = loadedConfig.getSessionFactoryName();
|
||||
if ( sfName != null ) {
|
||||
// but the cfg.xml file we are processing named one..
|
||||
mergedSettings.configurationValues.put( SESSION_FACTORY_NAME, sfName );
|
||||
private void normalizeSettings(
|
||||
PersistenceUnitDescriptor persistenceUnit,
|
||||
Map<?, ?> integrationSettings,
|
||||
MergedSettings mergedSettings) {
|
||||
// make a copy so we can remove things as we process them
|
||||
final HashMap<?, ?> integrationSettingsCopy = new HashMap<>( integrationSettings );
|
||||
|
||||
normalizeConnectionAccessUserAndPass( integrationSettingsCopy, mergedSettings );
|
||||
|
||||
normalizeTransactionCoordinator( persistenceUnit, integrationSettingsCopy, mergedSettings );
|
||||
|
||||
normalizeDataAccess( integrationSettingsCopy, mergedSettings, persistenceUnit );
|
||||
|
||||
// normalize ValidationMode
|
||||
final Object intgValidationMode = integrationSettingsCopy.remove( JPA_VALIDATION_MODE );
|
||||
if ( intgValidationMode != null ) {
|
||||
mergedSettings.configurationValues.put( JPA_VALIDATION_MODE, intgValidationMode );
|
||||
}
|
||||
else if ( persistenceUnit.getValidationMode() != null ) {
|
||||
mergedSettings.configurationValues.put( JPA_VALIDATION_MODE, persistenceUnit.getValidationMode() );
|
||||
}
|
||||
|
||||
// normalize SharedCacheMode
|
||||
final Object intgCacheMode = integrationSettingsCopy.remove( JPA_SHARED_CACHE_MODE );
|
||||
if ( intgCacheMode != null ) {
|
||||
mergedSettings.configurationValues.put( JPA_SHARED_CACHE_MODE, intgCacheMode );
|
||||
}
|
||||
else if ( persistenceUnit.getSharedCacheMode() != null ) {
|
||||
mergedSettings.configurationValues.put( JPA_SHARED_CACHE_MODE, persistenceUnit.getSharedCacheMode() );
|
||||
}
|
||||
|
||||
// Apply all "integration overrides" as the last step. By specification,
|
||||
// these should have precedence.
|
||||
//
|
||||
// NOTE that this occurs after the specialized normalize calls above which remove
|
||||
// any specially-handled settings.
|
||||
for ( Map.Entry<?,?> entry : integrationSettingsCopy.entrySet() ) {
|
||||
if ( entry.getKey() == null ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( entry.getValue() == null ) {
|
||||
mergedSettings.configurationValues.remove( entry.getKey() );
|
||||
}
|
||||
else {
|
||||
mergedSettings.configurationValues.put( entry.getKey(), entry.getValue() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Because a DataSource can be secured (requiring Hibernate to pass the USER/PASSWORD when accessing the DataSource)
|
||||
* we apply precedence to the USER and PASS separately
|
||||
*/
|
||||
private void normalizeConnectionAccessUserAndPass(
|
||||
HashMap<?, ?> integrationSettingsCopy,
|
||||
MergedSettings mergedSettings) {
|
||||
//noinspection unchecked
|
||||
final Object effectiveUser = NullnessHelper.coalesceSuppliedValues(
|
||||
() -> integrationSettingsCopy.remove( USER ),
|
||||
() -> integrationSettingsCopy.remove( JPA_JDBC_USER ),
|
||||
() -> extractPuProperty( persistenceUnit, USER ),
|
||||
() -> extractPuProperty( persistenceUnit, JPA_JDBC_USER )
|
||||
);
|
||||
|
||||
//noinspection unchecked
|
||||
final Object effectivePass = NullnessHelper.coalesceSuppliedValues(
|
||||
() -> integrationSettingsCopy.remove( PASS ),
|
||||
() -> integrationSettingsCopy.remove( JPA_JDBC_PASSWORD ),
|
||||
() -> extractPuProperty( persistenceUnit, PASS ),
|
||||
() -> extractPuProperty( persistenceUnit, JPA_JDBC_PASSWORD )
|
||||
);
|
||||
|
||||
if ( effectiveUser != null || effectivePass != null ) {
|
||||
applyUserAndPass( effectiveUser, effectivePass, mergedSettings );
|
||||
}
|
||||
}
|
||||
|
||||
private <T> T extractPuProperty(PersistenceUnitDescriptor persistenceUnit, String propertyName) {
|
||||
//noinspection unchecked
|
||||
return persistenceUnit.getProperties() == null ? null : (T) persistenceUnit.getProperties().get( propertyName );
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void applyUserAndPass(Object effectiveUser, Object effectivePass, MergedSettings mergedSettings) {
|
||||
if ( effectiveUser != null ) {
|
||||
mergedSettings.configurationValues.put( USER, effectiveUser );
|
||||
mergedSettings.configurationValues.put( JPA_JDBC_USER, effectiveUser );
|
||||
}
|
||||
|
||||
if ( effectivePass != null ) {
|
||||
mergedSettings.configurationValues.put( PASS, effectivePass );
|
||||
mergedSettings.configurationValues.put( JPA_JDBC_PASSWORD, effectivePass );
|
||||
}
|
||||
}
|
||||
|
||||
private static final String IS_JTA_TXN_COORD = "local.setting.IS_JTA_TXN_COORD";
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void normalizeTransactionCoordinator(
|
||||
PersistenceUnitDescriptor persistenceUnit,
|
||||
HashMap<?, ?> integrationSettingsCopy,
|
||||
MergedSettings mergedSettings) {
|
||||
PersistenceUnitTransactionType txnType = null;
|
||||
|
||||
final Object intgTxnType = integrationSettingsCopy.remove( JPA_TRANSACTION_TYPE );
|
||||
|
||||
if ( intgTxnType != null ) {
|
||||
txnType = PersistenceUnitTransactionTypeHelper.interpretTransactionType( intgTxnType );
|
||||
}
|
||||
else if ( persistenceUnit.getTransactionType() != null ) {
|
||||
txnType = persistenceUnit.getTransactionType();
|
||||
}
|
||||
else {
|
||||
final Object puPropTxnType = mergedSettings.configurationValues.get( JPA_TRANSACTION_TYPE );
|
||||
if ( puPropTxnType != null ) {
|
||||
txnType = PersistenceUnitTransactionTypeHelper.interpretTransactionType( puPropTxnType );
|
||||
}
|
||||
}
|
||||
|
||||
mergedSettings.configurationValues.putAll( loadedConfig.getConfigurationValues() );
|
||||
ssrBuilder.configure( loadedConfig );
|
||||
if ( txnType == null ) {
|
||||
// is it more appropriate to have this be based on bootstrap entry point (EE vs SE)?
|
||||
LOG.debugf( "PersistenceUnitTransactionType not specified - falling back to RESOURCE_LOCAL" );
|
||||
txnType = PersistenceUnitTransactionType.RESOURCE_LOCAL;
|
||||
}
|
||||
|
||||
boolean hasTxStrategy = mergedSettings.configurationValues.containsKey( TRANSACTION_COORDINATOR_STRATEGY );
|
||||
final Boolean definiteJtaCoordinator;
|
||||
|
||||
if ( hasTxStrategy ) {
|
||||
LOG.overridingTransactionStrategyDangerous( TRANSACTION_COORDINATOR_STRATEGY );
|
||||
|
||||
// see if we can tell whether it is a JTA coordinator
|
||||
final Object strategy = mergedSettings.configurationValues.get( TRANSACTION_COORDINATOR_STRATEGY );
|
||||
if ( strategy instanceof TransactionCoordinatorBuilder ) {
|
||||
definiteJtaCoordinator = ( (TransactionCoordinatorBuilder) strategy ).isJta();
|
||||
}
|
||||
else {
|
||||
definiteJtaCoordinator = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ( txnType == PersistenceUnitTransactionType.JTA ) {
|
||||
mergedSettings.configurationValues.put( TRANSACTION_COORDINATOR_STRATEGY, JtaTransactionCoordinatorBuilderImpl.class );
|
||||
definiteJtaCoordinator = true;
|
||||
}
|
||||
else if ( txnType == PersistenceUnitTransactionType.RESOURCE_LOCAL ) {
|
||||
mergedSettings.configurationValues.put( TRANSACTION_COORDINATOR_STRATEGY, JdbcResourceLocalTransactionCoordinatorBuilderImpl.class );
|
||||
definiteJtaCoordinator = false;
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException( "Could not determine TransactionCoordinator strategy to use" );
|
||||
}
|
||||
}
|
||||
|
||||
mergedSettings.configurationValues.put( IS_JTA_TXN_COORD, definiteJtaCoordinator );
|
||||
}
|
||||
|
||||
private void normalizeDataAccess(
|
||||
HashMap<?, ?> integrationSettingsCopy,
|
||||
MergedSettings mergedSettings,
|
||||
PersistenceUnitDescriptor persistenceUnit) {
|
||||
if ( dataSource != null ) {
|
||||
applyDataSource(
|
||||
dataSource,
|
||||
// we don't explicitly know
|
||||
null,
|
||||
integrationSettingsCopy,
|
||||
mergedSettings
|
||||
);
|
||||
|
||||
// EARLY EXIT!!
|
||||
return;
|
||||
}
|
||||
|
||||
if ( integrationSettingsCopy.containsKey( DATASOURCE ) ) {
|
||||
final Object dataSourceRef = integrationSettingsCopy.remove( DATASOURCE );
|
||||
if ( dataSourceRef != null ) {
|
||||
applyDataSource(
|
||||
dataSourceRef,
|
||||
null,
|
||||
integrationSettingsCopy,
|
||||
mergedSettings
|
||||
);
|
||||
|
||||
// EARLY EXIT!!
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ( integrationSettingsCopy.containsKey( JPA_JTA_DATASOURCE ) ) {
|
||||
final Object dataSourceRef = integrationSettingsCopy.remove( JPA_JTA_DATASOURCE );
|
||||
if ( dataSourceRef != null ) {
|
||||
applyDataSource(
|
||||
dataSourceRef,
|
||||
true,
|
||||
integrationSettingsCopy,
|
||||
mergedSettings
|
||||
);
|
||||
|
||||
// EARLY EXIT!!
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ( integrationSettingsCopy.containsKey( JPA_NON_JTA_DATASOURCE ) ) {
|
||||
final Object dataSourceRef = integrationSettingsCopy.remove( JPA_NON_JTA_DATASOURCE );
|
||||
|
||||
applyDataSource(
|
||||
dataSourceRef,
|
||||
false,
|
||||
integrationSettingsCopy,
|
||||
mergedSettings
|
||||
);
|
||||
|
||||
// EARLY EXIT!!
|
||||
return;
|
||||
}
|
||||
|
||||
if ( integrationSettingsCopy.containsKey( URL ) ) {
|
||||
// these have precedence over the JPA ones
|
||||
final Object integrationJdbcUrl = integrationSettingsCopy.get( URL );
|
||||
if ( integrationJdbcUrl != null ) {
|
||||
//noinspection unchecked
|
||||
applyJdbcSettings(
|
||||
integrationJdbcUrl,
|
||||
NullnessHelper.coalesceSuppliedValues(
|
||||
() -> ConfigurationHelper.getString( DRIVER, integrationSettingsCopy ),
|
||||
() -> ConfigurationHelper.getString( JPA_JDBC_DRIVER, integrationSettingsCopy ),
|
||||
() -> ConfigurationHelper.getString( DRIVER, mergedSettings.configurationValues ),
|
||||
() -> ConfigurationHelper.getString( JPA_JDBC_DRIVER, mergedSettings.configurationValues )
|
||||
),
|
||||
integrationSettingsCopy,
|
||||
mergedSettings
|
||||
);
|
||||
|
||||
// EARLY EXIT!!
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ( integrationSettingsCopy.containsKey( JPA_JDBC_URL ) ) {
|
||||
final Object integrationJdbcUrl = integrationSettingsCopy.get( JPA_JDBC_URL );
|
||||
|
||||
if ( integrationJdbcUrl != null ) {
|
||||
//noinspection unchecked
|
||||
applyJdbcSettings(
|
||||
integrationJdbcUrl,
|
||||
NullnessHelper.coalesceSuppliedValues(
|
||||
() -> ConfigurationHelper.getString( JPA_JDBC_DRIVER, integrationSettingsCopy ),
|
||||
() -> ConfigurationHelper.getString( JPA_JDBC_DRIVER, mergedSettings.configurationValues )
|
||||
),
|
||||
integrationSettingsCopy,
|
||||
mergedSettings
|
||||
);
|
||||
|
||||
// EARLY EXIT!!
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ( persistenceUnit.getJtaDataSource() != null ) {
|
||||
applyDataSource(
|
||||
persistenceUnit.getJtaDataSource(),
|
||||
true,
|
||||
integrationSettingsCopy,
|
||||
mergedSettings
|
||||
);
|
||||
|
||||
// EARLY EXIT!!
|
||||
return;
|
||||
}
|
||||
|
||||
if ( persistenceUnit.getNonJtaDataSource() != null ) {
|
||||
applyDataSource(
|
||||
persistenceUnit.getNonJtaDataSource(),
|
||||
false,
|
||||
integrationSettingsCopy,
|
||||
mergedSettings
|
||||
);
|
||||
|
||||
// EARLY EXIT!!
|
||||
return;
|
||||
}
|
||||
|
||||
if ( mergedSettings.configurationValues.containsKey( URL ) ) {
|
||||
final Object url = mergedSettings.configurationValues.get( URL );
|
||||
|
||||
if ( url != null && ( ! ( url instanceof String ) || StringHelper.isNotEmpty( (String) url ) ) ) {
|
||||
applyJdbcSettings(
|
||||
url,
|
||||
ConfigurationHelper.getString( DRIVER, mergedSettings.configurationValues ),
|
||||
integrationSettingsCopy,
|
||||
mergedSettings
|
||||
);
|
||||
|
||||
// EARLY EXIT!!
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ( mergedSettings.configurationValues.containsKey( JPA_JDBC_URL ) ) {
|
||||
final Object url = mergedSettings.configurationValues.get( JPA_JDBC_URL );
|
||||
|
||||
if ( url != null && ( ! ( url instanceof String ) || StringHelper.isNotEmpty( (String) url ) ) ) {
|
||||
applyJdbcSettings(
|
||||
url,
|
||||
ConfigurationHelper.getString( JPA_JDBC_DRIVER, mergedSettings.configurationValues ),
|
||||
integrationSettingsCopy,
|
||||
mergedSettings
|
||||
);
|
||||
|
||||
// EARLY EXIT!!
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// any other conditions to account for?
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void applyDataSource(
|
||||
Object dataSourceRef,
|
||||
Boolean useJtaDataSource,
|
||||
HashMap<?, ?> integrationSettingsCopy,
|
||||
MergedSettings mergedSettings) {
|
||||
|
||||
// `IS_JTA_TXN_COORD` is a value set during `#normalizeTransactionCoordinator` to indicate whether
|
||||
// the execution environment "is JTA" as best as it can tell..
|
||||
//
|
||||
// we use this value when JTA was not explicitly specified in regards the DataSource
|
||||
final boolean isJtaTransactionCoordinator = (boolean) mergedSettings.configurationValues.remove( IS_JTA_TXN_COORD );
|
||||
final boolean isJta = useJtaDataSource == null ? isJtaTransactionCoordinator : useJtaDataSource;
|
||||
|
||||
// add to EMF properties (questionable - see HHH-13432)
|
||||
final String emfKey;
|
||||
final String inverseEmfKey;
|
||||
if ( isJta ) {
|
||||
emfKey = JPA_JTA_DATASOURCE;
|
||||
inverseEmfKey = JPA_NON_JTA_DATASOURCE;
|
||||
}
|
||||
else {
|
||||
emfKey = JPA_NON_JTA_DATASOURCE;
|
||||
inverseEmfKey = JPA_JTA_DATASOURCE;
|
||||
}
|
||||
mergedSettings.configurationValues.put( emfKey, dataSourceRef );
|
||||
|
||||
// clear any settings logically overridden by this datasource
|
||||
cleanUpConfigKeys(
|
||||
integrationSettingsCopy,
|
||||
mergedSettings,
|
||||
inverseEmfKey,
|
||||
JPA_JDBC_DRIVER,
|
||||
DRIVER,
|
||||
JPA_JDBC_URL,
|
||||
URL
|
||||
);
|
||||
|
||||
|
||||
// clean-up the entries in the "integration overrides" so they do not get get picked
|
||||
// up in the general "integration overrides" handling
|
||||
cleanUpConfigKeys( integrationSettingsCopy, DATASOURCE, JPA_JTA_DATASOURCE, JPA_NON_JTA_DATASOURCE );
|
||||
|
||||
// add under Hibernate's DATASOURCE setting where the ConnectionProvider will find it
|
||||
mergedSettings.configurationValues.put( DATASOURCE, dataSourceRef );
|
||||
}
|
||||
|
||||
private void cleanUpConfigKeys(HashMap<?, ?> integrationSettingsCopy, MergedSettings mergedSettings, String... keys) {
|
||||
for ( String key : keys ) {
|
||||
final Object removedIntgSetting = integrationSettingsCopy.remove( key );
|
||||
if ( removedIntgSetting != null ) {
|
||||
LOG.debugf( "Removed integration override setting [%s] due to normalization", key );
|
||||
}
|
||||
|
||||
final Object removedMergedSetting = mergedSettings.configurationValues.remove( key );
|
||||
if ( removedMergedSetting != null ) {
|
||||
LOG.debugf( "Removed merged setting [%s] due to normalization", key );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void cleanUpConfigKeys(Map<?, ?> settings, String... keys) {
|
||||
for ( String key : keys ) {
|
||||
settings.remove( key );
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void applyJdbcSettings(
|
||||
Object url,
|
||||
String driver,
|
||||
HashMap<?, ?> integrationSettingsCopy,
|
||||
MergedSettings mergedSettings) {
|
||||
mergedSettings.configurationValues.put( URL, url );
|
||||
mergedSettings.configurationValues.put( JPA_JDBC_URL, url );
|
||||
|
||||
if ( driver != null ) {
|
||||
mergedSettings.configurationValues.put( DRIVER, driver );
|
||||
mergedSettings.configurationValues.put( JPA_JDBC_DRIVER, driver );
|
||||
}
|
||||
else {
|
||||
mergedSettings.configurationValues.remove( DRIVER );
|
||||
mergedSettings.configurationValues.remove( JPA_JDBC_DRIVER );
|
||||
}
|
||||
|
||||
// clean up the integration-map values
|
||||
cleanUpConfigKeys(
|
||||
integrationSettingsCopy,
|
||||
DRIVER,
|
||||
JPA_JDBC_DRIVER,
|
||||
URL,
|
||||
JPA_JDBC_URL,
|
||||
USER,
|
||||
JPA_JDBC_USER,
|
||||
PASS,
|
||||
JPA_JDBC_PASSWORD
|
||||
);
|
||||
|
||||
cleanUpConfigKeys(
|
||||
integrationSettingsCopy,
|
||||
mergedSettings,
|
||||
DATASOURCE,
|
||||
JPA_JTA_DATASOURCE,
|
||||
JPA_NON_JTA_DATASOURCE
|
||||
);
|
||||
}
|
||||
|
||||
private void processHibernateConfigXmlResources(
|
||||
StandardServiceRegistryBuilder ssrBuilder,
|
||||
MergedSettings mergedSettings,
|
||||
String cfgXmlResourceName) {
|
||||
final LoadedConfig loadedConfig = ssrBuilder.getConfigLoader().loadConfigXmlResource( cfgXmlResourceName );
|
||||
|
||||
mergedSettings.processHibernateConfigXmlResources( loadedConfig );
|
||||
|
||||
ssrBuilder.getAggregatedCfgXml().merge( loadedConfig );
|
||||
}
|
||||
|
||||
private GrantedPermission parseJaccConfigEntry(String keyString, String valueString) {
|
||||
|
@ -639,90 +1039,7 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
|
|||
return new CacheRegionDefinition( cacheType, role, usage, region, lazyProperty );
|
||||
}
|
||||
|
||||
private void configure(StandardServiceRegistryBuilder ssrBuilder) {
|
||||
|
||||
applyJdbcConnectionProperties( ssrBuilder );
|
||||
applyTransactionProperties( ssrBuilder );
|
||||
|
||||
// flush before completion validation
|
||||
if ( "true".equals( configurationValues.get( Environment.FLUSH_BEFORE_COMPLETION ) ) ) {
|
||||
ssrBuilder.applySetting( Environment.FLUSH_BEFORE_COMPLETION, "false" );
|
||||
LOG.definingFlushBeforeCompletionIgnoredInHem( Environment.FLUSH_BEFORE_COMPLETION );
|
||||
}
|
||||
|
||||
// final StrategySelector strategySelector = ssrBuilder.getBootstrapServiceRegistry().getService( StrategySelector.class );
|
||||
// final Object interceptorSetting = configurationValues.remove( AvailableSettings.SESSION_INTERCEPTOR );
|
||||
// if ( interceptorSetting != null ) {
|
||||
// settings.setSessionInterceptorClass(
|
||||
// loadSessionInterceptorClass( interceptorSetting, strategySelector )
|
||||
// );
|
||||
// }
|
||||
}
|
||||
|
||||
private void applyJdbcConnectionProperties(StandardServiceRegistryBuilder ssrBuilder) {
|
||||
if ( dataSource != null ) {
|
||||
ssrBuilder.applySetting( DATASOURCE, dataSource );
|
||||
}
|
||||
else if ( persistenceUnit.getJtaDataSource() != null ) {
|
||||
if ( ! ssrBuilder.getSettings().containsKey( DATASOURCE ) ) {
|
||||
ssrBuilder.applySetting( DATASOURCE, persistenceUnit.getJtaDataSource() );
|
||||
// HHH-8121 : make the PU-defined value available to EMF.getProperties()
|
||||
configurationValues.put( JPA_JTA_DATASOURCE, persistenceUnit.getJtaDataSource() );
|
||||
}
|
||||
}
|
||||
else if ( persistenceUnit.getNonJtaDataSource() != null ) {
|
||||
if ( ! ssrBuilder.getSettings().containsKey( DATASOURCE ) ) {
|
||||
ssrBuilder.applySetting( DATASOURCE, persistenceUnit.getNonJtaDataSource() );
|
||||
// HHH-8121 : make the PU-defined value available to EMF.getProperties()
|
||||
configurationValues.put( JPA_NON_JTA_DATASOURCE, persistenceUnit.getNonJtaDataSource() );
|
||||
}
|
||||
}
|
||||
else {
|
||||
final String driver = (String) configurationValues.get( JPA_JDBC_DRIVER );
|
||||
if ( StringHelper.isNotEmpty( driver ) ) {
|
||||
ssrBuilder.applySetting( DRIVER, driver );
|
||||
}
|
||||
final String url = (String) configurationValues.get( JPA_JDBC_URL );
|
||||
if ( StringHelper.isNotEmpty( url ) ) {
|
||||
ssrBuilder.applySetting( URL, url );
|
||||
}
|
||||
final String user = (String) configurationValues.get( JPA_JDBC_USER );
|
||||
if ( StringHelper.isNotEmpty( user ) ) {
|
||||
ssrBuilder.applySetting( USER, user );
|
||||
}
|
||||
final String pass = (String) configurationValues.get( JPA_JDBC_PASSWORD );
|
||||
if ( StringHelper.isNotEmpty( pass ) ) {
|
||||
ssrBuilder.applySetting( PASS, pass );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void applyTransactionProperties(StandardServiceRegistryBuilder ssrBuilder) {
|
||||
PersistenceUnitTransactionType txnType = PersistenceUnitTransactionTypeHelper.interpretTransactionType(
|
||||
configurationValues.get( JPA_TRANSACTION_TYPE )
|
||||
);
|
||||
if ( txnType == null ) {
|
||||
txnType = persistenceUnit.getTransactionType();
|
||||
}
|
||||
if ( txnType == null ) {
|
||||
// is it more appropriate to have this be based on bootstrap entry point (EE vs SE)?
|
||||
txnType = PersistenceUnitTransactionType.RESOURCE_LOCAL;
|
||||
}
|
||||
boolean hasTxStrategy = configurationValues.containsKey( TRANSACTION_COORDINATOR_STRATEGY );
|
||||
if ( hasTxStrategy ) {
|
||||
LOG.overridingTransactionStrategyDangerous( TRANSACTION_COORDINATOR_STRATEGY );
|
||||
}
|
||||
else {
|
||||
if ( txnType == PersistenceUnitTransactionType.JTA ) {
|
||||
ssrBuilder.applySetting( TRANSACTION_COORDINATOR_STRATEGY, JtaTransactionCoordinatorBuilderImpl.class );
|
||||
}
|
||||
else if ( txnType == PersistenceUnitTransactionType.RESOURCE_LOCAL ) {
|
||||
ssrBuilder.applySetting( TRANSACTION_COORDINATOR_STRATEGY, JdbcResourceLocalTransactionCoordinatorBuilderImpl.class );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void configure(StandardServiceRegistry ssr, MergedSettings mergedSettings) {
|
||||
private void configureIdentifierGenerators(StandardServiceRegistry ssr) {
|
||||
final StrategySelector strategySelector = ssr.getService( StrategySelector.class );
|
||||
|
||||
// apply id generators
|
||||
|
@ -744,10 +1061,9 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
|
|||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected List<ConverterDescriptor> populate(
|
||||
MetadataSources metadataSources,
|
||||
MergedSettings mergedSettings,
|
||||
StandardServiceRegistry ssr) {
|
||||
private List<ConverterDescriptor> applyMappingResources(MetadataSources metadataSources) {
|
||||
// todo : where in the heck are `org.hibernate.jpa.boot.spi.PersistenceUnitDescriptor.getManagedClassNames` handled?!?
|
||||
|
||||
// final ClassLoaderService classLoaderService = ssr.getService( ClassLoaderService.class );
|
||||
//
|
||||
// // todo : make sure MetadataSources/Metadata are capable of handling duplicate sources
|
||||
|
@ -826,12 +1142,10 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
|
|||
return converterDescriptors;
|
||||
}
|
||||
|
||||
protected void populate(
|
||||
MetadataBuilder metamodelBuilder,
|
||||
private void applyMetamodelBuilderSettings(
|
||||
MergedSettings mergedSettings,
|
||||
StandardServiceRegistry ssr,
|
||||
List<ConverterDescriptor> converterDescriptors) {
|
||||
( (MetadataBuilderImplementor) metamodelBuilder ).getBootstrapContext().markAsJpaBootstrap();
|
||||
metamodelBuilder.getBootstrapContext().markAsJpaBootstrap();
|
||||
|
||||
if ( persistenceUnit.getTempClassLoader() != null ) {
|
||||
metamodelBuilder.applyTempClassLoader( persistenceUnit.getTempClassLoader() );
|
||||
|
@ -915,7 +1229,7 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
|
|||
// Metamodel will clean this up...
|
||||
try {
|
||||
SessionFactoryBuilder sfBuilder = metadata().getSessionFactoryBuilder();
|
||||
populate( sfBuilder, standardServiceRegistry );
|
||||
populateSfBuilder( sfBuilder, standardServiceRegistry );
|
||||
|
||||
SchemaManagementToolCoordinator.process(
|
||||
metadata, standardServiceRegistry, configurationValues, DelayedDropRegistryNotAvailableImpl.INSTANCE
|
||||
|
@ -929,10 +1243,10 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
|
|||
cancel();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public EntityManagerFactory build() {
|
||||
SessionFactoryBuilder sfBuilder = metadata().getSessionFactoryBuilder();
|
||||
populate( sfBuilder, standardServiceRegistry );
|
||||
final SessionFactoryBuilder sfBuilder = metadata().getSessionFactoryBuilder();
|
||||
populateSfBuilder( sfBuilder, standardServiceRegistry );
|
||||
|
||||
try {
|
||||
return sfBuilder.build();
|
||||
|
@ -942,7 +1256,7 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
|
|||
}
|
||||
}
|
||||
|
||||
protected void populate(SessionFactoryBuilder sfBuilder, StandardServiceRegistry ssr) {
|
||||
protected void populateSfBuilder(SessionFactoryBuilder sfBuilder, StandardServiceRegistry ssr) {
|
||||
|
||||
final StrategySelector strategySelector = ssr.getService( StrategySelector.class );
|
||||
|
||||
|
@ -1027,7 +1341,36 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
|
|||
private Map<String, JaccPermissionDeclarations> jaccPermissionsByContextId;
|
||||
private List<CacheRegionDefinition> cacheRegionDefinitions;
|
||||
|
||||
/**
|
||||
* MergedSettings is initialized with hibernate.properties
|
||||
*/
|
||||
private MergedSettings() {
|
||||
configurationValues.putAll( Environment.getProperties() );
|
||||
}
|
||||
|
||||
public void processPersistenceUnitDescriptorProperties(PersistenceUnitDescriptor persistenceUnit) {
|
||||
if ( persistenceUnit.getProperties() != null ) {
|
||||
configurationValues.putAll( persistenceUnit.getProperties() );
|
||||
}
|
||||
|
||||
configurationValues.put( PERSISTENCE_UNIT_NAME, persistenceUnit.getName() );
|
||||
|
||||
}
|
||||
|
||||
public void processHibernateConfigXmlResources(LoadedConfig loadedConfig){
|
||||
if ( ! configurationValues.containsKey( SESSION_FACTORY_NAME ) ) {
|
||||
// there is not already a SF-name in the merged settings
|
||||
final String sfName = loadedConfig.getSessionFactoryName();
|
||||
if ( sfName != null ) {
|
||||
// but the cfg.xml file we are processing named one..
|
||||
configurationValues.put( SESSION_FACTORY_NAME, sfName );
|
||||
}
|
||||
}
|
||||
else {
|
||||
// make sure they match?
|
||||
}
|
||||
|
||||
configurationValues.putAll( loadedConfig.getConfigurationValues() );
|
||||
}
|
||||
|
||||
public Map getConfigurationValues() {
|
||||
|
|
|
@ -46,7 +46,6 @@ public class ResultSetProcessingContextImpl implements ResultSetProcessingContex
|
|||
private final AliasResolutionContext aliasResolutionContext;
|
||||
private final boolean readOnly;
|
||||
private final boolean shouldUseOptionalEntityInformation;
|
||||
private final boolean forceFetchLazyAttributes;
|
||||
private final boolean shouldReturnProxies;
|
||||
private final QueryParameters queryParameters;
|
||||
private final NamedParameterContext namedParameterContext;
|
||||
|
@ -58,6 +57,8 @@ public class ResultSetProcessingContextImpl implements ResultSetProcessingContex
|
|||
private List<HydratedEntityRegistration> hydratedEntityRegistrationList;
|
||||
private int nRowsRead = 0;
|
||||
|
||||
private Map<EntityReference,EntityReferenceProcessingState> identifierResolutionContextMap;
|
||||
|
||||
/**
|
||||
* Builds a ResultSetProcessingContextImpl
|
||||
*
|
||||
|
@ -72,7 +73,6 @@ public class ResultSetProcessingContextImpl implements ResultSetProcessingContex
|
|||
final AliasResolutionContext aliasResolutionContext,
|
||||
final boolean readOnly,
|
||||
final boolean shouldUseOptionalEntityInformation,
|
||||
final boolean forceFetchLazyAttributes,
|
||||
final boolean shouldReturnProxies,
|
||||
final QueryParameters queryParameters,
|
||||
final NamedParameterContext namedParameterContext,
|
||||
|
@ -83,7 +83,6 @@ public class ResultSetProcessingContextImpl implements ResultSetProcessingContex
|
|||
this.aliasResolutionContext = aliasResolutionContext;
|
||||
this.readOnly = readOnly;
|
||||
this.shouldUseOptionalEntityInformation = shouldUseOptionalEntityInformation;
|
||||
this.forceFetchLazyAttributes = forceFetchLazyAttributes;
|
||||
this.shouldReturnProxies = shouldReturnProxies;
|
||||
this.queryParameters = queryParameters;
|
||||
this.namedParameterContext = namedParameterContext;
|
||||
|
@ -137,15 +136,22 @@ public class ResultSetProcessingContextImpl implements ResultSetProcessingContex
|
|||
return LockMode.NONE;
|
||||
}
|
||||
|
||||
private Map<EntityReference,EntityReferenceProcessingState> identifierResolutionContextMap;
|
||||
|
||||
@Override
|
||||
public EntityReferenceProcessingState getProcessingState(final EntityReference entityReference) {
|
||||
EntityReferenceProcessingState context;
|
||||
if ( identifierResolutionContextMap == null ) {
|
||||
identifierResolutionContextMap = new IdentityHashMap<>();
|
||||
//The default expected size of IdentityHashMap is 21, which is likely to allocate larger arrays than what is typically necessary.
|
||||
//Reducing to 5, as a reasonable estimate for typical use: any larger query can better justify the need to resize,
|
||||
//while single loads shouldn't pay such an high cost.
|
||||
//This can save a lot of memory as it reduces the internal table of IdentityHashMap from a 64 slot array, to 16 slots:
|
||||
//that's a 75% memory cost reduction for usage patterns which do many individual loads.
|
||||
identifierResolutionContextMap = new IdentityHashMap<>(5);
|
||||
context = null;
|
||||
}
|
||||
else {
|
||||
context = identifierResolutionContextMap.get( entityReference );
|
||||
}
|
||||
|
||||
EntityReferenceProcessingState context = identifierResolutionContextMap.get( entityReference );
|
||||
if ( context == null ) {
|
||||
context = new EntityReferenceProcessingState() {
|
||||
private boolean wasMissingIdentifier;
|
||||
|
|
|
@ -100,9 +100,6 @@ public class ResultSetProcessorImpl implements ResultSetProcessor {
|
|||
maxRows = Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
// Handles the "FETCH ALL PROPERTIES" directive in HQL
|
||||
final boolean forceFetchLazyAttributes = false;
|
||||
|
||||
final ResultSetProcessingContextImpl context = new ResultSetProcessingContextImpl(
|
||||
resultSet,
|
||||
session,
|
||||
|
@ -110,7 +107,6 @@ public class ResultSetProcessorImpl implements ResultSetProcessor {
|
|||
aliasResolutionContext,
|
||||
readOnly,
|
||||
shouldUseOptionalEntityInstance,
|
||||
forceFetchLazyAttributes,
|
||||
returnProxies,
|
||||
queryParameters,
|
||||
namedParameterContext,
|
||||
|
|
|
@ -34,10 +34,8 @@ public class MaskSensitiveInformationTest extends BaseEntityManagerFunctionalTes
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void addConfigOptions(Map options) {
|
||||
options.put( AvailableSettings.JPA_JDBC_USER, options.get( AvailableSettings.USER ) );
|
||||
options.put( AvailableSettings.JPA_JDBC_PASSWORD, options.get( AvailableSettings.PASS ) );
|
||||
super.addConfigOptions( options );
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -9,54 +9,106 @@
|
|||
|
||||
package org.hibernate.jpa.test.connection;
|
||||
|
||||
import java.io.File;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import javax.persistence.PersistenceException;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.dialect.H2Dialect;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.jpa.HibernatePersistenceProvider;
|
||||
import org.hibernate.jpa.test.Distributor;
|
||||
import org.hibernate.jpa.test.Item;
|
||||
import org.hibernate.jpa.test.xml.Light;
|
||||
import org.hibernate.jpa.test.xml.Lighter;
|
||||
|
||||
import org.hibernate.testing.util.ExceptionUtil;
|
||||
import org.hibernate.testing.util.jpa.PersistenceUnitInfoAdapter;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author Emmanuel Bernard
|
||||
*/
|
||||
public class DataSourceInjectionTest {
|
||||
EntityManagerFactory emf;
|
||||
@Test
|
||||
public void testDatasourceInjection() throws Exception {
|
||||
File current = new File(".");
|
||||
File sub = new File(current, "puroot");
|
||||
sub.mkdir();
|
||||
PersistenceUnitInfoImpl info = new PersistenceUnitInfoImpl( sub.toURI().toURL(), new String[]{} );
|
||||
withPuRoot(
|
||||
puRootUrl -> {
|
||||
final PersistenceUnitInfoAdapter persistenceUnitInfo = createPuDescriptor( puRootUrl, new FakeDataSource() );
|
||||
|
||||
// otherwise the FakeDataSourceException will be eaten trying to resolve the Dialect
|
||||
final Map<String, Object> intgOverrides = Collections.singletonMap(
|
||||
AvailableSettings.DIALECT,
|
||||
H2Dialect.class
|
||||
);
|
||||
|
||||
final HibernatePersistenceProvider provider = new HibernatePersistenceProvider();
|
||||
try ( final SessionFactoryImplementor sf = provider.createContainerEntityManagerFactory(
|
||||
persistenceUnitInfo,
|
||||
intgOverrides
|
||||
).unwrap( SessionFactoryImplementor.class ) ) {
|
||||
|
||||
try ( final SessionImplementor session = sf.openSession().unwrap( SessionImplementor.class ) ) {
|
||||
session.createQuery( "select i from Item i" ).list();
|
||||
Assert.fail( "Expecting FakeDataSourceException" );
|
||||
}
|
||||
catch (PersistenceException pe) {
|
||||
try {
|
||||
throw (RuntimeException) pe.getCause();
|
||||
}
|
||||
catch (FakeDataSourceException fde) {
|
||||
//success
|
||||
}
|
||||
}
|
||||
catch (FakeDataSourceException fde) {
|
||||
//success
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
protected PersistenceUnitInfoAdapter createPuDescriptor(URL puRootUrl, DataSource dataSource) {
|
||||
return new PersistenceUnitInfoAdapter() {
|
||||
@Override
|
||||
public DataSource getNonJtaDataSource() {
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL getPersistenceUnitRootUrl() {
|
||||
return puRootUrl;
|
||||
}
|
||||
|
||||
public List<String> getManagedClassNames() {
|
||||
List<String> classes = new ArrayList<>();
|
||||
classes.add( Item.class.getName() );
|
||||
classes.add( Distributor.class.getName() );
|
||||
classes.add( Light.class.getName() );
|
||||
classes.add( Lighter.class.getName() );
|
||||
return classes;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void withPuRoot(Consumer<URL> puRootUrlConsumer) throws Exception {
|
||||
// create a temporary directory to serve as the "PU root URL"
|
||||
final Path puroot = Files.createTempDirectory( "puroot" );
|
||||
final URL puRootUrl = puroot.toUri().toURL();
|
||||
|
||||
try {
|
||||
emf = new HibernatePersistenceProvider().createContainerEntityManagerFactory( info, null );
|
||||
try {
|
||||
emf.createEntityManager().createQuery( "select i from Item i" ).getResultList();
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
emf.close();
|
||||
}
|
||||
catch (Exception ignore) {
|
||||
int i = 0;
|
||||
}
|
||||
}
|
||||
Assert.fail( "FakeDatasource should have been used" );
|
||||
}
|
||||
catch (PersistenceException pe) {
|
||||
if(emf != null){
|
||||
emf.close();
|
||||
}
|
||||
Assert.assertTrue( ExceptionUtil.rootCause( pe ) instanceof FakeDataSourceException );
|
||||
}
|
||||
catch (FakeDataSourceException fde) {
|
||||
//success
|
||||
puRootUrlConsumer.accept( puRootUrl );
|
||||
}
|
||||
finally {
|
||||
sub.delete();
|
||||
Files.deleteIfExists( puroot );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ public class PersistenceUnitInfoImpl implements PersistenceUnitInfo {
|
|||
private URL puRoot;
|
||||
|
||||
public PersistenceUnitInfoImpl(URL puRoot, String[] mappingFiles) {
|
||||
this.mappingFiles = new ArrayList<String>( mappingFiles.length );
|
||||
this.mappingFiles = new ArrayList<>( mappingFiles.length );
|
||||
this.mappingFiles.addAll( Arrays.asList( mappingFiles ) );
|
||||
this.puRoot = puRoot;
|
||||
}
|
||||
|
|
|
@ -1,54 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.orm.test.bootstrap;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.persistence.spi.PersistenceProvider;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.jpa.HibernatePersistenceProvider;
|
||||
|
||||
import org.hibernate.testing.FailureExpected;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||
import org.hibernate.testing.util.jpa.PersistenceUnitInfoAdapter;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class PersistenceUnitInfoTests extends BaseUnitTestCase {
|
||||
@Test
|
||||
@TestForIssue( jiraKey = "HHH-13432" )
|
||||
@FailureExpected( jiraKey = "HHH-13432" )
|
||||
public void testJtaDataExposedAsProperty() {
|
||||
final DataSource puDataSource = new DataSourceStub( "puDataSource" );
|
||||
final PersistenceUnitInfoAdapter info = new PersistenceUnitInfoAdapter() {
|
||||
|
||||
@Override
|
||||
public DataSource getNonJtaDataSource() {
|
||||
return puDataSource;
|
||||
}
|
||||
};
|
||||
|
||||
final PersistenceProvider provider = new HibernatePersistenceProvider();
|
||||
|
||||
final EntityManagerFactory emf = provider.createContainerEntityManagerFactory(
|
||||
info,
|
||||
Collections.emptyMap()
|
||||
);
|
||||
|
||||
final Map<String, Object> properties = emf.getProperties();
|
||||
final Object o = properties.get( AvailableSettings.JPA_JTA_DATASOURCE );
|
||||
assertEquals( o, puDataSource );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.orm.test.bootstrap.jpa;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.persistence.spi.PersistenceProvider;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl;
|
||||
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.jpa.HibernatePersistenceProvider;
|
||||
import org.hibernate.testing.jdbc.DataSourceStub;
|
||||
|
||||
import org.hibernate.testing.FailureExpected;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||
import org.hibernate.testing.util.jpa.PersistenceUnitInfoAdapter;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class PersistenceUnitInfoTests extends BaseUnitTestCase {
|
||||
@Test
|
||||
@TestForIssue( jiraKey = "HHH-13432" )
|
||||
public void testNonJtaDataExposedAsProperty() {
|
||||
final DataSource puDataSource = new DataSourceStub( "puDataSource" );
|
||||
final PersistenceUnitInfoAdapter info = new PersistenceUnitInfoAdapter() {
|
||||
|
||||
@Override
|
||||
public DataSource getNonJtaDataSource() {
|
||||
return puDataSource;
|
||||
}
|
||||
};
|
||||
|
||||
final PersistenceProvider provider = new HibernatePersistenceProvider();
|
||||
|
||||
final EntityManagerFactory emf = provider.createContainerEntityManagerFactory(
|
||||
info,
|
||||
Collections.emptyMap()
|
||||
);
|
||||
|
||||
// first let's check the DataSource used in the EMF...
|
||||
final ConnectionProvider connectionProvider = emf.unwrap( SessionFactoryImplementor.class )
|
||||
.getServiceRegistry()
|
||||
.getService( ConnectionProvider.class );
|
||||
assertThat( connectionProvider, instanceOf( DatasourceConnectionProviderImpl.class ) );
|
||||
final DatasourceConnectionProviderImpl dsCp = (DatasourceConnectionProviderImpl) connectionProvider;
|
||||
assertThat( dsCp.getDataSource(), is( puDataSource ) );
|
||||
|
||||
// now let's check that it is exposed via the EMF properties
|
||||
// - note : the spec does not indicate that this should work, but
|
||||
// it worked this way in previous versions
|
||||
final Object o = emf.getProperties().get( AvailableSettings.JPA_NON_JTA_DATASOURCE );
|
||||
assertThat( o, is( puDataSource ) );
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue( jiraKey = "HHH-13432" )
|
||||
public void testJtaDataExposedAsProperty() {
|
||||
final DataSource puDataSource = new DataSourceStub( "puDataSource" );
|
||||
final PersistenceUnitInfoAdapter info = new PersistenceUnitInfoAdapter() {
|
||||
|
||||
@Override
|
||||
public DataSource getJtaDataSource() {
|
||||
return puDataSource;
|
||||
}
|
||||
};
|
||||
|
||||
final PersistenceProvider provider = new HibernatePersistenceProvider();
|
||||
|
||||
final EntityManagerFactory emf = provider.createContainerEntityManagerFactory(
|
||||
info,
|
||||
Collections.emptyMap()
|
||||
);
|
||||
|
||||
// first let's check the DataSource used in the EMF...
|
||||
final ConnectionProvider connectionProvider = emf.unwrap( SessionFactoryImplementor.class )
|
||||
.getServiceRegistry()
|
||||
.getService( ConnectionProvider.class );
|
||||
assertThat( connectionProvider, instanceOf( DatasourceConnectionProviderImpl.class ) );
|
||||
final DatasourceConnectionProviderImpl dsCp = (DatasourceConnectionProviderImpl) connectionProvider;
|
||||
assertThat( dsCp.getDataSource(), is( puDataSource ) );
|
||||
|
||||
// now let's check that it is exposed via the EMF properties
|
||||
// - again, the spec does not indicate that this should work, but
|
||||
// it worked this way in previous versions
|
||||
final Map<String, Object> properties = emf.getProperties();
|
||||
final Object o = properties.get( AvailableSettings.JPA_JTA_DATASOURCE );
|
||||
assertEquals( puDataSource, o );
|
||||
}
|
||||
}
|
|
@ -4,35 +4,43 @@
|
|||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.orm.test.bootstrap;
|
||||
package org.hibernate.orm.test.bootstrap.jpa;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.metamodel.EntityType;
|
||||
import javax.persistence.spi.PersistenceProvider;
|
||||
import javax.persistence.spi.PersistenceUnitInfo;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.hibernate.cache.spi.access.AccessType;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl;
|
||||
import org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl;
|
||||
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.jpa.HibernatePersistenceProvider;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
|
||||
import org.hibernate.testing.FailureExpected;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.env.ConnectionProviderBuilder;
|
||||
import org.hibernate.testing.jdbc.DataSourceStub;
|
||||
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||
import org.hibernate.testing.util.jpa.DelegatingPersistenceUnitInfo;
|
||||
import org.hibernate.testing.util.jpa.PersistenceUnitInfoAdapter;
|
||||
import org.hibernate.testing.util.jpa.PersistenceUnitInfoPropertiesWrapper;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
import static org.hamcrest.CoreMatchers.nullValue;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
||||
/**
|
||||
|
@ -41,31 +49,19 @@ import static org.hamcrest.MatcherAssert.assertThat;
|
|||
public class PersistenceUnitOverridesTests extends BaseUnitTestCase {
|
||||
|
||||
@Test
|
||||
public void testCustomProviderPassingIntegrationJpaJdbcOverrides() {
|
||||
PersistenceProvider provider = new HibernatePersistenceProvider() {
|
||||
@Override
|
||||
public EntityManagerFactory createContainerEntityManagerFactory(PersistenceUnitInfo info, Map integrationOverrides) {
|
||||
return super.createContainerEntityManagerFactory(
|
||||
new DelegatingPersistenceUnitInfo( info ) {
|
||||
@Override
|
||||
public Properties getProperties() {
|
||||
// use the "db1" connection settings keyed by the JPA property names (org.hibernate.cfg.AvailableSettings.JPA_JDBC_DRIVER, e.g.)
|
||||
final Properties properties = new Properties();
|
||||
properties.putAll( info.getProperties() );
|
||||
properties.putAll( ConnectionProviderBuilder.getJpaConnectionProviderProperties( "db1" ) );
|
||||
return properties;
|
||||
}
|
||||
},
|
||||
integrationOverrides
|
||||
);
|
||||
}
|
||||
};
|
||||
public void testPassingIntegrationJpaJdbcOverrides() {
|
||||
|
||||
// however, use the "db2" JPA connection settings which should override the persistence unit values
|
||||
// the integration overrides say to use the "db2" JPA connection settings (which should override the persistence unit values)
|
||||
final Map integrationOverrides = ConnectionProviderBuilder.getJpaConnectionProviderProperties( "db2" );
|
||||
|
||||
final EntityManagerFactory emf = provider.createContainerEntityManagerFactory(
|
||||
new PersistenceUnitInfoPropertiesWrapper(),
|
||||
final EntityManagerFactory emf = new HibernatePersistenceProvider().createContainerEntityManagerFactory(
|
||||
new PersistenceUnitInfoAdapter() {
|
||||
@Override
|
||||
public Properties getProperties() {
|
||||
// effectively, the `persistence.xml` defines `db1` as the connection settings
|
||||
return ConnectionProviderBuilder.getJpaConnectionProviderProperties( "db1" );
|
||||
}
|
||||
},
|
||||
integrationOverrides
|
||||
);
|
||||
|
||||
|
@ -84,7 +80,50 @@ public class PersistenceUnitOverridesTests extends BaseUnitTestCase {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testPassingIntegrationJpaJdbcOverridesForJtaDataSourceProperty() {
|
||||
public void testPassingIntegrationJtaDataSourceOverrideForJpaJdbcSettings() {
|
||||
final PersistenceUnitInfoAdapter puInfo = new PersistenceUnitInfoAdapter(
|
||||
ConnectionProviderBuilder.getJpaConnectionProviderProperties( "db2" )
|
||||
);
|
||||
|
||||
final DataSource integrationDataSource = new DataSourceStub( "integrationDataSource" );
|
||||
|
||||
final HibernatePersistenceProvider provider = new HibernatePersistenceProvider();
|
||||
|
||||
final EntityManagerFactory emf = provider.createContainerEntityManagerFactory(
|
||||
puInfo,
|
||||
Collections.singletonMap( AvailableSettings.JPA_JTA_DATASOURCE, integrationDataSource )
|
||||
);
|
||||
|
||||
try {
|
||||
// first let's check the DataSource used in the EMF...
|
||||
final ConnectionProvider connectionProvider = emf.unwrap( SessionFactoryImplementor.class )
|
||||
.getServiceRegistry()
|
||||
.getService( ConnectionProvider.class );
|
||||
assertThat( connectionProvider, instanceOf( DatasourceConnectionProviderImpl.class ) );
|
||||
final DatasourceConnectionProviderImpl dsCp = (DatasourceConnectionProviderImpl) connectionProvider;
|
||||
assertThat( dsCp.getDataSource(), is( integrationDataSource ) );
|
||||
|
||||
// now let's check that it is exposed via the EMF properties
|
||||
// - note : the spec does not indicate that this should work, but
|
||||
// it worked this way in previous versions
|
||||
final Object jtaDs = emf.getProperties().get( AvailableSettings.JPA_JTA_DATASOURCE );
|
||||
assertThat( jtaDs, is( integrationDataSource ) );
|
||||
|
||||
// Additionally, we should have set Hibernate's DATASOURCE setting
|
||||
final Object hibDs = emf.getProperties().get( AvailableSettings.JPA_JTA_DATASOURCE );
|
||||
assertThat( hibDs, is( integrationDataSource ) );
|
||||
|
||||
// Make sure the non-jta-data-source setting was cleared or otherwise null
|
||||
final Object nonJtaDs = emf.getProperties().get( AvailableSettings.JPA_NON_JTA_DATASOURCE );
|
||||
assertThat( nonJtaDs, nullValue() );
|
||||
}
|
||||
finally {
|
||||
emf.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPassingIntegrationJpaJdbcOverrideForJtaDataSourceProperty() {
|
||||
PersistenceProvider provider = new HibernatePersistenceProvider() {
|
||||
@Override
|
||||
public EntityManagerFactory createContainerEntityManagerFactory(PersistenceUnitInfo info, Map integrationOverrides) {
|
||||
|
@ -103,6 +142,16 @@ public class PersistenceUnitOverridesTests extends BaseUnitTestCase {
|
|||
puProperties.put( AvailableSettings.JPA_JTA_DATASOURCE, puDataSource );
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataSource getJtaDataSource() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataSource getNonJtaDataSource() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Properties getProperties() {
|
||||
return puProperties;
|
||||
|
@ -142,11 +191,11 @@ public class PersistenceUnitOverridesTests extends BaseUnitTestCase {
|
|||
}
|
||||
|
||||
@Test
|
||||
@FailureExpected(
|
||||
jiraKey = "HHH-12858",
|
||||
message = "Even though the JDBC settings override a DataSource *property*, it" +
|
||||
" does not override a DataSource defined using the dedicated persistence.xml element"
|
||||
)
|
||||
// @FailureExpected(
|
||||
// jiraKey = "HHH-12858",
|
||||
// message = "Even though the JDBC settings override a DataSource *property*, it" +
|
||||
// " does not override a DataSource defined using the dedicated persistence.xml element"
|
||||
// )
|
||||
public void testPassingIntegrationJpaJdbcOverridesForJtaDataSourceElement() {
|
||||
PersistenceProvider provider = new HibernatePersistenceProvider() {
|
||||
@Override
|
||||
|
@ -154,11 +203,7 @@ public class PersistenceUnitOverridesTests extends BaseUnitTestCase {
|
|||
return super.createContainerEntityManagerFactory(
|
||||
new DelegatingPersistenceUnitInfo( info ) {
|
||||
// inject a JPA JTA DataSource setting into the PU
|
||||
final DataSource puDataSource;
|
||||
|
||||
{
|
||||
puDataSource = new DataSourceStub( "puDataSource" );
|
||||
}
|
||||
final DataSource puDataSource = new DataSourceStub( "puDataSource" );
|
||||
|
||||
@Override
|
||||
public DataSource getJtaDataSource() {
|
||||
|
@ -199,11 +244,11 @@ public class PersistenceUnitOverridesTests extends BaseUnitTestCase {
|
|||
}
|
||||
|
||||
@Test
|
||||
@FailureExpected(
|
||||
jiraKey = "HHH-12858",
|
||||
message = "So it appears any use of the persistence.xml `jta-data-source` or `non-jta-data-source` " +
|
||||
"have precedence over integration settings, which is also incorrect"
|
||||
)
|
||||
// @FailureExpected(
|
||||
// jiraKey = "HHH-12858",
|
||||
// message = "So it appears any use of the persistence.xml `jta-data-source` or `non-jta-data-source` " +
|
||||
// "have precedence over integration settings, which is also incorrect"
|
||||
// )
|
||||
public void testPassingIntegrationJpaDataSourceOverrideForJtaDataSourceElement() {
|
||||
final DataSource puDataSource = new DataSourceStub( "puDataSource" );
|
||||
final DataSource integrationDataSource = new DataSourceStub( "integrationDataSource" );
|
||||
|
@ -255,7 +300,7 @@ public class PersistenceUnitOverridesTests extends BaseUnitTestCase {
|
|||
}
|
||||
|
||||
@Test
|
||||
@FailureExpected( jiraKey = "HHH-12858", message = "regression - fix" )
|
||||
@TestForIssue( jiraKey = "HHH-13640" )
|
||||
public void testIntegrationOverridesOfPersistenceXmlDataSource() {
|
||||
|
||||
// mimics a DataSource defined in the persistence.xml
|
||||
|
@ -300,7 +345,7 @@ public class PersistenceUnitOverridesTests extends BaseUnitTestCase {
|
|||
}
|
||||
|
||||
@Test
|
||||
@FailureExpected( jiraKey = "HHH-12858", message = "regression - fix" )
|
||||
@TestForIssue( jiraKey = "HHH-13640" )
|
||||
public void testIntegrationOverridesOfPersistenceXmlDataSourceWithDriverManagerInfo() {
|
||||
|
||||
// mimics a DataSource defined in the persistence.xml
|
||||
|
@ -326,9 +371,135 @@ public class PersistenceUnitOverridesTests extends BaseUnitTestCase {
|
|||
integrationSettings
|
||||
);
|
||||
|
||||
final SessionFactoryImplementor sessionFactory = emf.unwrap( SessionFactoryImplementor.class );
|
||||
final ConnectionProvider connectionProvider = sessionFactory.getServiceRegistry().getService( ConnectionProvider.class );
|
||||
assertThat( connectionProvider, instanceOf( DriverManagerConnectionProviderImpl.class ) );
|
||||
try {
|
||||
final SessionFactoryImplementor sessionFactory = emf.unwrap( SessionFactoryImplementor.class );
|
||||
final ConnectionProvider connectionProvider = sessionFactory.getServiceRegistry().getService(
|
||||
ConnectionProvider.class );
|
||||
assertThat( connectionProvider, instanceOf( DriverManagerConnectionProviderImpl.class ) );
|
||||
}
|
||||
finally {
|
||||
emf.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCfgXmlBaseline() {
|
||||
final PersistenceUnitInfoAdapter info = new PersistenceUnitInfoAdapter() {
|
||||
private final Properties props = new Properties();
|
||||
{
|
||||
props.put( org.hibernate.jpa.AvailableSettings.CFG_FILE, "org/hibernate/orm/test/bootstrap/jpa/hibernate.cfg.xml" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Properties getProperties() {
|
||||
return props;
|
||||
}
|
||||
};
|
||||
|
||||
final PersistenceProvider provider = new HibernatePersistenceProvider();
|
||||
|
||||
final Map integrationSettings = Collections.emptyMap();
|
||||
|
||||
final EntityManagerFactory emf = provider.createContainerEntityManagerFactory(
|
||||
info,
|
||||
integrationSettings
|
||||
);
|
||||
|
||||
try {
|
||||
assertThat(
|
||||
emf.getProperties().get( AvailableSettings.DIALECT ),
|
||||
is( PersistenceUnitDialect.class.getName() )
|
||||
);
|
||||
assertThat(
|
||||
emf.unwrap( SessionFactoryImplementor.class ).getJdbcServices().getDialect(),
|
||||
instanceOf( PersistenceUnitDialect.class )
|
||||
);
|
||||
|
||||
final EntityType<MappedEntity> entityMapping = emf.getMetamodel().entity( MappedEntity.class );
|
||||
assertThat( entityMapping, notNullValue() );
|
||||
}
|
||||
finally {
|
||||
emf.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIntegrationOverridesOfCfgXml() {
|
||||
final PersistenceUnitInfoAdapter info = new PersistenceUnitInfoAdapter() {
|
||||
private final Properties props = new Properties();
|
||||
{
|
||||
props.put( org.hibernate.jpa.AvailableSettings.CFG_FILE, "org/hibernate/orm/test/bootstrap/jpa/hibernate.cfg.xml" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Properties getProperties() {
|
||||
return props;
|
||||
}
|
||||
};
|
||||
|
||||
final PersistenceProvider provider = new HibernatePersistenceProvider();
|
||||
|
||||
final Map integrationSettings = Collections.singletonMap(
|
||||
AvailableSettings.DIALECT,
|
||||
IntegrationDialect.class.getName()
|
||||
);
|
||||
|
||||
final EntityManagerFactory emf = provider.createContainerEntityManagerFactory(
|
||||
info,
|
||||
integrationSettings
|
||||
);
|
||||
|
||||
try {
|
||||
assertThat(
|
||||
emf.getProperties().get( AvailableSettings.DIALECT ),
|
||||
is( IntegrationDialect.class.getName() )
|
||||
);
|
||||
assertThat(
|
||||
emf.unwrap( SessionFactoryImplementor.class ).getJdbcServices().getDialect(),
|
||||
instanceOf( IntegrationDialect.class )
|
||||
);
|
||||
|
||||
final EntityPersister entityMapping = emf.unwrap( SessionFactoryImplementor.class )
|
||||
.getMetamodel()
|
||||
.entityPersister( MappedEntity.class );
|
||||
assertThat( entityMapping, notNullValue() );
|
||||
assertThat(
|
||||
entityMapping.getCacheAccessStrategy().getAccessType(),
|
||||
is( AccessType.READ_ONLY )
|
||||
);
|
||||
}
|
||||
finally {
|
||||
emf.close();
|
||||
}
|
||||
}
|
||||
|
||||
public static class PersistenceUnitDialect extends Dialect {
|
||||
}
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public static class IntegrationDialect extends Dialect {
|
||||
}
|
||||
|
||||
@Entity
|
||||
public static class MappedEntity {
|
||||
private Integer id;
|
||||
private String name;
|
||||
|
||||
@Id
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -22,8 +22,8 @@ import org.hibernate.boot.SessionFactoryBuilder;
|
|||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.proxy.HibernateProxy;
|
||||
import org.hibernate.stat.Statistics;
|
||||
|
||||
import org.hibernate.testing.FailureExpected;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
|
||||
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
||||
|
@ -31,6 +31,7 @@ import org.junit.After;
|
|||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
|
@ -77,16 +78,52 @@ public class LazyToOnesProxyWithSubclassesTest extends BaseNonConfigCoreFunction
|
|||
|
||||
inSession(
|
||||
session -> {
|
||||
final Statistics stats = sessionFactory().getStatistics();
|
||||
stats.clear();
|
||||
final OtherEntity otherEntity = session.get( OtherEntity.class, "test1" );
|
||||
assertTrue( Hibernate.isPropertyInitialized( otherEntity, "animal" ) );
|
||||
assertFalse( Hibernate.isInitialized( otherEntity.animal ) );
|
||||
assertTrue( HibernateProxy.class.isInstance( otherEntity.animal ) );
|
||||
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
|
||||
Animal animal = session.load( Animal.class, "A Human" );
|
||||
assertFalse( Hibernate.isInitialized( animal ) );
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetInitializeAssociations() {
|
||||
inTransaction(
|
||||
session -> {
|
||||
Human human = new Human( "A Human" );
|
||||
OtherEntity otherEntity = new OtherEntity( "test1" );
|
||||
otherEntity.animal = human;
|
||||
|
||||
session.persist( human );
|
||||
session.persist( otherEntity );
|
||||
}
|
||||
);
|
||||
|
||||
inSession(
|
||||
session -> {
|
||||
final Statistics stats = sessionFactory().getStatistics();
|
||||
stats.clear();
|
||||
final OtherEntity otherEntity = session.get( OtherEntity.class, "test1" );
|
||||
assertTrue( Hibernate.isPropertyInitialized( otherEntity, "animal" ) );
|
||||
assertFalse( Hibernate.isInitialized( otherEntity.animal ) );
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
|
||||
Animal animal = session.get( Animal.class, "A Human" );
|
||||
assertTrue( Hibernate.isInitialized( animal ) );
|
||||
assertEquals( 2, stats.getPrepareStatementCount() );
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExistingProxyAssociation() {
|
||||
inTransaction(
|
||||
|
@ -102,6 +139,8 @@ public class LazyToOnesProxyWithSubclassesTest extends BaseNonConfigCoreFunction
|
|||
|
||||
inSession(
|
||||
session -> {
|
||||
final Statistics stats = sessionFactory().getStatistics();
|
||||
stats.clear();
|
||||
final OtherEntity otherEntity = session.get( OtherEntity.class, "test1" );
|
||||
assertTrue( Hibernate.isPropertyInitialized( otherEntity, "animal" ) );
|
||||
assertFalse( Hibernate.isInitialized( otherEntity.animal ) );
|
||||
|
@ -109,13 +148,12 @@ public class LazyToOnesProxyWithSubclassesTest extends BaseNonConfigCoreFunction
|
|||
assertTrue( Hibernate.isPropertyInitialized( otherEntity, "primate" ) );
|
||||
assertFalse( Hibernate.isInitialized( otherEntity.primate ) );
|
||||
assertTrue( HibernateProxy.class.isInstance( otherEntity.primate ) );
|
||||
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
@FailureExpected( jiraKey = "HHH-13640" )
|
||||
public void testExistingProxyAssociationLeafSubclass() {
|
||||
inTransaction(
|
||||
session -> {
|
||||
|
@ -131,6 +169,9 @@ public class LazyToOnesProxyWithSubclassesTest extends BaseNonConfigCoreFunction
|
|||
|
||||
inSession(
|
||||
session -> {
|
||||
final Statistics stats = sessionFactory().getStatistics();
|
||||
stats.clear();
|
||||
|
||||
final OtherEntity otherEntity = session.get( OtherEntity.class, "test1" );
|
||||
assertTrue( Hibernate.isPropertyInitialized( otherEntity, "animal" ) );
|
||||
assertFalse( Hibernate.isInitialized( otherEntity.animal ) );
|
||||
|
@ -142,6 +183,14 @@ public class LazyToOnesProxyWithSubclassesTest extends BaseNonConfigCoreFunction
|
|||
assertFalse( Hibernate.isInitialized( otherEntity.human ) );
|
||||
// TODO: Should otherEntity.human be a narrowed HibernateProxy or
|
||||
// an uninitialized non-HibernateProxy proxy?
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
|
||||
Human human = otherEntity.getHuman();
|
||||
human.getName();
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
|
||||
human.getSex();
|
||||
assertEquals( 2, stats.getPrepareStatementCount() );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -158,7 +207,6 @@ public class LazyToOnesProxyWithSubclassesTest extends BaseNonConfigCoreFunction
|
|||
);
|
||||
}
|
||||
|
||||
|
||||
@Entity(name = "Animal")
|
||||
@Table(name = "Animal")
|
||||
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
|
||||
|
@ -195,6 +243,8 @@ public class LazyToOnesProxyWithSubclassesTest extends BaseNonConfigCoreFunction
|
|||
@Table(name = "Human")
|
||||
public static class Human extends Primate {
|
||||
|
||||
private String sex;
|
||||
|
||||
public Human(String name) {
|
||||
this();
|
||||
setName( name );
|
||||
|
@ -203,6 +253,14 @@ public class LazyToOnesProxyWithSubclassesTest extends BaseNonConfigCoreFunction
|
|||
protected Human() {
|
||||
// this form used by Hibernate
|
||||
}
|
||||
|
||||
public String getSex() {
|
||||
return sex;
|
||||
}
|
||||
|
||||
public void setSex(String sex) {
|
||||
this.sex = sex;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "OtherEntity")
|
||||
|
@ -235,5 +293,13 @@ public class LazyToOnesProxyWithSubclassesTest extends BaseNonConfigCoreFunction
|
|||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public Human getHuman() {
|
||||
return human;
|
||||
}
|
||||
|
||||
public void setHuman(Human human) {
|
||||
this.human = human;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,364 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.test.bytecode.enhancement.lazy.proxy;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.hibernate.Hibernate;
|
||||
import org.hibernate.annotations.DynamicUpdate;
|
||||
import org.hibernate.boot.MetadataSources;
|
||||
import org.hibernate.boot.SessionFactoryBuilder;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
|
||||
import org.hibernate.testing.bytecode.enhancement.EnhancementOptions;
|
||||
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
*/
|
||||
@TestForIssue( jiraKey = "HHH-13640" )
|
||||
@RunWith(BytecodeEnhancerRunner.class)
|
||||
@EnhancementOptions(lazyLoading = true,inlineDirtyChecking = true)
|
||||
public class ProxyInitializeAndUpdateInlineDirtyTrackingDynamicUpdateTest extends BaseNonConfigCoreFunctionalTestCase {
|
||||
@Override
|
||||
protected void configureStandardServiceRegistryBuilder(StandardServiceRegistryBuilder ssrb) {
|
||||
super.configureStandardServiceRegistryBuilder( ssrb );
|
||||
ssrb.applySetting( AvailableSettings.ALLOW_ENHANCEMENT_AS_PROXY, "true" );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configureSessionFactoryBuilder(SessionFactoryBuilder sfb) {
|
||||
super.configureSessionFactoryBuilder( sfb );
|
||||
sfb.applyStatisticsSupport( true );
|
||||
sfb.applySecondLevelCacheSupport( false );
|
||||
sfb.applyQueryCacheSupport( false );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyMetadataSources(MetadataSources sources) {
|
||||
super.applyMetadataSources( sources );
|
||||
sources.addAnnotatedClass( Animal.class );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInitializeWithGetter() {
|
||||
inTransaction(
|
||||
session -> {
|
||||
Animal animal = new Animal();
|
||||
animal.name = "animal";
|
||||
animal.age = 3;
|
||||
animal.sex = "female";
|
||||
animal.color = "green";
|
||||
session.persist( animal );
|
||||
}
|
||||
);
|
||||
|
||||
inTransaction(
|
||||
session -> {
|
||||
Animal animal = session.load( Animal.class, "animal" );
|
||||
assertFalse( Hibernate.isInitialized( animal ) );
|
||||
assertEquals( "female", animal.getSex() );
|
||||
assertTrue( Hibernate.isInitialized( animal ) );
|
||||
assertEquals( 3, animal.getAge() );
|
||||
animal.setSex( "other" );
|
||||
}
|
||||
);
|
||||
|
||||
inSession(
|
||||
session -> {
|
||||
Animal animal = session.get( Animal.class, "animal" );
|
||||
assertTrue( Hibernate.isInitialized( animal ) );
|
||||
assertEquals( "other", animal.getSex() );
|
||||
assertEquals( 3, animal.getAge() );
|
||||
assertEquals( "green", animal.getColor() );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInitializeWithSetter() {
|
||||
inTransaction(
|
||||
session -> {
|
||||
Animal animal = new Animal();
|
||||
animal.name = "animal";
|
||||
animal.age = 3;
|
||||
animal.sex = "female";
|
||||
animal.color = "green";
|
||||
session.persist( animal );
|
||||
}
|
||||
);
|
||||
|
||||
inTransaction(
|
||||
session -> {
|
||||
Animal animal = session.load( Animal.class, "animal" );
|
||||
assertFalse( Hibernate.isInitialized( animal ) );
|
||||
animal.setSex( "other" );
|
||||
// Setting the attribute value should not initialize animal
|
||||
// with dirty-checking and dynamic-update.
|
||||
assertFalse( Hibernate.isInitialized( animal ) );
|
||||
}
|
||||
);
|
||||
|
||||
inSession(
|
||||
session -> {
|
||||
Animal animal = session.get( Animal.class, "animal" );
|
||||
assertTrue( Hibernate.isInitialized( animal ) );
|
||||
assertEquals( "other", animal.getSex() );
|
||||
assertEquals( "green", animal.getColor() );
|
||||
assertEquals( 3, animal.getAge() );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMergeUpdatedOntoUninitialized() {
|
||||
inTransaction(
|
||||
session -> {
|
||||
Animal animal = new Animal();
|
||||
animal.name = "animal";
|
||||
animal.age = 3;
|
||||
animal.sex = "female";
|
||||
session.persist( animal );
|
||||
}
|
||||
);
|
||||
|
||||
final Animal animalInitialized = doInHibernate(
|
||||
this::sessionFactory,
|
||||
session -> {
|
||||
final Animal animal = session.get( Animal.class, "animal" );
|
||||
assertTrue( Hibernate.isInitialized( animal ) );
|
||||
assertEquals( "female", animal.getSex() );
|
||||
assertEquals( 3, animal.getAge() );
|
||||
return animal;
|
||||
}
|
||||
);
|
||||
|
||||
animalInitialized.setAge( 4 );
|
||||
animalInitialized.setSex( "other" );
|
||||
|
||||
inTransaction(
|
||||
session -> {
|
||||
final Animal animal = session.load( Animal.class, "animal" );
|
||||
assertFalse( Hibernate.isInitialized( animal ) );
|
||||
session.merge( animalInitialized );
|
||||
assertTrue( Hibernate.isInitialized( animal ) );
|
||||
assertEquals( 4, animal.getAge() );
|
||||
assertEquals( "other", animal.getSex() );
|
||||
}
|
||||
);
|
||||
|
||||
inTransaction(
|
||||
session -> {
|
||||
final Animal animal = session.get( Animal.class, "animal" );
|
||||
assertTrue( Hibernate.isInitialized( animal ) );
|
||||
assertEquals( "other", animal.getSex() );
|
||||
assertEquals( 4, animal.getAge() );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMergeUpdatedOntoUpdated() {
|
||||
inTransaction(
|
||||
session -> {
|
||||
Animal animal = new Animal();
|
||||
animal.name = "animal";
|
||||
animal.age = 3;
|
||||
animal.sex = "female";
|
||||
session.persist( animal );
|
||||
}
|
||||
);
|
||||
|
||||
final Animal animalInitialized = doInHibernate(
|
||||
this::sessionFactory,
|
||||
session -> {
|
||||
final Animal animal = session.get( Animal.class, "animal" );
|
||||
assertTrue( Hibernate.isInitialized( animal ) );
|
||||
assertEquals( "female", animal.getSex() );
|
||||
assertEquals( 3, animal.getAge() );
|
||||
return animal;
|
||||
}
|
||||
);
|
||||
|
||||
animalInitialized.setAge( 4 );
|
||||
animalInitialized.setSex( "other" );
|
||||
|
||||
inTransaction(
|
||||
session -> {
|
||||
final Animal animal = session.get( Animal.class, "animal" );
|
||||
assertTrue( Hibernate.isInitialized( animal ) );
|
||||
animal.setAge( 5 );
|
||||
animal.setSex( "male" );
|
||||
session.merge( animalInitialized );
|
||||
assertEquals( 4, animal.getAge() );
|
||||
assertEquals( "other", animal.getSex() );
|
||||
}
|
||||
);
|
||||
|
||||
inTransaction(
|
||||
session -> {
|
||||
final Animal animal = session.get( Animal.class, "animal" );
|
||||
assertTrue( Hibernate.isInitialized( animal ) );
|
||||
assertEquals( "other", animal.getSex() );
|
||||
assertEquals( 4, animal.getAge() );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMergeUninitializedOntoUninitialized() {
|
||||
inTransaction(
|
||||
session -> {
|
||||
Animal animal = new Animal();
|
||||
animal.name = "animal";
|
||||
animal.age = 3;
|
||||
animal.sex = "female";
|
||||
session.persist( animal );
|
||||
}
|
||||
);
|
||||
|
||||
final Animal animalUninitialized = doInHibernate(
|
||||
this::sessionFactory,
|
||||
session -> {
|
||||
final Animal animal = session.load( Animal.class, "animal" );
|
||||
assertFalse( Hibernate.isInitialized( animal ) );
|
||||
return animal;
|
||||
}
|
||||
);
|
||||
|
||||
inTransaction(
|
||||
session -> {
|
||||
final Animal animal = session.load( Animal.class, "animal" );
|
||||
assertFalse( Hibernate.isInitialized( animal ) );
|
||||
session.merge( animalUninitialized );
|
||||
assertFalse( Hibernate.isInitialized( animal ) );
|
||||
}
|
||||
);
|
||||
|
||||
inTransaction(
|
||||
session -> {
|
||||
final Animal animal = session.get( Animal.class, "animal" );
|
||||
assertTrue( Hibernate.isInitialized( animal ) );
|
||||
assertEquals( "female", animal.getSex() );
|
||||
assertEquals( 3, animal.getAge() );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMergeUninitializedOntoUpdated() {
|
||||
inTransaction(
|
||||
session -> {
|
||||
Animal animal = new Animal();
|
||||
animal.name = "animal";
|
||||
animal.age = 3;
|
||||
animal.sex = "female";
|
||||
session.persist( animal );
|
||||
}
|
||||
);
|
||||
|
||||
final Animal animalUninitialized = doInHibernate(
|
||||
this::sessionFactory,
|
||||
session -> {
|
||||
final Animal animal = session.load( Animal.class, "animal" );
|
||||
assertFalse( Hibernate.isInitialized( animal ) );
|
||||
return animal;
|
||||
}
|
||||
);
|
||||
|
||||
inTransaction(
|
||||
session -> {
|
||||
final Animal animal = session.get( Animal.class, "animal" );
|
||||
assertTrue( Hibernate.isInitialized( animal ) );
|
||||
animal.setSex( "other" );
|
||||
animal.setAge( 4 );
|
||||
session.merge( animalUninitialized );
|
||||
assertTrue( Hibernate.isInitialized( animal ) );
|
||||
assertEquals( "other", animal.getSex() );
|
||||
assertEquals( 4, animal.getAge() );
|
||||
}
|
||||
);
|
||||
|
||||
inTransaction(
|
||||
session -> {
|
||||
final Animal animal = session.get( Animal.class, "animal" );
|
||||
assertTrue( Hibernate.isInitialized( animal ) );
|
||||
assertEquals( "other", animal.getSex() );
|
||||
assertEquals( 4, animal.getAge() );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanUpTestData() {
|
||||
inTransaction(
|
||||
session -> {
|
||||
session.createQuery( "delete from Animal" ).executeUpdate();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Entity(name = "Animal")
|
||||
@Table(name = "Animal")
|
||||
@DynamicUpdate
|
||||
public static class Animal {
|
||||
|
||||
@Id
|
||||
private String name;
|
||||
|
||||
private int age;
|
||||
|
||||
private String sex;
|
||||
|
||||
private String color;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
protected void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public String getSex() {
|
||||
return sex;
|
||||
}
|
||||
|
||||
public void setSex(String sex) {
|
||||
this.sex = sex;
|
||||
}
|
||||
|
||||
public String getColor() {
|
||||
return color;
|
||||
}
|
||||
|
||||
public void setColor(String color) {
|
||||
this.color = color;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,361 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.test.bytecode.enhancement.lazy.proxy;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.hibernate.Hibernate;
|
||||
import org.hibernate.boot.MetadataSources;
|
||||
import org.hibernate.boot.SessionFactoryBuilder;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
|
||||
import org.hibernate.testing.bytecode.enhancement.EnhancementOptions;
|
||||
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
*/
|
||||
@TestForIssue( jiraKey = "HHH-13640" )
|
||||
@RunWith(BytecodeEnhancerRunner.class)
|
||||
@EnhancementOptions(lazyLoading = true,inlineDirtyChecking = true)
|
||||
public class ProxyInitializeAndUpdateInlineDirtyTrackingTest extends BaseNonConfigCoreFunctionalTestCase {
|
||||
@Override
|
||||
protected void configureStandardServiceRegistryBuilder(StandardServiceRegistryBuilder ssrb) {
|
||||
super.configureStandardServiceRegistryBuilder( ssrb );
|
||||
ssrb.applySetting( AvailableSettings.ALLOW_ENHANCEMENT_AS_PROXY, "true" );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configureSessionFactoryBuilder(SessionFactoryBuilder sfb) {
|
||||
super.configureSessionFactoryBuilder( sfb );
|
||||
sfb.applyStatisticsSupport( true );
|
||||
sfb.applySecondLevelCacheSupport( false );
|
||||
sfb.applyQueryCacheSupport( false );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyMetadataSources(MetadataSources sources) {
|
||||
super.applyMetadataSources( sources );
|
||||
sources.addAnnotatedClass( Animal.class );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInitializeWithGetter() {
|
||||
inTransaction(
|
||||
session -> {
|
||||
Animal animal = new Animal();
|
||||
animal.name = "animal";
|
||||
animal.age = 3;
|
||||
animal.sex = "female";
|
||||
animal.color = "green";
|
||||
session.persist( animal );
|
||||
}
|
||||
);
|
||||
|
||||
inTransaction(
|
||||
session -> {
|
||||
Animal animal = session.load( Animal.class, "animal" );
|
||||
assertFalse( Hibernate.isInitialized( animal ) );
|
||||
assertEquals( "female", animal.getSex() );
|
||||
assertTrue( Hibernate.isInitialized( animal ) );
|
||||
assertEquals( 3, animal.getAge() );
|
||||
animal.setSex( "other" );
|
||||
}
|
||||
);
|
||||
|
||||
inSession(
|
||||
session -> {
|
||||
Animal animal = session.get( Animal.class, "animal" );
|
||||
assertTrue( Hibernate.isInitialized( animal ) );
|
||||
assertEquals( "other", animal.getSex() );
|
||||
assertEquals( 3, animal.getAge() );
|
||||
assertEquals( "green", animal.getColor() );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInitializeWithSetter() {
|
||||
inTransaction(
|
||||
session -> {
|
||||
Animal animal = new Animal();
|
||||
animal.name = "animal";
|
||||
animal.age = 3;
|
||||
animal.sex = "female";
|
||||
animal.color = "green";
|
||||
session.persist( animal );
|
||||
}
|
||||
);
|
||||
|
||||
inTransaction(
|
||||
session -> {
|
||||
Animal animal = session.load( Animal.class, "animal" );
|
||||
assertFalse( Hibernate.isInitialized( animal ) );
|
||||
animal.setSex( "other" );
|
||||
// Setting the attribute value should have initialized animal.
|
||||
assertTrue( Hibernate.isInitialized( animal ) );
|
||||
}
|
||||
);
|
||||
|
||||
inSession(
|
||||
session -> {
|
||||
Animal animal = session.get( Animal.class, "animal" );
|
||||
assertTrue( Hibernate.isInitialized( animal ) );
|
||||
assertEquals( "other", animal.getSex() );
|
||||
assertEquals( "green", animal.getColor() );
|
||||
assertEquals( 3, animal.getAge() );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMergeUpdatedOntoUninitialized() {
|
||||
inTransaction(
|
||||
session -> {
|
||||
Animal animal = new Animal();
|
||||
animal.name = "animal";
|
||||
animal.age = 3;
|
||||
animal.sex = "female";
|
||||
session.persist( animal );
|
||||
}
|
||||
);
|
||||
|
||||
final Animal animalInitialized = doInHibernate(
|
||||
this::sessionFactory,
|
||||
session -> {
|
||||
final Animal animal = session.get( Animal.class, "animal" );
|
||||
assertTrue( Hibernate.isInitialized( animal ) );
|
||||
assertEquals( "female", animal.getSex() );
|
||||
assertEquals( 3, animal.getAge() );
|
||||
return animal;
|
||||
}
|
||||
);
|
||||
|
||||
animalInitialized.setAge( 4 );
|
||||
animalInitialized.setSex( "other" );
|
||||
|
||||
inTransaction(
|
||||
session -> {
|
||||
final Animal animal = session.load( Animal.class, "animal" );
|
||||
assertFalse( Hibernate.isInitialized( animal ) );
|
||||
session.merge( animalInitialized );
|
||||
assertTrue( Hibernate.isInitialized( animal ) );
|
||||
assertEquals( 4, animal.getAge() );
|
||||
assertEquals( "other", animal.getSex() );
|
||||
}
|
||||
);
|
||||
|
||||
inTransaction(
|
||||
session -> {
|
||||
final Animal animal = session.get( Animal.class, "animal" );
|
||||
assertTrue( Hibernate.isInitialized( animal ) );
|
||||
assertEquals( "other", animal.getSex() );
|
||||
assertEquals( 4, animal.getAge() );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMergeUpdatedOntoUpdated() {
|
||||
inTransaction(
|
||||
session -> {
|
||||
Animal animal = new Animal();
|
||||
animal.name = "animal";
|
||||
animal.age = 3;
|
||||
animal.sex = "female";
|
||||
session.persist( animal );
|
||||
}
|
||||
);
|
||||
|
||||
final Animal animalInitialized = doInHibernate(
|
||||
this::sessionFactory,
|
||||
session -> {
|
||||
final Animal animal = session.get( Animal.class, "animal" );
|
||||
assertTrue( Hibernate.isInitialized( animal ) );
|
||||
assertEquals( "female", animal.getSex() );
|
||||
assertEquals( 3, animal.getAge() );
|
||||
return animal;
|
||||
}
|
||||
);
|
||||
|
||||
animalInitialized.setAge( 4 );
|
||||
animalInitialized.setSex( "other" );
|
||||
|
||||
inTransaction(
|
||||
session -> {
|
||||
final Animal animal = session.get( Animal.class, "animal" );
|
||||
assertTrue( Hibernate.isInitialized( animal ) );
|
||||
animal.setAge( 5 );
|
||||
animal.setSex( "male" );
|
||||
session.merge( animalInitialized );
|
||||
assertEquals( 4, animal.getAge() );
|
||||
assertEquals( "other", animal.getSex() );
|
||||
}
|
||||
);
|
||||
|
||||
inTransaction(
|
||||
session -> {
|
||||
final Animal animal = session.get( Animal.class, "animal" );
|
||||
assertTrue( Hibernate.isInitialized( animal ) );
|
||||
assertEquals( "other", animal.getSex() );
|
||||
assertEquals( 4, animal.getAge() );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMergeUninitializedOntoUninitialized() {
|
||||
inTransaction(
|
||||
session -> {
|
||||
Animal animal = new Animal();
|
||||
animal.name = "animal";
|
||||
animal.age = 3;
|
||||
animal.sex = "female";
|
||||
session.persist( animal );
|
||||
}
|
||||
);
|
||||
|
||||
final Animal animalUninitialized = doInHibernate(
|
||||
this::sessionFactory,
|
||||
session -> {
|
||||
final Animal animal = session.load( Animal.class, "animal" );
|
||||
assertFalse( Hibernate.isInitialized( animal ) );
|
||||
return animal;
|
||||
}
|
||||
);
|
||||
|
||||
inTransaction(
|
||||
session -> {
|
||||
final Animal animal = session.load( Animal.class, "animal" );
|
||||
assertFalse( Hibernate.isInitialized( animal ) );
|
||||
session.merge( animalUninitialized );
|
||||
assertFalse( Hibernate.isInitialized( animal ) );
|
||||
}
|
||||
);
|
||||
|
||||
inTransaction(
|
||||
session -> {
|
||||
final Animal animal = session.get( Animal.class, "animal" );
|
||||
assertTrue( Hibernate.isInitialized( animal ) );
|
||||
assertEquals( "female", animal.getSex() );
|
||||
assertEquals( 3, animal.getAge() );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMergeUninitializedOntoUpdated() {
|
||||
inTransaction(
|
||||
session -> {
|
||||
Animal animal = new Animal();
|
||||
animal.name = "animal";
|
||||
animal.age = 3;
|
||||
animal.sex = "female";
|
||||
session.persist( animal );
|
||||
}
|
||||
);
|
||||
|
||||
final Animal animalUninitialized = doInHibernate(
|
||||
this::sessionFactory,
|
||||
session -> {
|
||||
final Animal animal = session.load( Animal.class, "animal" );
|
||||
assertFalse( Hibernate.isInitialized( animal ) );
|
||||
return animal;
|
||||
}
|
||||
);
|
||||
|
||||
inTransaction(
|
||||
session -> {
|
||||
final Animal animal = session.get( Animal.class, "animal" );
|
||||
assertTrue( Hibernate.isInitialized( animal ) );
|
||||
animal.setSex( "other" );
|
||||
animal.setAge( 4 );
|
||||
session.merge( animalUninitialized );
|
||||
assertTrue( Hibernate.isInitialized( animal ) );
|
||||
assertEquals( "other", animal.getSex() );
|
||||
assertEquals( 4, animal.getAge() );
|
||||
}
|
||||
);
|
||||
|
||||
inTransaction(
|
||||
session -> {
|
||||
final Animal animal = session.get( Animal.class, "animal" );
|
||||
assertTrue( Hibernate.isInitialized( animal ) );
|
||||
assertEquals( "other", animal.getSex() );
|
||||
assertEquals( 4, animal.getAge() );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanUpTestData() {
|
||||
inTransaction(
|
||||
session -> {
|
||||
session.createQuery( "delete from Animal" ).executeUpdate();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Entity(name = "Animal")
|
||||
@Table(name = "Animal")
|
||||
public static class Animal {
|
||||
|
||||
@Id
|
||||
private String name;
|
||||
|
||||
private int age;
|
||||
|
||||
private String sex;
|
||||
|
||||
private String color;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
protected void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public String getSex() {
|
||||
return sex;
|
||||
}
|
||||
|
||||
public void setSex(String sex) {
|
||||
this.sex = sex;
|
||||
}
|
||||
|
||||
public String getColor() {
|
||||
return color;
|
||||
}
|
||||
|
||||
public void setColor(String color) {
|
||||
this.color = color;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,361 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.test.bytecode.enhancement.lazy.proxy;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.hibernate.Hibernate;
|
||||
import org.hibernate.boot.MetadataSources;
|
||||
import org.hibernate.boot.SessionFactoryBuilder;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
|
||||
import org.hibernate.testing.bytecode.enhancement.EnhancementOptions;
|
||||
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
*/
|
||||
@TestForIssue( jiraKey = "HHH-13640" )
|
||||
@RunWith(BytecodeEnhancerRunner.class)
|
||||
@EnhancementOptions(lazyLoading = true)
|
||||
public class ProxyInitializeAndUpdateTest extends BaseNonConfigCoreFunctionalTestCase {
|
||||
@Override
|
||||
protected void configureStandardServiceRegistryBuilder(StandardServiceRegistryBuilder ssrb) {
|
||||
super.configureStandardServiceRegistryBuilder( ssrb );
|
||||
ssrb.applySetting( AvailableSettings.ALLOW_ENHANCEMENT_AS_PROXY, "true" );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configureSessionFactoryBuilder(SessionFactoryBuilder sfb) {
|
||||
super.configureSessionFactoryBuilder( sfb );
|
||||
sfb.applyStatisticsSupport( true );
|
||||
sfb.applySecondLevelCacheSupport( false );
|
||||
sfb.applyQueryCacheSupport( false );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyMetadataSources(MetadataSources sources) {
|
||||
super.applyMetadataSources( sources );
|
||||
sources.addAnnotatedClass( Animal.class );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInitializeWithGetter() {
|
||||
inTransaction(
|
||||
session -> {
|
||||
Animal animal = new Animal();
|
||||
animal.name = "animal";
|
||||
animal.age = 3;
|
||||
animal.sex = "female";
|
||||
animal.color = "green";
|
||||
session.persist( animal );
|
||||
}
|
||||
);
|
||||
|
||||
inTransaction(
|
||||
session -> {
|
||||
Animal animal = session.load( Animal.class, "animal" );
|
||||
assertFalse( Hibernate.isInitialized( animal ) );
|
||||
assertEquals( "female", animal.getSex() );
|
||||
assertTrue( Hibernate.isInitialized( animal ) );
|
||||
assertEquals( 3, animal.getAge() );
|
||||
animal.setSex( "other" );
|
||||
}
|
||||
);
|
||||
|
||||
inSession(
|
||||
session -> {
|
||||
Animal animal = session.get( Animal.class, "animal" );
|
||||
assertTrue( Hibernate.isInitialized( animal ) );
|
||||
assertEquals( "other", animal.getSex() );
|
||||
assertEquals( 3, animal.getAge() );
|
||||
assertEquals( "green", animal.getColor() );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInitializeWithSetter() {
|
||||
inTransaction(
|
||||
session -> {
|
||||
Animal animal = new Animal();
|
||||
animal.name = "animal";
|
||||
animal.age = 3;
|
||||
animal.sex = "female";
|
||||
animal.color = "green";
|
||||
session.persist( animal );
|
||||
}
|
||||
);
|
||||
|
||||
inTransaction(
|
||||
session -> {
|
||||
Animal animal = session.load( Animal.class, "animal" );
|
||||
assertFalse( Hibernate.isInitialized( animal ) );
|
||||
animal.setSex( "other" );
|
||||
// Setting the attribute value should have initialized animal.
|
||||
assertTrue( Hibernate.isInitialized( animal ) );
|
||||
}
|
||||
);
|
||||
|
||||
inSession(
|
||||
session -> {
|
||||
Animal animal = session.get( Animal.class, "animal" );
|
||||
assertTrue( Hibernate.isInitialized( animal ) );
|
||||
assertEquals( "other", animal.getSex() );
|
||||
assertEquals( "green", animal.getColor() );
|
||||
assertEquals( 3, animal.getAge() );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMergeUpdatedOntoUninitialized() {
|
||||
inTransaction(
|
||||
session -> {
|
||||
Animal animal = new Animal();
|
||||
animal.name = "animal";
|
||||
animal.age = 3;
|
||||
animal.sex = "female";
|
||||
session.persist( animal );
|
||||
}
|
||||
);
|
||||
|
||||
final Animal animalInitialized = doInHibernate(
|
||||
this::sessionFactory,
|
||||
session -> {
|
||||
final Animal animal = session.get( Animal.class, "animal" );
|
||||
assertTrue( Hibernate.isInitialized( animal ) );
|
||||
assertEquals( "female", animal.getSex() );
|
||||
assertEquals( 3, animal.getAge() );
|
||||
return animal;
|
||||
}
|
||||
);
|
||||
|
||||
animalInitialized.setAge( 4 );
|
||||
animalInitialized.setSex( "other" );
|
||||
|
||||
inTransaction(
|
||||
session -> {
|
||||
final Animal animal = session.load( Animal.class, "animal" );
|
||||
assertFalse( Hibernate.isInitialized( animal ) );
|
||||
session.merge( animalInitialized );
|
||||
assertTrue( Hibernate.isInitialized( animal ) );
|
||||
assertEquals( 4, animal.getAge() );
|
||||
assertEquals( "other", animal.getSex() );
|
||||
}
|
||||
);
|
||||
|
||||
inTransaction(
|
||||
session -> {
|
||||
final Animal animal = session.get( Animal.class, "animal" );
|
||||
assertTrue( Hibernate.isInitialized( animal ) );
|
||||
assertEquals( "other", animal.getSex() );
|
||||
assertEquals( 4, animal.getAge() );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMergeUpdatedOntoUpdated() {
|
||||
inTransaction(
|
||||
session -> {
|
||||
Animal animal = new Animal();
|
||||
animal.name = "animal";
|
||||
animal.age = 3;
|
||||
animal.sex = "female";
|
||||
session.persist( animal );
|
||||
}
|
||||
);
|
||||
|
||||
final Animal animalInitialized = doInHibernate(
|
||||
this::sessionFactory,
|
||||
session -> {
|
||||
final Animal animal = session.get( Animal.class, "animal" );
|
||||
assertTrue( Hibernate.isInitialized( animal ) );
|
||||
assertEquals( "female", animal.getSex() );
|
||||
assertEquals( 3, animal.getAge() );
|
||||
return animal;
|
||||
}
|
||||
);
|
||||
|
||||
animalInitialized.setAge( 4 );
|
||||
animalInitialized.setSex( "other" );
|
||||
|
||||
inTransaction(
|
||||
session -> {
|
||||
final Animal animal = session.get( Animal.class, "animal" );
|
||||
assertTrue( Hibernate.isInitialized( animal ) );
|
||||
animal.setAge( 5 );
|
||||
animal.setSex( "male" );
|
||||
session.merge( animalInitialized );
|
||||
assertEquals( 4, animal.getAge() );
|
||||
assertEquals( "other", animal.getSex() );
|
||||
}
|
||||
);
|
||||
|
||||
inTransaction(
|
||||
session -> {
|
||||
final Animal animal = session.get( Animal.class, "animal" );
|
||||
assertTrue( Hibernate.isInitialized( animal ) );
|
||||
assertEquals( "other", animal.getSex() );
|
||||
assertEquals( 4, animal.getAge() );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMergeUninitializedOntoUninitialized() {
|
||||
inTransaction(
|
||||
session -> {
|
||||
Animal animal = new Animal();
|
||||
animal.name = "animal";
|
||||
animal.age = 3;
|
||||
animal.sex = "female";
|
||||
session.persist( animal );
|
||||
}
|
||||
);
|
||||
|
||||
final Animal animalUninitialized = doInHibernate(
|
||||
this::sessionFactory,
|
||||
session -> {
|
||||
final Animal animal = session.load( Animal.class, "animal" );
|
||||
assertFalse( Hibernate.isInitialized( animal ) );
|
||||
return animal;
|
||||
}
|
||||
);
|
||||
|
||||
inTransaction(
|
||||
session -> {
|
||||
final Animal animal = session.load( Animal.class, "animal" );
|
||||
assertFalse( Hibernate.isInitialized( animal ) );
|
||||
session.merge( animalUninitialized );
|
||||
assertFalse( Hibernate.isInitialized( animal ) );
|
||||
}
|
||||
);
|
||||
|
||||
inTransaction(
|
||||
session -> {
|
||||
final Animal animal = session.get( Animal.class, "animal" );
|
||||
assertTrue( Hibernate.isInitialized( animal ) );
|
||||
assertEquals( "female", animal.getSex() );
|
||||
assertEquals( 3, animal.getAge() );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMergeUninitializedOntoUpdated() {
|
||||
inTransaction(
|
||||
session -> {
|
||||
Animal animal = new Animal();
|
||||
animal.name = "animal";
|
||||
animal.age = 3;
|
||||
animal.sex = "female";
|
||||
session.persist( animal );
|
||||
}
|
||||
);
|
||||
|
||||
final Animal animalUninitialized = doInHibernate(
|
||||
this::sessionFactory,
|
||||
session -> {
|
||||
final Animal animal = session.load( Animal.class, "animal" );
|
||||
assertFalse( Hibernate.isInitialized( animal ) );
|
||||
return animal;
|
||||
}
|
||||
);
|
||||
|
||||
inTransaction(
|
||||
session -> {
|
||||
final Animal animal = session.get( Animal.class, "animal" );
|
||||
assertTrue( Hibernate.isInitialized( animal ) );
|
||||
animal.setSex( "other" );
|
||||
animal.setAge( 4 );
|
||||
session.merge( animalUninitialized );
|
||||
assertTrue( Hibernate.isInitialized( animal ) );
|
||||
assertEquals( "other", animal.getSex() );
|
||||
assertEquals( 4, animal.getAge() );
|
||||
}
|
||||
);
|
||||
|
||||
inTransaction(
|
||||
session -> {
|
||||
final Animal animal = session.get( Animal.class, "animal" );
|
||||
assertTrue( Hibernate.isInitialized( animal ) );
|
||||
assertEquals( "other", animal.getSex() );
|
||||
assertEquals( 4, animal.getAge() );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanUpTestData() {
|
||||
inTransaction(
|
||||
session -> {
|
||||
session.createQuery( "delete from Animal" ).executeUpdate();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Entity(name = "Animal")
|
||||
@Table(name = "Animal")
|
||||
public static class Animal {
|
||||
|
||||
@Id
|
||||
private String name;
|
||||
|
||||
private int age;
|
||||
|
||||
private String sex;
|
||||
|
||||
private String color;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
protected void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public String getSex() {
|
||||
return sex;
|
||||
}
|
||||
|
||||
public void setSex(String sex) {
|
||||
this.sex = sex;
|
||||
}
|
||||
|
||||
public String getColor() {
|
||||
return color;
|
||||
}
|
||||
|
||||
public void setColor(String color) {
|
||||
this.color = color;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -25,12 +25,9 @@ import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
|||
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
|
||||
import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementAsProxyLazinessInterceptor;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.collection.spi.PersistentCollection;
|
||||
import org.hibernate.engine.spi.CollectionKey;
|
||||
import org.hibernate.engine.spi.EntityEntry;
|
||||
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
|
||||
import org.hibernate.engine.spi.PersistentAttributeInterceptor;
|
||||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.stat.Statistics;
|
||||
|
||||
|
@ -200,8 +197,12 @@ public class SimpleUpdateTestWithLazyLoading extends BaseNonConfigCoreFunctional
|
|||
|
||||
doInHibernate( this::sessionFactory, s -> {
|
||||
Child loadedChild = s.load( Child.class, lastChildID );
|
||||
assertThat( Hibernate.isInitialized( loadedChild ), is( false ) );
|
||||
assertThat( loadedChild.getName(), is( updatedName ) );
|
||||
assertThat( Hibernate.isInitialized( loadedChild ), is( true ) );
|
||||
assertThat( Hibernate.isInitialized( loadedChild.getParent() ), is( false ) );
|
||||
assertThat( loadedChild.getParent().getName(), is( parentName ) );
|
||||
assertThat( Hibernate.isInitialized( loadedChild.getParent() ), is( true ) );
|
||||
} );
|
||||
}
|
||||
|
||||
|
@ -216,7 +217,9 @@ public class SimpleUpdateTestWithLazyLoading extends BaseNonConfigCoreFunctional
|
|||
assertEquals( 0, stats.getPrepareStatementCount() );
|
||||
Person relative = new Person();
|
||||
relative.setName( "Luis" );
|
||||
assertThat( Hibernate.isInitialized( loadedChild ), is( false ) );
|
||||
loadedChild.addRelative( relative );
|
||||
assertThat( Hibernate.isInitialized( loadedChild ), is( true ) );
|
||||
assertEquals( 2, stats.getPrepareStatementCount() );
|
||||
s.persist( relative );
|
||||
} );
|
||||
|
|
|
@ -115,13 +115,13 @@ public class SimpleUpdateTestWithLazyLoadingAndInlineDirtyTracking extends BaseN
|
|||
MatcherAssert.assertThat( interceptor, instanceOf( EnhancementAsProxyLazinessInterceptor.class ) );
|
||||
|
||||
loadedChild.setName( updatedName );
|
||||
assertEquals( 0, stats.getPrepareStatementCount() );
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
assertThat( loadedChild.getName(), is( updatedName ) );
|
||||
assertEquals( 0, stats.getPrepareStatementCount() );
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
} );
|
||||
|
||||
// the UPDATE
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
assertEquals( 2, stats.getPrepareStatementCount() );
|
||||
|
||||
doInHibernate( this::sessionFactory, s -> {
|
||||
Child loadedChild = s.load( Child.class, lastChildID );
|
||||
|
@ -143,11 +143,11 @@ public class SimpleUpdateTestWithLazyLoadingAndInlineDirtyTracking extends BaseN
|
|||
Parent parent = new Parent();
|
||||
parent.setName( parentName );
|
||||
|
||||
assertEquals( 0, stats.getPrepareStatementCount() );
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
loadedChild.setParent( parent );
|
||||
assertEquals( 0, stats.getPrepareStatementCount() );
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
assertThat( loadedChild.getParent().getName(), is( parentName ) );
|
||||
assertEquals( 0, stats.getPrepareStatementCount() );
|
||||
assertEquals( 1, stats.getPrepareStatementCount() );
|
||||
s.save( parent );
|
||||
} );
|
||||
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
<!--
|
||||
~ Hibernate, Relational Persistence for Idiomatic Java
|
||||
~
|
||||
~ License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
~ See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
-->
|
||||
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
|
||||
<hibernate-configuration>
|
||||
<session-factory>
|
||||
<property name="hibernate.dialect">org.hibernate.orm.test.bootstrap.jpa.PersistenceUnitOverridesTests$PersistenceUnitDialect</property>
|
||||
<mapping class="org.hibernate.orm.test.bootstrap.jpa.PersistenceUnitOverridesTests$MappedEntity"/>
|
||||
<class-cache class="org.hibernate.orm.test.bootstrap.jpa.PersistenceUnitOverridesTests$MappedEntity" usage="read-only"/>
|
||||
</session-factory>
|
||||
</hibernate-configuration>
|
|
@ -115,8 +115,12 @@ public class ClassesAuditingData {
|
|||
|
||||
if ( propertyAuditingData.getMapKeyEnumType() != null ) {
|
||||
final String referencedEntityName = MappingTools.getReferencedEntityName( property.getValue() );
|
||||
final ClassAuditingData referencedAuditingData = entityNameToAuditingData.get( referencedEntityName );
|
||||
addMapEnumeratedKey( property.getValue(), property.getPropertyAccessorName(), referencedAuditingData );
|
||||
if ( referencedEntityName != null ) {
|
||||
// If no entity could be determined, this means the enum type isn't an entity mapping and instead is one
|
||||
// to a basic type. In this use case, there is nothing special to do.
|
||||
final ClassAuditingData referencedAuditingData = entityNameToAuditingData.get( referencedEntityName );
|
||||
addMapEnumeratedKey( property.getValue(), property.getPropertyAccessorName(), referencedAuditingData );
|
||||
}
|
||||
}
|
||||
|
||||
// HHH-9108
|
||||
|
|
|
@ -526,8 +526,9 @@ public final class CollectionMetadataGenerator {
|
|||
final IndexedCollection indexedValue = (IndexedCollection) propertyValue;
|
||||
final String mapKey = propertyAuditingData.getMapKey();
|
||||
final EnumType mapKeyEnumType = propertyAuditingData.getMapKeyEnumType();
|
||||
if ( mapKey == null && mapKeyEnumType == null ) {
|
||||
// This entity doesn't specify a javax.persistence.MapKey. Mapping it to the middle entity.
|
||||
if ( ( mapKey == null && mapKeyEnumType == null ) || ( mapKeyEnumType != null && referencedEntityName == null ) ) {
|
||||
// This entity doesn't specify a javax.persistence.MapKey or there is a MapKeyEnumerated but its a non-entity type.
|
||||
// Mapping it to the middle entity.
|
||||
return addValueToMiddleTable(
|
||||
indexedValue.getIndex(),
|
||||
middleEntityXml,
|
||||
|
|
|
@ -0,0 +1,156 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.envers.test.integration.collection.mapkey;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.persistence.CollectionTable;
|
||||
import javax.persistence.ElementCollection;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.MapKeyColumn;
|
||||
import javax.persistence.MapKeyEnumerated;
|
||||
|
||||
import org.hibernate.envers.Audited;
|
||||
import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase;
|
||||
import org.hibernate.envers.test.Priority;
|
||||
import org.hibernate.envers.test.tools.TestTools;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
|
||||
import static org.hibernate.envers.test.tools.TestTools.checkCollection;
|
||||
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* @author Chris Cranford
|
||||
*/
|
||||
@TestForIssue(jiraKey = "HHH-13655")
|
||||
public class MapKeyEnumeratedNonEntityTest extends BaseEnversJPAFunctionalTestCase {
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class<?>[] { TestEntity.class };
|
||||
}
|
||||
|
||||
@Test
|
||||
@Priority(10)
|
||||
public void initData() {
|
||||
// Revision 1
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
|
||||
final TestEntity test = new TestEntity();
|
||||
test.setId( 1 );
|
||||
test.addMapKeyAssociation( TestEnum.ONE, 1 );
|
||||
|
||||
entityManager.persist( test );
|
||||
} );
|
||||
|
||||
// Revision 2
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
final TestEntity test = entityManager.find( TestEntity.class, 1 );
|
||||
test.addMapKeyAssociation( TestEnum.TWO, 2 );
|
||||
|
||||
entityManager.merge( test );
|
||||
} );
|
||||
|
||||
// Revision 3
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
final TestEntity test = entityManager.find( TestEntity.class, 1 );
|
||||
test.removeMapKeyAssociation( TestEnum.ONE );
|
||||
entityManager.merge( test );
|
||||
} );
|
||||
|
||||
// Revision 4
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
final TestEntity test = entityManager.find( TestEntity.class, 1 );
|
||||
test.removeMapKeyAssociation( TestEnum.TWO );
|
||||
entityManager.merge( test );
|
||||
} );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRevisionNumberHistory() {
|
||||
assertEquals( Arrays.asList( 1, 2, 3, 4 ), getAuditReader().getRevisions( TestEntity.class, 1 ) );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRevisionHistory() {
|
||||
|
||||
final TestEntity rev1 = getAuditReader().find( TestEntity.class, 1, 1 );
|
||||
assertEquals( 1, rev1.getMapEnumMap().size() );
|
||||
assertEquals( TestEnum.ONE, rev1.getMapEnumMap().keySet().iterator().next() );
|
||||
|
||||
final TestEntity rev2 = getAuditReader().find( TestEntity.class, 1, 2 );
|
||||
assertEquals( 2, rev2.getMapEnumMap().size() );
|
||||
assertEquals( TestTools.makeSet( TestEnum.ONE, TestEnum.TWO ), rev2.getMapEnumMap().keySet() );
|
||||
checkCollection( rev2.getMapEnumMap().values(), 1, 2 );
|
||||
|
||||
final TestEntity rev3 = getAuditReader().find( TestEntity.class, 1, 3 );
|
||||
assertEquals( 1, rev3.getMapEnumMap().size() );
|
||||
assertEquals( TestTools.makeSet( TestEnum.TWO ), rev3.getMapEnumMap().keySet() );
|
||||
checkCollection( rev2.getMapEnumMap().values(), 2 );
|
||||
|
||||
final TestEntity rev4 = getAuditReader().find( TestEntity.class, 1, 4 );
|
||||
assertEquals( 0, rev4.getMapEnumMap().size() );
|
||||
}
|
||||
|
||||
public enum TestEnum {
|
||||
ONE,
|
||||
TWO
|
||||
}
|
||||
|
||||
@Entity(name = "TestEntity")
|
||||
@Audited
|
||||
public static class TestEntity {
|
||||
@Id
|
||||
private Integer id;
|
||||
|
||||
@MapKeyEnumerated(EnumType.STRING)
|
||||
@ElementCollection
|
||||
@CollectionTable(name = "test_Entity_enum_items")
|
||||
@MapKeyColumn(name = "type", length = 20, nullable = false)
|
||||
private Map<TestEnum, Integer> mapEnumMap = new HashMap<>();
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Map<TestEnum, Integer> getMapEnumMap() {
|
||||
return mapEnumMap;
|
||||
}
|
||||
|
||||
public void setMapEnumMap(Map<TestEnum, Integer> mapEnumMap) {
|
||||
this.mapEnumMap = mapEnumMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TestEntity{" +
|
||||
"id=" + id +
|
||||
", mapEnumMap=" + mapEnumMap +
|
||||
'}';
|
||||
}
|
||||
|
||||
public void addMapKeyAssociation(TestEnum key, Integer value) {
|
||||
mapEnumMap.put( key, value );
|
||||
}
|
||||
|
||||
public Integer removeMapKeyAssociation(TestEnum key) {
|
||||
final Integer value = mapEnumMap.get( key );
|
||||
mapEnumMap.remove( key );
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,7 +4,7 @@
|
|||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.orm.test.bootstrap;
|
||||
package org.hibernate.testing.jdbc;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.sql.Connection;
|
||||
|
@ -24,7 +24,7 @@ public class DataSourceStub implements DataSource {
|
|||
private final DriverManagerConnectionProviderImpl connectionProvider;
|
||||
private PrintWriter printWriter;
|
||||
|
||||
DataSourceStub(String id) {
|
||||
public DataSourceStub(String id) {
|
||||
this.id = id;
|
||||
connectionProvider = new DriverManagerConnectionProviderImpl();
|
||||
connectionProvider.configure( ConnectionProviderBuilder.getConnectionProviderProperties() );
|
Loading…
Reference in New Issue