Merge remote-tracking branch 'upstream5/master' into wip/6.0_merge_14
This commit is contained in:
commit
f1bf079122
|
@ -17,7 +17,7 @@ buildscript {
|
||||||
classpath 'org.hibernate.build.gradle:gradle-xjc-plugin:1.0.2.Final'
|
classpath 'org.hibernate.build.gradle:gradle-xjc-plugin:1.0.2.Final'
|
||||||
classpath 'gradle.plugin.com.github.lburgazzoli:gradle-karaf-plugin:0.1.1'
|
classpath 'gradle.plugin.com.github.lburgazzoli:gradle-karaf-plugin:0.1.1'
|
||||||
classpath 'org.asciidoctor:asciidoctor-gradle-plugin:1.5.7'
|
classpath 'org.asciidoctor:asciidoctor-gradle-plugin:1.5.7'
|
||||||
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.3'
|
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.4'
|
||||||
classpath 'de.thetaphi:forbiddenapis:2.5'
|
classpath 'de.thetaphi:forbiddenapis:2.5'
|
||||||
classpath 'org.junit.platform:junit-platform-gradle-plugin:1.0.1'
|
classpath 'org.junit.platform:junit-platform-gradle-plugin:1.0.1'
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,36 @@ Hibernate 5 Changelog
|
||||||
|
|
||||||
Note: Please refer to JIRA to learn more about each issue.
|
Note: Please refer to JIRA to learn more about each issue.
|
||||||
|
|
||||||
|
Changes in 5.4.9.Final (November 14, 2019)
|
||||||
|
------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
https://hibernate.atlassian.net/projects/HHH/versions/31806/tab/release-report-done
|
||||||
|
|
||||||
|
** Bug
|
||||||
|
* [HHH-12030] - Symbol$TypeVariableSymbol cannot be cast to TypeElement
|
||||||
|
* [HHH-13307] - On release of batch it still contained JDBC statements using JTA
|
||||||
|
* [HHH-13433] - EntityManager.find() should only check for roll-back-only condition if there is an active JTA transaction, otherwise ORM should throw convert( e, lockOptions )
|
||||||
|
* [HHH-13614] - Allow the IntegratorProvider to be supplied via its FQN in the JPA persistence.xml
|
||||||
|
* [HHH-13670] - Missing from clause in query with joined inheritance, regression in 5.4.5
|
||||||
|
* [HHH-13687] - TenantSchemaResolver not called in integration test after upgrade from 5.4.4 to >=5.4.5
|
||||||
|
* [HHH-13690] - Multi-tenancy supporting session factories can not be created
|
||||||
|
* [HHH-13698] - Hibernate does not recognize MySQL 8 error code 3572 as PessimisticLockException
|
||||||
|
* [HHH-13700] - Configuration property CONNECTION_PROVIDER_DISABLES_AUTOCOMMIT should not be passed to the JDBC connection properties
|
||||||
|
* [HHH-13705] - Enhancement as Proxy with inline dirty checking - flush of an @ManyToOne with an Embedded value having not null properties causes PropertyValueException
|
||||||
|
* [HHH-13710] - Wrong tenant-identifier in Envers temporary session
|
||||||
|
* [HHH-13712] - inheritance - select count query is not working with inheritance
|
||||||
|
* [HHH-13727] - h2 database with DATABASE_TO_UPPER=false throws org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "sequences" not found
|
||||||
|
|
||||||
|
** Task
|
||||||
|
* [HHH-13730] - Upgrade to Classmate 1.4.0
|
||||||
|
* [HHH-13731] - Upgrade to Classmate 1.5.1
|
||||||
|
* [HHH-13733] - Upgrade to Jandex 2.1.1.Final
|
||||||
|
|
||||||
|
** Improvement
|
||||||
|
* [HHH-13654] - Avoid clearing of collections when closing StatefulPersistenceContext
|
||||||
|
* [HHH-13723] - Hint sizing of ArrayList in ResultSetProcessingContextImpl
|
||||||
|
|
||||||
|
|
||||||
Changes in 5.4.8.Final (October 28, 2019)
|
Changes in 5.4.8.Final (October 28, 2019)
|
||||||
------------------------------------------------------------------------------------------------------------------------
|
------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ ext {
|
||||||
javassistVersion = '3.24.0-GA'
|
javassistVersion = '3.24.0-GA'
|
||||||
byteBuddyVersion = '1.10.2'
|
byteBuddyVersion = '1.10.2'
|
||||||
|
|
||||||
agroalVersion = '1.6'
|
agroalVersion = '1.7'
|
||||||
|
|
||||||
geolatteVersion = '1.4.0'
|
geolatteVersion = '1.4.0'
|
||||||
|
|
||||||
|
@ -55,8 +55,8 @@ ext {
|
||||||
|
|
||||||
// Annotations
|
// Annotations
|
||||||
commons_annotations: "org.hibernate.common:hibernate-commons-annotations:${hibernateCommonsVersion}",
|
commons_annotations: "org.hibernate.common:hibernate-commons-annotations:${hibernateCommonsVersion}",
|
||||||
jandex: 'org.jboss:jandex:2.0.5.Final',
|
jandex: 'org.jboss:jandex:2.1.1.Final',
|
||||||
classmate: 'com.fasterxml:classmate:1.3.4',
|
classmate: 'com.fasterxml:classmate:1.5.1',
|
||||||
|
|
||||||
// Dom4J
|
// Dom4J
|
||||||
dom4j: 'org.dom4j:dom4j:2.1.1@jar',
|
dom4j: 'org.dom4j:dom4j:2.1.1@jar',
|
||||||
|
|
|
@ -104,7 +104,7 @@ public class H2Dialect extends Dialect {
|
||||||
|
|
||||||
if ( buildId >= 32 ) {
|
if ( buildId >= 32 ) {
|
||||||
this.sequenceInformationExtractor = SequenceInformationExtractorH2DatabaseImpl.INSTANCE;
|
this.sequenceInformationExtractor = SequenceInformationExtractorH2DatabaseImpl.INSTANCE;
|
||||||
this.querySequenceString = "select * from INFORMATION_SCHEMA.sequences";
|
this.querySequenceString = "select * from INFORMATION_SCHEMA.SEQUENCES";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.sequenceInformationExtractor = SequenceInformationExtractorNoOpImpl.INSTANCE;
|
this.sequenceInformationExtractor = SequenceInformationExtractorNoOpImpl.INSTANCE;
|
||||||
|
|
|
@ -359,10 +359,7 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.defaultSessionOpenOptions = withOptions();
|
this.defaultSessionOpenOptions = withOptions();
|
||||||
this.temporarySessionOpenOptions = withOptions()
|
this.temporarySessionOpenOptions = buildTemporarySessionOpenOptions();
|
||||||
.autoClose( false )
|
|
||||||
.flushMode( FlushMode.MANUAL )
|
|
||||||
.connectionHandlingMode( PhysicalConnectionHandlingMode.DELAYED_ACQUISITION_AND_RELEASE_AFTER_STATEMENT );
|
|
||||||
this.fastSessionServices = new FastSessionServices( this );
|
this.fastSessionServices = new FastSessionServices( this );
|
||||||
|
|
||||||
this.observer.sessionFactoryCreated( this );
|
this.observer.sessionFactoryCreated( this );
|
||||||
|
@ -385,6 +382,13 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private SessionBuilder buildTemporarySessionOpenOptions() {
|
||||||
|
return withOptions()
|
||||||
|
.autoClose( false )
|
||||||
|
.flushMode( FlushMode.MANUAL )
|
||||||
|
.connectionHandlingMode( PhysicalConnectionHandlingMode.DELAYED_ACQUISITION_AND_RELEASE_AFTER_STATEMENT );
|
||||||
|
}
|
||||||
|
|
||||||
private void primeSecondLevelCacheRegions(MetadataImplementor mappingMetadata) {
|
private void primeSecondLevelCacheRegions(MetadataImplementor mappingMetadata) {
|
||||||
final Map<String, DomainDataRegionConfigImpl.Builder> regionConfigBuilders = new ConcurrentHashMap<>();
|
final Map<String, DomainDataRegionConfigImpl.Builder> regionConfigBuilders = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
@ -515,12 +519,27 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Session openSession() throws HibernateException {
|
public Session openSession() throws HibernateException {
|
||||||
|
final CurrentTenantIdentifierResolver currentTenantIdentifierResolver = getCurrentTenantIdentifierResolver();
|
||||||
|
//We can only use reuse the defaultSessionOpenOptions as a constant when there is no TenantIdentifierResolver
|
||||||
|
if ( currentTenantIdentifierResolver != null ) {
|
||||||
|
return this.withOptions().openSession();
|
||||||
|
}
|
||||||
|
else {
|
||||||
return this.defaultSessionOpenOptions.openSession();
|
return this.defaultSessionOpenOptions.openSession();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public Session openTemporarySession() throws HibernateException {
|
public Session openTemporarySession() throws HibernateException {
|
||||||
|
final CurrentTenantIdentifierResolver currentTenantIdentifierResolver = getCurrentTenantIdentifierResolver();
|
||||||
|
//We can only use reuse the defaultSessionOpenOptions as a constant when there is no TenantIdentifierResolver
|
||||||
|
if ( currentTenantIdentifierResolver != null ) {
|
||||||
|
return buildTemporarySessionOpenOptions()
|
||||||
|
.openSession();
|
||||||
|
}
|
||||||
|
else {
|
||||||
return this.temporarySessionOpenOptions.openSession();
|
return this.temporarySessionOpenOptions.openSession();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public Session getCurrentSession() throws HibernateException {
|
public Session getCurrentSession() throws HibernateException {
|
||||||
if ( currentSessionContext == null ) {
|
if ( currentSessionContext == null ) {
|
||||||
|
@ -1365,8 +1384,9 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
|
||||||
public StatelessSessionBuilderImpl(SessionFactoryImpl sessionFactory) {
|
public StatelessSessionBuilderImpl(SessionFactoryImpl sessionFactory) {
|
||||||
this.sessionFactory = sessionFactory;
|
this.sessionFactory = sessionFactory;
|
||||||
|
|
||||||
if ( sessionFactory.getCurrentTenantIdentifierResolver() != null ) {
|
CurrentTenantIdentifierResolver tenantIdentifierResolver = sessionFactory.getCurrentTenantIdentifierResolver();
|
||||||
tenantIdentifier = sessionFactory.getCurrentTenantIdentifierResolver().resolveCurrentTenantIdentifier();
|
if ( tenantIdentifierResolver != null ) {
|
||||||
|
tenantIdentifier = tenantIdentifierResolver.resolveCurrentTenantIdentifier();
|
||||||
}
|
}
|
||||||
queryParametersValidationEnabled = sessionFactory.getSessionFactoryOptions().isQueryParametersValidationEnabled();
|
queryParametersValidationEnabled = sessionFactory.getSessionFactoryOptions().isQueryParametersValidationEnabled();
|
||||||
}
|
}
|
||||||
|
|
|
@ -2851,7 +2851,13 @@ public final class SessionImpl
|
||||||
}
|
}
|
||||||
catch ( JDBCException e ) {
|
catch ( JDBCException e ) {
|
||||||
if ( accessTransaction().isActive() && accessTransaction().getRollbackOnly() ) {
|
if ( accessTransaction().isActive() && accessTransaction().getRollbackOnly() ) {
|
||||||
// assume this is the similar to the WildFly / IronJacamar "feature" described under HHH-12472
|
// Assume this is the similar to the WildFly / IronJacamar "feature" described under HHH-12472.
|
||||||
|
// Just log the exception and return null.
|
||||||
|
if ( log.isDebugEnabled() ) {
|
||||||
|
log.debug( "JDBCException was thrown for a transaction marked for rollback; " +
|
||||||
|
"this is probably due to an operation failing fast due to the " +
|
||||||
|
"transaction marked for rollback.", e );
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -277,37 +277,11 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
MetadataBuilderContributor metadataBuilderContributor = null;
|
MetadataBuilderContributor metadataBuilderContributor = loadSettingInstance(
|
||||||
Class<? extends MetadataBuilderContributor> metadataBuilderContributorImplClass = null;
|
METADATA_BUILDER_CONTRIBUTOR,
|
||||||
|
metadataBuilderContributorSetting,
|
||||||
if ( metadataBuilderContributorSetting instanceof MetadataBuilderContributor ) {
|
MetadataBuilderContributor.class
|
||||||
metadataBuilderContributor = (MetadataBuilderContributor) metadataBuilderContributorSetting;
|
|
||||||
}
|
|
||||||
else if ( metadataBuilderContributorSetting instanceof Class ) {
|
|
||||||
metadataBuilderContributorImplClass = (Class<? extends MetadataBuilderContributor>) metadataBuilderContributorSetting;
|
|
||||||
}
|
|
||||||
else if ( metadataBuilderContributorSetting instanceof String ) {
|
|
||||||
final ClassLoaderService classLoaderService = standardServiceRegistry.getService( ClassLoaderService.class );
|
|
||||||
|
|
||||||
metadataBuilderContributorImplClass = classLoaderService.classForName( (String) metadataBuilderContributorSetting );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"The provided " + METADATA_BUILDER_CONTRIBUTOR + " setting value [" + metadataBuilderContributorSetting + "] is not supported!"
|
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
if ( metadataBuilderContributorImplClass != null ) {
|
|
||||||
try {
|
|
||||||
metadataBuilderContributor = metadataBuilderContributorImplClass.newInstance();
|
|
||||||
}
|
|
||||||
catch (InstantiationException | IllegalAccessException e) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"The MetadataBuilderContributor class [" + metadataBuilderContributorImplClass + "] could not be instantiated!",
|
|
||||||
e
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( metadataBuilderContributor != null ) {
|
if ( metadataBuilderContributor != null ) {
|
||||||
metadataBuilderContributor.contribute( metamodelBuilder );
|
metadataBuilderContributor.contribute( metamodelBuilder );
|
||||||
|
@ -395,12 +369,7 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
|
||||||
ClassLoaderService providedClassLoaderService) {
|
ClassLoaderService providedClassLoaderService) {
|
||||||
final BootstrapServiceRegistryBuilder bsrBuilder = new BootstrapServiceRegistryBuilder();
|
final BootstrapServiceRegistryBuilder bsrBuilder = new BootstrapServiceRegistryBuilder();
|
||||||
|
|
||||||
final IntegratorProvider integratorProvider = (IntegratorProvider) integrationSettings.get( INTEGRATOR_PROVIDER );
|
applyIntegrationProvider( integrationSettings, bsrBuilder );
|
||||||
if ( integratorProvider != null ) {
|
|
||||||
for ( Integrator integrator : integratorProvider.getIntegrators() ) {
|
|
||||||
bsrBuilder.applyIntegrator( integrator );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final StrategyRegistrationProviderList strategyRegistrationProviderList
|
final StrategyRegistrationProviderList strategyRegistrationProviderList
|
||||||
= (StrategyRegistrationProviderList) integrationSettings.get( STRATEGY_REGISTRATION_PROVIDERS );
|
= (StrategyRegistrationProviderList) integrationSettings.get( STRATEGY_REGISTRATION_PROVIDERS );
|
||||||
|
@ -465,6 +434,25 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
|
||||||
return bsrBuilder.build();
|
return bsrBuilder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void applyIntegrationProvider(Map integrationSettings, BootstrapServiceRegistryBuilder bsrBuilder) {
|
||||||
|
Object integrationSetting = integrationSettings.get( INTEGRATOR_PROVIDER );
|
||||||
|
if ( integrationSetting == null ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final IntegratorProvider integratorProvider = loadSettingInstance(
|
||||||
|
INTEGRATOR_PROVIDER,
|
||||||
|
integrationSetting,
|
||||||
|
IntegratorProvider.class
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( integratorProvider != null ) {
|
||||||
|
for ( Integrator integrator : integratorProvider.getIntegrators() ) {
|
||||||
|
bsrBuilder.applyIntegrator( integrator );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
private MergedSettings mergeSettings(
|
private MergedSettings mergeSettings(
|
||||||
PersistenceUnitDescriptor persistenceUnit,
|
PersistenceUnitDescriptor persistenceUnit,
|
||||||
Map<?,?> integrationSettings,
|
Map<?,?> integrationSettings,
|
||||||
|
@ -1397,4 +1385,51 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
|
||||||
this.cacheRegionDefinitions.add( cacheRegionDefinition );
|
this.cacheRegionDefinitions.add( cacheRegionDefinition );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private <T> T loadSettingInstance(String settingName, Object settingValue, Class<T> clazz) {
|
||||||
|
T instance = null;
|
||||||
|
Class<? extends T> instanceClass = null;
|
||||||
|
|
||||||
|
if ( clazz.isAssignableFrom( settingValue.getClass() ) ) {
|
||||||
|
instance = (T) settingValue;
|
||||||
|
}
|
||||||
|
else if ( settingValue instanceof Class ) {
|
||||||
|
instanceClass = (Class<? extends T>) settingValue;
|
||||||
|
}
|
||||||
|
else if ( settingValue instanceof String ) {
|
||||||
|
String settingStringValue = (String) settingValue;
|
||||||
|
if ( standardServiceRegistry != null ) {
|
||||||
|
final ClassLoaderService classLoaderService = standardServiceRegistry.getService( ClassLoaderService.class );
|
||||||
|
|
||||||
|
instanceClass = classLoaderService.classForName( settingStringValue );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
try {
|
||||||
|
instanceClass = (Class<? extends T>) Class.forName( settingStringValue );
|
||||||
|
}
|
||||||
|
catch (ClassNotFoundException e) {
|
||||||
|
throw new IllegalArgumentException( "Can't load class: " + settingStringValue, e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"The provided " + settingName + " setting value [" + settingValue + "] is not supported!"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( instanceClass != null ) {
|
||||||
|
try {
|
||||||
|
instance = instanceClass.newInstance();
|
||||||
|
}
|
||||||
|
catch (InstantiationException | IllegalAccessException e) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"The " + clazz.getSimpleName() +" class [" + instanceClass + "] could not be instantiated!",
|
||||||
|
e
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -281,8 +281,9 @@ public class ResultSetProcessingContextImpl implements ResultSetProcessingContex
|
||||||
|
|
||||||
|
|
||||||
// managing the running list of registrations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// managing the running list of registrations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
final int sizeHint = currentRowHydratedEntityRegistrationList.size();
|
||||||
if ( hydratedEntityRegistrationList == null ) {
|
if ( hydratedEntityRegistrationList == null ) {
|
||||||
hydratedEntityRegistrationList = new ArrayList<>();
|
hydratedEntityRegistrationList = new ArrayList<>( sizeHint );
|
||||||
}
|
}
|
||||||
hydratedEntityRegistrationList.addAll( currentRowHydratedEntityRegistrationList );
|
hydratedEntityRegistrationList.addAll( currentRowHydratedEntityRegistrationList );
|
||||||
|
|
||||||
|
|
|
@ -75,7 +75,16 @@ public abstract class Constraint implements RelationalModel, Exportable, Seriali
|
||||||
* @return String The generated name
|
* @return String The generated name
|
||||||
*/
|
*/
|
||||||
public static String generateName(String prefix, Table table, List<Column> columns) {
|
public static String generateName(String prefix, Table table, List<Column> columns) {
|
||||||
return generateName( prefix, table, columns.toArray( new Column[columns.size()] ) );
|
//N.B. legacy APIs are involved: can't trust that the columns List is actually
|
||||||
|
//containing Column instances - the generic type isn't consistently enforced.
|
||||||
|
ArrayList<Column> defensive = new ArrayList<>( columns.size() );
|
||||||
|
for ( Object o : columns ) {
|
||||||
|
if ( o instanceof Column ) {
|
||||||
|
defensive.add( (Column) o );
|
||||||
|
}
|
||||||
|
//else: others might be Formula instances. They don't need to be part of the name generation.
|
||||||
|
}
|
||||||
|
return generateName( prefix, table, defensive.toArray( new Column[0] ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -20,6 +20,7 @@ import org.hibernate.engine.spi.EntityKey;
|
||||||
import org.hibernate.engine.spi.PersistenceContext;
|
import org.hibernate.engine.spi.PersistenceContext;
|
||||||
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
|
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
|
||||||
import org.hibernate.engine.spi.PersistentAttributeInterceptor;
|
import org.hibernate.engine.spi.PersistentAttributeInterceptor;
|
||||||
|
import org.hibernate.engine.spi.SelfDirtinessTracker;
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
import org.hibernate.engine.spi.Status;
|
import org.hibernate.engine.spi.Status;
|
||||||
import org.hibernate.mapping.PersistentClass;
|
import org.hibernate.mapping.PersistentClass;
|
||||||
|
@ -140,8 +141,14 @@ public final class BytecodeEnhancementMetadataPojoImpl implements BytecodeEnhanc
|
||||||
final PersistenceContext persistenceContext = session.getPersistenceContext();
|
final PersistenceContext persistenceContext = session.getPersistenceContext();
|
||||||
|
|
||||||
// first, instantiate the entity instance to use as the proxy
|
// first, instantiate the entity instance to use as the proxy
|
||||||
final PersistentAttributeInterceptable entity = (PersistentAttributeInterceptable) persister.getEntityTuplizer().instantiate( identifier, session );
|
final EntityTuplizer entityTuplizer = persister.getEntityTuplizer();
|
||||||
|
final PersistentAttributeInterceptable entity = (PersistentAttributeInterceptable) entityTuplizer
|
||||||
|
.instantiate( identifier, session );
|
||||||
|
|
||||||
|
// clear the fields that are marked as dirty in the dirtyness tracker
|
||||||
|
if ( entity instanceof SelfDirtinessTracker ) {
|
||||||
|
( (SelfDirtinessTracker) entity ).$$_hibernate_clearDirtyAttributes();
|
||||||
|
}
|
||||||
// add the entity (proxy) instance to the PC
|
// add the entity (proxy) instance to the PC
|
||||||
persistenceContext.addEnhancedProxy( entityKey, entity );
|
persistenceContext.addEnhancedProxy( entityKey, entity );
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* 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.jpa.test.integrationprovider;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.hibernate.boot.Metadata;
|
||||||
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.integrator.spi.Integrator;
|
||||||
|
import org.hibernate.jpa.boot.spi.IntegratorProvider;
|
||||||
|
import org.hibernate.service.spi.SessionFactoryServiceRegistry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andrea Boriero
|
||||||
|
*/
|
||||||
|
public class DtoIntegratorProvider implements IntegratorProvider {
|
||||||
|
@Override
|
||||||
|
public List<Integrator> getIntegrators() {
|
||||||
|
return Collections.singletonList(
|
||||||
|
new Integrator() {
|
||||||
|
@Override
|
||||||
|
public void integrate(
|
||||||
|
Metadata metadata,
|
||||||
|
SessionFactoryImplementor sessionFactory,
|
||||||
|
SessionFactoryServiceRegistry serviceRegistry) {
|
||||||
|
metadata.getImports().put( "PersonDto", PersonDto.class.getName() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void disintegrate(
|
||||||
|
SessionFactoryImplementor sessionFactory,
|
||||||
|
SessionFactoryServiceRegistry serviceRegistry) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* 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.jpa.test.integrationprovider;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl;
|
||||||
|
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||||
|
|
||||||
|
import org.hibernate.testing.TestForIssue;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Vlad Mihalcea
|
||||||
|
*/
|
||||||
|
@TestForIssue(jiraKey = "HHH-13614")
|
||||||
|
public class IntegrationProviderSettingByClassTest extends BaseEntityManagerFunctionalTestCase {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?>[] getAnnotatedClasses() {
|
||||||
|
return new Class<?>[] {
|
||||||
|
Person.class
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test() {
|
||||||
|
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||||
|
List<PersonDto> dtos = entityManager.createQuery(
|
||||||
|
"select new PersonDto(id, name) " +
|
||||||
|
"from Person", PersonDto.class )
|
||||||
|
.getResultList();
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addMappings(Map settings) {
|
||||||
|
settings.put( EntityManagerFactoryBuilderImpl.INTEGRATOR_PROVIDER, DtoIntegratorProvider.class );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* 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.jpa.test.integrationprovider;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl;
|
||||||
|
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||||
|
|
||||||
|
import org.hibernate.testing.TestForIssue;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Vlad Mihalcea
|
||||||
|
*/
|
||||||
|
@TestForIssue(jiraKey = "HHH-13614")
|
||||||
|
public class IntegrationProviderSettingByObjectTest extends BaseEntityManagerFunctionalTestCase {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?>[] getAnnotatedClasses() {
|
||||||
|
return new Class<?>[] {
|
||||||
|
Person.class
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test() {
|
||||||
|
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||||
|
List<PersonDto> dtos = entityManager.createQuery(
|
||||||
|
"select new PersonDto(id, name) " +
|
||||||
|
"from Person", PersonDto.class )
|
||||||
|
.getResultList();
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addMappings(Map settings) {
|
||||||
|
settings.put( EntityManagerFactoryBuilderImpl.INTEGRATOR_PROVIDER, new DtoIntegratorProvider() );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* 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.jpa.test.integrationprovider;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl;
|
||||||
|
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||||
|
|
||||||
|
import org.hibernate.testing.TestForIssue;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Vlad Mihalcea
|
||||||
|
*/
|
||||||
|
@TestForIssue(jiraKey = "HHH-13614")
|
||||||
|
public class IntegrationProviderSettingByStringTest extends BaseEntityManagerFunctionalTestCase {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?>[] getAnnotatedClasses() {
|
||||||
|
return new Class<?>[] {
|
||||||
|
Person.class
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test() {
|
||||||
|
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||||
|
List<PersonDto> dtos = entityManager.createQuery(
|
||||||
|
"select new PersonDto(id, name) " +
|
||||||
|
"from Person", PersonDto.class )
|
||||||
|
.getResultList();
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addMappings(Map settings) {
|
||||||
|
settings.put( EntityManagerFactoryBuilderImpl.INTEGRATOR_PROVIDER, DtoIntegratorProvider.class.getName() );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* 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.jpa.test.integrationprovider;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andrea Boriero
|
||||||
|
*/
|
||||||
|
@Entity(name = "Person")
|
||||||
|
public class Person {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
private int age;
|
||||||
|
|
||||||
|
public Person() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Person(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAge() {
|
||||||
|
return age;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAge(int age) {
|
||||||
|
this.age = age;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* 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.jpa.test.integrationprovider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andrea Boriero
|
||||||
|
*/
|
||||||
|
public class PersonDto {
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public PersonDto(Long id, String name) {
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,149 @@
|
||||||
|
/*
|
||||||
|
* 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.query.hhh13670;
|
||||||
|
|
||||||
|
import org.hibernate.cfg.Configuration;
|
||||||
|
import org.hibernate.testing.TestForIssue;
|
||||||
|
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.ConstraintMode;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.FetchType;
|
||||||
|
import javax.persistence.ForeignKey;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.Inheritance;
|
||||||
|
import javax.persistence.InheritanceType;
|
||||||
|
import javax.persistence.JoinColumn;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.Tuple;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
|
||||||
|
@TestForIssue(jiraKey = "HHH-13670")
|
||||||
|
public class HHH13670Test extends BaseCoreFunctionalTestCase {
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
doInJPA(this::sessionFactory, em -> {
|
||||||
|
SubA a_1 = new SubA(1L);
|
||||||
|
SubA a_2 = new SubA(2L);
|
||||||
|
SubA a_3 = new SubA(3L);
|
||||||
|
SubA a_14 = em.getReference(SubA.class, 10L);
|
||||||
|
SubB b_4 = new SubB(4L, null);
|
||||||
|
SubB b_5 = new SubB(5L, a_3);
|
||||||
|
SubB b_6 = new SubB(6L, b_4);
|
||||||
|
SubB b_7 = new SubB(7L, a_14);
|
||||||
|
|
||||||
|
em.merge(a_1);
|
||||||
|
em.merge(a_2);
|
||||||
|
em.merge(a_3);
|
||||||
|
em.merge(b_4);
|
||||||
|
em.merge(b_5);
|
||||||
|
em.merge(b_6);
|
||||||
|
em.merge(b_7);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDereferenceSuperClassAttributeInWithClause() {
|
||||||
|
doInJPA(this::sessionFactory, em -> {
|
||||||
|
em.createQuery("SELECT subB_0.id FROM SubB subB_0 LEFT JOIN subB_0.other subA_0 ON subA_0.id = subB_0.parent.id", Tuple.class).getResultList();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRootTypeJoinWithGroupJoins() {
|
||||||
|
doInJPA(this::sessionFactory, em -> {
|
||||||
|
List<Tuple> resultList = em.createQuery("SELECT subB_0.id, subA_0.id, subB_0.id, subA_0.id FROM SubB subB_0 LEFT JOIN Super subA_0 ON subA_0.id = subB_0.parent.id ORDER BY subB_0.id ASC, subA_0.id ASC", Tuple.class)
|
||||||
|
.getResultList();
|
||||||
|
|
||||||
|
assertEquals("Rows omitted despite optional association should have rendered a left join", 4, resultList.size());
|
||||||
|
|
||||||
|
assertEquals((Long) 4L , resultList.get(0).get(0));
|
||||||
|
assertEquals((Long) 5L , resultList.get(1).get(0));
|
||||||
|
assertEquals((Long) 6L , resultList.get(2).get(0));
|
||||||
|
assertEquals((Long) 7L , resultList.get(3).get(0));
|
||||||
|
|
||||||
|
assertNull(resultList.get(0).get(1, Long.class));
|
||||||
|
assertEquals((Long) 3L , resultList.get(1).get(1, Long.class));
|
||||||
|
assertEquals((Long) 4L , resultList.get(2).get(1, Long.class));
|
||||||
|
assertNull("Missing entry in foreign table should not be returned", resultList.get(3).get(1, Long.class));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSubTypeJoinWithTableGroupJoins() {
|
||||||
|
doInJPA(this::sessionFactory, em -> {
|
||||||
|
List<Tuple> resultList = em.createQuery("SELECT subB_0.id, subA_0.id, subB_0.id, subA_0.id FROM SubB subB_0 LEFT JOIN SubA subA_0 ON subA_0.id = subB_0.parent.id ORDER BY subB_0.id ASC, subA_0.id ASC", Tuple.class)
|
||||||
|
.getResultList();
|
||||||
|
|
||||||
|
assertEquals("Rows omitted despite optional association should have rendered a left join", 4, resultList.size());
|
||||||
|
|
||||||
|
assertEquals((Long) 4L, resultList.get(0).get(0));
|
||||||
|
assertEquals((Long) 5L, resultList.get(1).get(0));
|
||||||
|
assertEquals((Long) 6L, resultList.get(2).get(0));
|
||||||
|
assertEquals((Long) 7L, resultList.get(3).get(0));
|
||||||
|
|
||||||
|
assertNull(resultList.get(0).get(1, Long.class));
|
||||||
|
assertEquals((Long) 3L, resultList.get(1).get(1, Long.class));
|
||||||
|
assertNull("Another subtype than queried for was returned", resultList.get(2).get(1));
|
||||||
|
assertNull("Missing entry in foreign table should not be returned", resultList.get(3).get(1, Long.class));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?>[] getAnnotatedClasses() {
|
||||||
|
return new Class<?>[] { Super.class, SubA.class, SubB.class };
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "Super")
|
||||||
|
@Inheritance(strategy = InheritanceType.JOINED)
|
||||||
|
public static class Super<SubType extends Super> {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@Column
|
||||||
|
Long id;
|
||||||
|
|
||||||
|
@JoinColumn(foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
|
||||||
|
@ManyToOne(targetEntity = Super.class, fetch = FetchType.LAZY)
|
||||||
|
SubType parent;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "SubA")
|
||||||
|
public static class SubA extends Super {
|
||||||
|
|
||||||
|
SubA() {}
|
||||||
|
|
||||||
|
SubA(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "SubB")
|
||||||
|
public static class SubB extends Super<SubA> {
|
||||||
|
|
||||||
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
|
Super other;
|
||||||
|
|
||||||
|
SubB() {}
|
||||||
|
|
||||||
|
SubB(Long id, Super parent) {
|
||||||
|
this.id = id;
|
||||||
|
((Super) this).parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,122 @@
|
||||||
|
/*
|
||||||
|
* 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.query.hhh13712;
|
||||||
|
|
||||||
|
import org.hibernate.testing.TestForIssue;
|
||||||
|
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.ConstraintMode;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.FetchType;
|
||||||
|
import javax.persistence.ForeignKey;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.Inheritance;
|
||||||
|
import javax.persistence.InheritanceType;
|
||||||
|
import javax.persistence.JoinColumn;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.Tuple;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
|
||||||
|
@TestForIssue(jiraKey = "HHH-13712")
|
||||||
|
public class HHH13712Test extends BaseCoreFunctionalTestCase {
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
doInJPA(this::sessionFactory, em -> {
|
||||||
|
SomeOther a_1 = new SomeOther(1L);
|
||||||
|
SomeOther a_2 = new SomeOther(2L);
|
||||||
|
SomeOther a_3 = new SomeOther(3L);
|
||||||
|
SubObject b_5 = new SubObject(5L, a_1);
|
||||||
|
SubObject b_6 = new SubObject(6L, a_2);
|
||||||
|
SubObject b_7 = new SubObject(7L, a_3);
|
||||||
|
|
||||||
|
em.merge(a_1);
|
||||||
|
em.merge(a_2);
|
||||||
|
em.merge(a_3);
|
||||||
|
em.merge(b_5);
|
||||||
|
em.merge(b_6);
|
||||||
|
em.merge(b_7);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testJoinSuperclassAssociationOnly() {
|
||||||
|
doInJPA(this::sessionFactory, em -> {
|
||||||
|
List<Integer> actual = em.createQuery("SELECT 1 FROM SubObject sub LEFT JOIN sub.parent p", Integer.class).getResultList();
|
||||||
|
assertEquals(3, actual.size());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testJoinSuperclassAssociation() {
|
||||||
|
doInJPA(this::sessionFactory, em -> {
|
||||||
|
long actual = em.createQuery("SELECT COUNT(sub) FROM SubObject sub LEFT JOIN sub.parent p WHERE p.id = 1", Long.class).getSingleResult();
|
||||||
|
assertEquals(1L, actual);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCountParentIds() {
|
||||||
|
doInJPA(this::sessionFactory, em -> {
|
||||||
|
long actual = em.createQuery("SELECT COUNT(distinct sub.parent.id) FROM SubObject sub", Long.class).getSingleResult();
|
||||||
|
assertEquals(3L, actual);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?>[] getAnnotatedClasses() {
|
||||||
|
return new Class<?>[] { Super.class, SubObject.class, SomeOther.class };
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "Super")
|
||||||
|
@Inheritance(strategy = InheritanceType.JOINED)
|
||||||
|
public static class Super {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@Column
|
||||||
|
Long id;
|
||||||
|
|
||||||
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
|
@JoinColumn(nullable = false)
|
||||||
|
SomeOther parent;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "SubObject")
|
||||||
|
public static class SubObject extends Super {
|
||||||
|
|
||||||
|
SubObject() {}
|
||||||
|
|
||||||
|
SubObject(Long id, SomeOther parent) {
|
||||||
|
this.id = id;
|
||||||
|
this.parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "SomeOther")
|
||||||
|
public static class SomeOther {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@Column
|
||||||
|
Long id;
|
||||||
|
|
||||||
|
SomeOther() {}
|
||||||
|
|
||||||
|
SomeOther(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
/*
|
||||||
|
* 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.inlinedirtychecking;
|
||||||
|
|
||||||
|
import org.hibernate.bytecode.enhance.spi.UnloadedClass;
|
||||||
|
|
||||||
|
import org.hibernate.testing.bytecode.enhancement.EnhancerTestContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andrea Boriero
|
||||||
|
*/
|
||||||
|
public class DirtyCheckEnhancementContext extends EnhancerTestContext {
|
||||||
|
@Override
|
||||||
|
public boolean doExtendedEnhancement(UnloadedClass classDescriptor) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,691 @@
|
||||||
|
/*
|
||||||
|
* 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.inlinedirtychecking;
|
||||||
|
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import javax.persistence.Cacheable;
|
||||||
|
import javax.persistence.CascadeType;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.DiscriminatorColumn;
|
||||||
|
import javax.persistence.DiscriminatorType;
|
||||||
|
import javax.persistence.DiscriminatorValue;
|
||||||
|
import javax.persistence.Embeddable;
|
||||||
|
import javax.persistence.Embedded;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.EnumType;
|
||||||
|
import javax.persistence.Enumerated;
|
||||||
|
import javax.persistence.FetchType;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.Inheritance;
|
||||||
|
import javax.persistence.InheritanceType;
|
||||||
|
import javax.persistence.JoinColumn;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
import org.hibernate.annotations.NaturalId;
|
||||||
|
import org.hibernate.boot.MetadataSources;
|
||||||
|
import org.hibernate.boot.SessionFactoryBuilder;
|
||||||
|
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||||
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
|
import org.hibernate.stat.Statistics;
|
||||||
|
|
||||||
|
import org.hibernate.testing.TestForIssue;
|
||||||
|
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
|
||||||
|
import org.hibernate.testing.bytecode.enhancement.CustomEnhancementContext;
|
||||||
|
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.is;
|
||||||
|
import static org.hamcrest.CoreMatchers.nullValue;
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andrea Boriero
|
||||||
|
*/
|
||||||
|
@RunWith(BytecodeEnhancerRunner.class)
|
||||||
|
@CustomEnhancementContext({ DirtyCheckEnhancementContext.class, NoDirtyCheckEnhancementContext.class })
|
||||||
|
@TestForIssue(jiraKey = "HHH-13705")
|
||||||
|
public class ManyToOnePropertyAccessByFieldTest extends BaseNonConfigCoreFunctionalTestCase {
|
||||||
|
@Override
|
||||||
|
protected void configureStandardServiceRegistryBuilder(StandardServiceRegistryBuilder ssrb) {
|
||||||
|
super.configureStandardServiceRegistryBuilder( ssrb );
|
||||||
|
ssrb.applySetting( AvailableSettings.ALLOW_ENHANCEMENT_AS_PROXY, "true" );
|
||||||
|
ssrb.applySetting( AvailableSettings.FORMAT_SQL, "false" );
|
||||||
|
ssrb.applySetting( AvailableSettings.GENERATE_STATISTICS, "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( User.class );
|
||||||
|
sources.addAnnotatedClass( Office.class );
|
||||||
|
sources.addAnnotatedClass( Client.class );
|
||||||
|
sources.addAnnotatedClass( Request.class );
|
||||||
|
sources.addAnnotatedClass( InternalRequest.class );
|
||||||
|
sources.addAnnotatedClass( Phone.class );
|
||||||
|
}
|
||||||
|
|
||||||
|
private Long userId;
|
||||||
|
private Long targetUserId;
|
||||||
|
private Long officeId;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
inTransaction(
|
||||||
|
session -> {
|
||||||
|
Log log = new Log();
|
||||||
|
log.setCreationDate( OffsetDateTime.now() );
|
||||||
|
|
||||||
|
|
||||||
|
Office office = buildOffice( "The office", "And", Collections.emptySet() );
|
||||||
|
|
||||||
|
session.persist( office );
|
||||||
|
officeId = office.getId();
|
||||||
|
|
||||||
|
User user = new User();
|
||||||
|
user.setOffice( office );
|
||||||
|
user.setClient( office.getClient() );
|
||||||
|
user.setName( "Fab" );
|
||||||
|
user.setLog( log );
|
||||||
|
user.setEmail( "fab@hibernate.org" );
|
||||||
|
|
||||||
|
session.persist( user );
|
||||||
|
|
||||||
|
userId = user.getId();
|
||||||
|
|
||||||
|
user = new User();
|
||||||
|
user.setOffice( office );
|
||||||
|
user.setClient( office.getClient() );
|
||||||
|
user.setName( "And" );
|
||||||
|
user.setLog( log );
|
||||||
|
user.setEmail( "and@hibernate.org" );
|
||||||
|
|
||||||
|
session.persist( user );
|
||||||
|
targetUserId = user.getId();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
inTransaction(
|
||||||
|
session -> {
|
||||||
|
session.createQuery( "delete from Request" ).executeUpdate();
|
||||||
|
session.createQuery( "delete from User" ).executeUpdate();
|
||||||
|
session.createQuery( "delete from Office" ).executeUpdate();
|
||||||
|
session.createQuery( "delete from Client" ).executeUpdate();
|
||||||
|
session.createQuery( "delete from Phone" ).executeUpdate();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPersist() {
|
||||||
|
final Statistics stats = sessionFactory().getStatistics();
|
||||||
|
stats.clear();
|
||||||
|
|
||||||
|
InternalRequest internalRequest = new InternalRequest( 1L );
|
||||||
|
inTransaction(
|
||||||
|
session -> {
|
||||||
|
User user = session.find( User.class, userId );
|
||||||
|
internalRequest.setUser( user );
|
||||||
|
assertThat( stats.getPrepareStatementCount(), is( 1L ) );
|
||||||
|
|
||||||
|
User targetUser = session.find( User.class, targetUserId );
|
||||||
|
assertThat( stats.getPrepareStatementCount(), is( 2L ) );
|
||||||
|
|
||||||
|
internalRequest.setTargetUser( targetUser );
|
||||||
|
|
||||||
|
session.persist( internalRequest );
|
||||||
|
|
||||||
|
}
|
||||||
|
);
|
||||||
|
assertThat( stats.getPrepareStatementCount(), is( 3L ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDelete() {
|
||||||
|
Set<Phone> officePhones = new HashSet<>();
|
||||||
|
officePhones.add( new Phone( 1L, "landline", "028-234-9876" ) );
|
||||||
|
officePhones.add( new Phone( 2L, "mobile", "072-122-9876" ) );
|
||||||
|
Office office = buildOffice( "second office", "Fab", officePhones );
|
||||||
|
inTransaction(
|
||||||
|
session -> {
|
||||||
|
session.save( office );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
inTransaction(
|
||||||
|
session -> {
|
||||||
|
Office result = session.find( Office.class, office.id );
|
||||||
|
session.delete( result );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
inTransaction(
|
||||||
|
session -> {
|
||||||
|
List<Office> offices = session.createQuery( "from Office" ).list();
|
||||||
|
assertThat( offices.size(), is( 1 ) );
|
||||||
|
assertThat( offices.get( 0 ).getId(), is( officeId ) );
|
||||||
|
|
||||||
|
List<Phone> phones = session.createQuery( "from Phone" ).list();
|
||||||
|
assertThat( phones.size(), is( 0 ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUpdate() {
|
||||||
|
InternalRequest internalRequest = new InternalRequest( 1L );
|
||||||
|
inTransaction(
|
||||||
|
session -> {
|
||||||
|
User user = session.find( User.class, userId );
|
||||||
|
internalRequest.setUser( user );
|
||||||
|
|
||||||
|
User targetUser = session.find( User.class, targetUserId );
|
||||||
|
|
||||||
|
internalRequest.setTargetUser( targetUser );
|
||||||
|
|
||||||
|
session.persist( internalRequest );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
inTransaction(
|
||||||
|
session -> {
|
||||||
|
InternalRequest result = session.find( InternalRequest.class, internalRequest.getId() );
|
||||||
|
assertThat( result.getTargetUser().getId(), is( targetUserId ) );
|
||||||
|
assertThat( result.getUser().getId(), is( userId ) );
|
||||||
|
result.setUser( null );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
inTransaction(
|
||||||
|
session -> {
|
||||||
|
InternalRequest result = session.find( InternalRequest.class, internalRequest.getId() );
|
||||||
|
assertThat( result.getTargetUser().getId(), is( targetUserId ) );
|
||||||
|
assertThat( result.getUser(), is( nullValue() ) );
|
||||||
|
|
||||||
|
User user = session.find( User.class, userId );
|
||||||
|
result.setTargetUser( user );
|
||||||
|
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
inTransaction(
|
||||||
|
session -> {
|
||||||
|
InternalRequest result = session.find( InternalRequest.class, internalRequest.getId() );
|
||||||
|
assertThat( result.getTargetUser().getId(), is( userId ) );
|
||||||
|
assertThat( result.getUser(), is( nullValue() ) );
|
||||||
|
|
||||||
|
User user = session.find( User.class, userId );
|
||||||
|
result.setUser( user );
|
||||||
|
|
||||||
|
Set<Phone> officePhones = new HashSet<>();
|
||||||
|
officePhones.add( new Phone( 1L, "landline", "028-234-9876" ) );
|
||||||
|
officePhones.add( new Phone( 2L, "mobile", "072-122-9876" ) );
|
||||||
|
Office office = buildOffice( "second office", "Fab", officePhones );
|
||||||
|
|
||||||
|
|
||||||
|
session.save( office );
|
||||||
|
|
||||||
|
List<Office> offices = new ArrayList<>();
|
||||||
|
offices.add( office );
|
||||||
|
|
||||||
|
user.setOffices( offices );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
inTransaction(
|
||||||
|
session -> {
|
||||||
|
InternalRequest result = session.find( InternalRequest.class, internalRequest.getId() );
|
||||||
|
assertThat( result.getTargetUser().getId(), is( userId ) );
|
||||||
|
User user = result.getUser();
|
||||||
|
assertThat( user.getId(), is( userId ) );
|
||||||
|
List<Office> offices = user.getOffices();
|
||||||
|
assertThat( offices.size(), is( 1 ) );
|
||||||
|
Office office = offices.get( 0 );
|
||||||
|
assertThat( office.getPhones().size(), is( 2 ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Office buildOffice(String officename, String clientName, Set<Phone> phones) {
|
||||||
|
Log log = new Log();
|
||||||
|
log.setCreationDate( OffsetDateTime.now() );
|
||||||
|
|
||||||
|
Office office;
|
||||||
|
office = new Office();
|
||||||
|
Client client = new Client();
|
||||||
|
client.setName( clientName );
|
||||||
|
client.setLog( log );
|
||||||
|
|
||||||
|
office.setName( officename );
|
||||||
|
office.setActive( true );
|
||||||
|
office.setDescription( officename );
|
||||||
|
office.setManaged( true );
|
||||||
|
office.setLog( log );
|
||||||
|
office.setClient( client );
|
||||||
|
office.setPhones( phones );
|
||||||
|
|
||||||
|
return office;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Embeddable
|
||||||
|
public static class Log {
|
||||||
|
@Column(name = "`creationDate`", nullable = false)
|
||||||
|
private OffsetDateTime creationDate;
|
||||||
|
|
||||||
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
|
@JoinColumn(name = "`idCreator`")
|
||||||
|
private User creator;
|
||||||
|
|
||||||
|
public OffsetDateTime getCreationDate() {
|
||||||
|
return creationDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreationDate(OffsetDateTime creationDate) {
|
||||||
|
this.creationDate = creationDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public User getCreator() {
|
||||||
|
return creator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreator(User creator) {
|
||||||
|
this.creator = creator;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "User")
|
||||||
|
@Table(name = "`User`")
|
||||||
|
public static class User {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Column(length = 120, nullable = false)
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Column(length = 200, nullable = false, unique = true)
|
||||||
|
private String email;
|
||||||
|
|
||||||
|
private String hash;
|
||||||
|
|
||||||
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
|
@JoinColumn(name = "idOffice")
|
||||||
|
private Office office;
|
||||||
|
|
||||||
|
@OneToMany
|
||||||
|
private List<Office> offices;
|
||||||
|
|
||||||
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
|
@JoinColumn(name = "`idClient`")
|
||||||
|
private Client client;
|
||||||
|
|
||||||
|
@Embedded
|
||||||
|
private Log log = new Log();
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Office getOffice() {
|
||||||
|
return office;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOffice(Office office) {
|
||||||
|
this.office = office;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Log getLog() {
|
||||||
|
return log;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLog(Log log) {
|
||||||
|
this.log = log;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Client getClient() {
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClient(Client client) {
|
||||||
|
this.client = client;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEmail() {
|
||||||
|
return email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEmail(String email) {
|
||||||
|
this.email = email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHash() {
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHash(String hash) {
|
||||||
|
this.hash = hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Office> getOffices() {
|
||||||
|
return offices;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOffices(List<Office> offices) {
|
||||||
|
this.offices = offices;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "Office")
|
||||||
|
public static class Office {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Column(length = 50, nullable = false)
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private Boolean isActive = true;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private Boolean isManaged = false;
|
||||||
|
|
||||||
|
@ManyToOne(optional = false, cascade = CascadeType.ALL)
|
||||||
|
@JoinColumn(name = "idClient")
|
||||||
|
private Client client;
|
||||||
|
|
||||||
|
@OneToMany(cascade = CascadeType.ALL)
|
||||||
|
private Set<Phone> phones = new HashSet<>();
|
||||||
|
|
||||||
|
@Embedded
|
||||||
|
private Log log = new Log();
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Client getClient() {
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClient(Client client) {
|
||||||
|
this.client = client;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDescription(String description) {
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getActive() {
|
||||||
|
return isActive;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setActive(Boolean active) {
|
||||||
|
isActive = active;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getManaged() {
|
||||||
|
return isManaged;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setManaged(Boolean managed) {
|
||||||
|
isManaged = managed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Log getLog() {
|
||||||
|
return log;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLog(Log log) {
|
||||||
|
this.log = log;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<Phone> getPhones() {
|
||||||
|
return phones;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPhones(Set<Phone> phones) {
|
||||||
|
this.phones = phones;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "Phone")
|
||||||
|
public static class Phone {
|
||||||
|
@Id
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String type;
|
||||||
|
|
||||||
|
@NaturalId
|
||||||
|
@Column(name = "`number`")
|
||||||
|
private String number;
|
||||||
|
|
||||||
|
public Phone() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Phone(Long id, String type, String number) {
|
||||||
|
this.id = id;
|
||||||
|
this.type = type;
|
||||||
|
this.number = number;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(String type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNumber() {
|
||||||
|
return number;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNumber(String number) {
|
||||||
|
this.number = number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "Client")
|
||||||
|
public static class Client {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Embedded
|
||||||
|
private Log log = new Log();
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Log getLog() {
|
||||||
|
return log;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLog(Log log) {
|
||||||
|
this.log = log;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
|
||||||
|
@DiscriminatorColumn(discriminatorType = DiscriminatorType.STRING, name = "type", length = 30)
|
||||||
|
@Cacheable
|
||||||
|
@Entity(name = "Request")
|
||||||
|
public static abstract class Request {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
|
@JoinColumn(name = "idUser")
|
||||||
|
private User user;
|
||||||
|
|
||||||
|
@Column(name = "`creationDate`", nullable = false)
|
||||||
|
private OffsetDateTime creationDate = OffsetDateTime.now();
|
||||||
|
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
@Column(length = 30, nullable = false, name = "status")
|
||||||
|
private StatusRequest status = StatusRequest.REQUESTED;
|
||||||
|
|
||||||
|
Request() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Request(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public User getUser() {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUser(User userSolicitacao) {
|
||||||
|
this.user = userSolicitacao;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OffsetDateTime getCreationDate() {
|
||||||
|
return creationDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreationDate(OffsetDateTime creationDate) {
|
||||||
|
this.creationDate = creationDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StatusRequest getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatus(StatusRequest status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "InternalRequest")
|
||||||
|
@DiscriminatorValue(value = "INTERN")
|
||||||
|
public static class InternalRequest extends Request {
|
||||||
|
|
||||||
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
|
@JoinColumn(name = "`idTargetUser`")
|
||||||
|
private User targetUser;
|
||||||
|
|
||||||
|
InternalRequest() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public InternalRequest(Long id) {
|
||||||
|
super( id );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public User getTargetUser() {
|
||||||
|
return targetUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTargetUser(User targetUser) {
|
||||||
|
this.targetUser = targetUser;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum StatusRequest {
|
||||||
|
|
||||||
|
REQUESTED( "requested" ), WAITING( "Feedback waiting" );
|
||||||
|
|
||||||
|
private final String description;
|
||||||
|
|
||||||
|
StatusRequest(final String description) {
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,195 @@
|
||||||
|
/*
|
||||||
|
* 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.inlinedirtychecking;
|
||||||
|
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Embeddable;
|
||||||
|
import javax.persistence.Embedded;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.FetchType;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.JoinColumn;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
import org.hibernate.boot.MetadataSources;
|
||||||
|
import org.hibernate.boot.SessionFactoryBuilder;
|
||||||
|
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||||
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
|
import org.hibernate.stat.Statistics;
|
||||||
|
|
||||||
|
import org.hibernate.testing.TestForIssue;
|
||||||
|
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
|
||||||
|
import org.hibernate.testing.bytecode.enhancement.CustomEnhancementContext;
|
||||||
|
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.is;
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andrea Boriero
|
||||||
|
*/
|
||||||
|
@RunWith(BytecodeEnhancerRunner.class)
|
||||||
|
@CustomEnhancementContext({ DirtyCheckEnhancementContext.class, NoDirtyCheckEnhancementContext.class })
|
||||||
|
@TestForIssue(jiraKey = "HHH-13705")
|
||||||
|
public class ManyToOneWithEmbeddedAndNotOptionalFieldTest extends BaseNonConfigCoreFunctionalTestCase {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configureStandardServiceRegistryBuilder(StandardServiceRegistryBuilder ssrb) {
|
||||||
|
super.configureStandardServiceRegistryBuilder( ssrb );
|
||||||
|
ssrb.applySetting( AvailableSettings.ALLOW_ENHANCEMENT_AS_PROXY, "true" );
|
||||||
|
ssrb.applySetting( AvailableSettings.FORMAT_SQL, "false" );
|
||||||
|
ssrb.applySetting( AvailableSettings.GENERATE_STATISTICS, "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( Client.class );
|
||||||
|
sources.addAnnotatedClass( User.class );
|
||||||
|
}
|
||||||
|
|
||||||
|
private Long userId;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
User user = new User();
|
||||||
|
inTransaction(
|
||||||
|
session -> {
|
||||||
|
|
||||||
|
Log log = new Log();
|
||||||
|
log.setCreationDate( OffsetDateTime.now() );
|
||||||
|
|
||||||
|
Client client = new Client();
|
||||||
|
client.setName( "And" );
|
||||||
|
client.setLog( log );
|
||||||
|
|
||||||
|
|
||||||
|
session.save( client );
|
||||||
|
|
||||||
|
user.setName( "Fab" );
|
||||||
|
|
||||||
|
user.setClient( client );
|
||||||
|
|
||||||
|
session.save( user );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
userId = user.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void load() {
|
||||||
|
final Statistics stats = sessionFactory().getStatistics();
|
||||||
|
stats.clear();
|
||||||
|
inTransaction(
|
||||||
|
session -> {
|
||||||
|
session.find( User.class, userId );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
assertThat( stats.getPrepareStatementCount(), is( 1L ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "Client")
|
||||||
|
public static class Client {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Embedded
|
||||||
|
private Log log = new Log();
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Log getLog() {
|
||||||
|
return log;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLog(Log log) {
|
||||||
|
this.log = log;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "User")
|
||||||
|
@Table(name = "`User`")
|
||||||
|
public static class User {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Column(length = 120, nullable = false)
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
|
@JoinColumn(name = "`idClient`")
|
||||||
|
private Client client;
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Client getClient() {
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClient(Client client) {
|
||||||
|
this.client = client;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Embeddable
|
||||||
|
public static class Log {
|
||||||
|
@Column(name = "`creationDate`", nullable = false)
|
||||||
|
private OffsetDateTime creationDate;
|
||||||
|
|
||||||
|
public OffsetDateTime getCreationDate() {
|
||||||
|
return creationDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreationDate(OffsetDateTime creationDate) {
|
||||||
|
this.creationDate = creationDate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* 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.inlinedirtychecking;
|
||||||
|
|
||||||
|
import org.hibernate.bytecode.enhance.spi.UnloadedClass;
|
||||||
|
|
||||||
|
import org.hibernate.testing.bytecode.enhancement.EnhancerTestContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andrea Boriero
|
||||||
|
*/
|
||||||
|
public class NoDirtyCheckEnhancementContext extends EnhancerTestContext {
|
||||||
|
@Override
|
||||||
|
public boolean doDirtyCheckingInline(UnloadedClass classDescriptor) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean doExtendedEnhancement(UnloadedClass classDescriptor) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,95 @@
|
||||||
|
/*
|
||||||
|
* 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.exceptionhandling;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.Map;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.PersistenceException;
|
||||||
|
|
||||||
|
import org.hibernate.JDBCException;
|
||||||
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
|
import org.hibernate.dialect.H2Dialect;
|
||||||
|
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||||
|
|
||||||
|
import org.hibernate.testing.RequiresDialect;
|
||||||
|
import org.hibernate.testing.TestForIssue;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
|
@TestForIssue( jiraKey = "HHH-13737")
|
||||||
|
@RequiresDialect(H2Dialect.class)
|
||||||
|
public class NonActiveTransactionSessionFindJdbcExceptionHandlingTest extends BaseEntityManagerFunctionalTestCase {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testJdbcExceptionThrown() {
|
||||||
|
// delete "description" column so that a JDBCException caused by a SQLException is thrown when looking up the AnEntity
|
||||||
|
doInJPA(
|
||||||
|
this::entityManagerFactory,
|
||||||
|
entityManager -> {
|
||||||
|
entityManager.createNativeQuery( "alter table AnEntity drop column description" ).executeUpdate();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
EntityManager entityManager = getOrCreateEntityManager();
|
||||||
|
try {
|
||||||
|
entityManager.find( AnEntity.class, 1 );
|
||||||
|
fail( "A PersistenceException should have been thrown." );
|
||||||
|
}
|
||||||
|
catch ( PersistenceException ex ) {
|
||||||
|
assertTrue( JDBCException.class.isInstance( ex.getCause() ) );
|
||||||
|
assertTrue( SQLException.class.isInstance( ex.getCause().getCause() ) );
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
entityManager.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setupData() {
|
||||||
|
doInJPA(
|
||||||
|
this::entityManagerFactory,
|
||||||
|
entityManager -> {
|
||||||
|
entityManager.persist( new AnEntity( 1, "description" ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
protected void addMappings(Map settings) {
|
||||||
|
settings.put( AvailableSettings.JPA_TRANSACTION_COMPLIANCE, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class[] getAnnotatedClasses() {
|
||||||
|
return new Class[] { AnEntity.class };
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "AnEntity")
|
||||||
|
public static class AnEntity {
|
||||||
|
@Id
|
||||||
|
private int id;
|
||||||
|
@Column(name = "description")
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
AnEntity() {
|
||||||
|
}
|
||||||
|
|
||||||
|
AnEntity(int id, String description) {
|
||||||
|
this.id = id;
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
* 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.mapping.joinformula;
|
||||||
|
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class ChildEntity {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Column(name = "PARENT_ID")
|
||||||
|
private Long parentId;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* 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.mapping.joinformula;
|
||||||
|
|
||||||
|
import org.hibernate.Session;
|
||||||
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
|
import org.hibernate.cfg.Configuration;
|
||||||
|
|
||||||
|
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class JoinFormulaTest extends BaseCoreFunctionalTestCase {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class[] getAnnotatedClasses() {
|
||||||
|
return new Class[] {
|
||||||
|
ParentEntity.class,
|
||||||
|
ChildEntity.class
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure(Configuration configuration) {
|
||||||
|
super.configure( configuration );
|
||||||
|
configuration.setProperty( AvailableSettings.SHOW_SQL, Boolean.TRUE.toString() );
|
||||||
|
configuration.setProperty( AvailableSettings.FORMAT_SQL, Boolean.TRUE.toString() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void hhh13722Test() {
|
||||||
|
try (Session s = openSession()) {
|
||||||
|
//Nothing to do: the test just needs to verify that
|
||||||
|
//this can boot.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* 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.mapping.joinformula;
|
||||||
|
|
||||||
|
import org.hibernate.annotations.JoinColumnOrFormula;
|
||||||
|
import org.hibernate.annotations.JoinColumnsOrFormulas;
|
||||||
|
import org.hibernate.annotations.JoinFormula;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.JoinColumn;
|
||||||
|
import javax.persistence.OneToOne;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class ParentEntity {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@OneToOne(targetEntity = ChildEntity.class, optional = false)
|
||||||
|
@JoinColumnsOrFormulas({
|
||||||
|
@JoinColumnOrFormula(column = @JoinColumn(name = "ID", referencedColumnName = "PARENT_ID", insertable = false, updatable = false)),
|
||||||
|
@JoinColumnOrFormula(formula = @JoinFormula(referencedColumnName = "NAME", value = "'Tom'"))
|
||||||
|
})
|
||||||
|
private ChildEntity tom;
|
||||||
|
|
||||||
|
@OneToOne(targetEntity = ChildEntity.class, optional = false)
|
||||||
|
@JoinColumnsOrFormulas({
|
||||||
|
@JoinColumnOrFormula(column = @JoinColumn(name = "ID", referencedColumnName = "PARENT_ID", insertable = false, updatable = false)),
|
||||||
|
@JoinColumnOrFormula(formula = @JoinFormula(referencedColumnName = "NAME", value = "'Ben'"))
|
||||||
|
})
|
||||||
|
private ChildEntity ben;
|
||||||
|
|
||||||
|
}
|
|
@ -193,9 +193,10 @@ public class DiscriminatorMultiTenancyTest extends BaseUnitTestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void doInHibernate(String tenant,
|
public void doInHibernate(String tenant, Consumer<Session> function) {
|
||||||
Consumer<Session> function) {
|
|
||||||
currentTenantResolver.currentTenantIdentifier = tenant;
|
currentTenantResolver.currentTenantIdentifier = tenant;
|
||||||
TransactionUtil.doInHibernate( this::sessionFactory, tenant, function);
|
//Careful: do not use the #doInHibernate version of the method which takes a tenant: the goal of these tests is
|
||||||
|
// to verify that the CurrentTenantIdentifierResolver is being applied!
|
||||||
|
TransactionUtil.doInHibernate( this::sessionFactory, function);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -35,6 +35,8 @@ import org.hibernate.dialect.SQLServerDialect;
|
||||||
import org.hibernate.dialect.SybaseASE15Dialect;
|
import org.hibernate.dialect.SybaseASE15Dialect;
|
||||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -44,6 +46,28 @@ public class TransactionUtil {
|
||||||
|
|
||||||
private static final Logger log = Logger.getLogger( TransactionUtil.class );
|
private static final Logger log = Logger.getLogger( TransactionUtil.class );
|
||||||
|
|
||||||
|
public static void doInHibernate(Supplier<SessionFactory> factorySupplier, Consumer<Session> function) {
|
||||||
|
final SessionFactory sessionFactory = factorySupplier.get();
|
||||||
|
Assert.assertNotNull( "SessionFactory is null in test!", sessionFactory );
|
||||||
|
//Make sure any error is propagated
|
||||||
|
try ( Session session = sessionFactory.openSession() ) {
|
||||||
|
final Transaction txn = session.getTransaction();
|
||||||
|
txn.begin();
|
||||||
|
try {
|
||||||
|
function.accept( session );
|
||||||
|
}
|
||||||
|
catch (Throwable e) {
|
||||||
|
try {
|
||||||
|
txn.rollback();
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
txn.commit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hibernate transaction function
|
* Hibernate transaction function
|
||||||
*
|
*
|
||||||
|
|
|
@ -294,7 +294,13 @@ public class JPAMetaModelEntityProcessor extends AbstractProcessor {
|
||||||
TypeMirror collectionElementType = TypeUtils.getCollectionElementType(
|
TypeMirror collectionElementType = TypeUtils.getCollectionElementType(
|
||||||
declaredType, fqNameOfReturnType, null, context
|
declaredType, fqNameOfReturnType, null, context
|
||||||
);
|
);
|
||||||
returnedElement = (TypeElement) context.getTypeUtils().asElement( collectionElementType );
|
|
||||||
|
final Element collectionElement = context.getTypeUtils().asElement( collectionElementType );
|
||||||
|
if ( ElementKind.TYPE_PARAMETER.equals( collectionElement.getKind() ) ) {
|
||||||
|
return Boolean.FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
returnedElement = (TypeElement) collectionElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( type.getQualifiedName().toString().equals( returnedElement.getQualifiedName().toString() ) ) {
|
if ( type.getQualifiedName().toString().equals( returnedElement.getQualifiedName().toString() ) ) {
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
/*
|
||||||
|
* 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.jpamodelgen.test.embeddable.generics;
|
||||||
|
|
||||||
|
import javax.persistence.Embeddable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Chris Cranford
|
||||||
|
*/
|
||||||
|
@Embeddable
|
||||||
|
public class ChildEmbeddable extends ParentEmbeddable<MyTypeImpl> {
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
* 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.jpamodelgen.test.embeddable.generics;
|
||||||
|
|
||||||
|
import org.hibernate.jpamodelgen.test.util.CompilationTest;
|
||||||
|
import org.hibernate.jpamodelgen.test.util.TestForIssue;
|
||||||
|
import org.hibernate.jpamodelgen.test.util.TestUtil;
|
||||||
|
import org.hibernate.jpamodelgen.test.util.WithClasses;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.hibernate.jpamodelgen.test.util.TestUtil.assertMetamodelClassGeneratedFor;
|
||||||
|
import static org.hibernate.jpamodelgen.test.util.TestUtil.assertSetAttributeTypeInMetaModelFor;
|
||||||
|
import static org.hibernate.jpamodelgen.test.util.TestUtil.assertSuperClassRelationShipInMetamodel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Chris Cranford
|
||||||
|
*/
|
||||||
|
@TestForIssue(jiraKey = "HHH_12030")
|
||||||
|
public class EmbeddableGenericsTest extends CompilationTest {
|
||||||
|
@Test
|
||||||
|
@WithClasses({ ChildEmbeddable.class, ParentEmbeddable.class })
|
||||||
|
public void testGeneratingEmbeddablesWithGenerics() {
|
||||||
|
assertMetamodelClassGeneratedFor( ChildEmbeddable.class );
|
||||||
|
assertMetamodelClassGeneratedFor( ParentEmbeddable.class );
|
||||||
|
|
||||||
|
assertSetAttributeTypeInMetaModelFor(
|
||||||
|
ParentEmbeddable.class,
|
||||||
|
"fields",
|
||||||
|
MyTypeInterface.class,
|
||||||
|
"Expected Set<MyTypeInterface> for attribute named 'fields'"
|
||||||
|
);
|
||||||
|
|
||||||
|
assertSuperClassRelationShipInMetamodel(
|
||||||
|
ChildEmbeddable.class,
|
||||||
|
ParentEmbeddable.class
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
/*
|
||||||
|
* 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.jpamodelgen.test.embeddable.generics;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Chris Cranford
|
||||||
|
*/
|
||||||
|
public class MyTypeImpl implements MyTypeInterface {
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
/*
|
||||||
|
* 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.jpamodelgen.test.embeddable.generics;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Chris Cranford
|
||||||
|
*/
|
||||||
|
public interface MyTypeInterface {
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
* 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.jpamodelgen.test.embeddable.generics;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.persistence.Embeddable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Chris Cranford
|
||||||
|
*/
|
||||||
|
@Embeddable
|
||||||
|
public class ParentEmbeddable<MyType extends MyTypeInterface> {
|
||||||
|
private Set<MyType> fields;
|
||||||
|
|
||||||
|
public Set<MyType> getFields() {
|
||||||
|
return fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFields(Set<MyType> fields) {
|
||||||
|
this.fields = fields;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue