* Added JpaCompliance for @OrderBy handling
* Added `NonTransientException` checked during MappingModelCreationProcess "post init callback" handling to indicate non-recoverable errors * Redesigned `MappingModelCreationProcess#executePostInitCallbacks` to account for `NonTransientException`
This commit is contained in:
parent
d180cb63d2
commit
41093ae66c
|
@ -102,4 +102,8 @@
|
|||
|90005700
|
||||
|org.hibernate.envers.boot.EnversBootLogger
|
||||
|
||||
|90005701
|
||||
|90005800
|
||||
|org.hibernate.metamodel.mapping.MappingModelCreationLogger
|
||||
|
||||
|===
|
||||
|
|
|
@ -728,6 +728,11 @@ public interface SessionFactoryBuilder {
|
|||
*/
|
||||
SessionFactoryBuilder enableJpaQueryCompliance(boolean enabled);
|
||||
|
||||
/**
|
||||
* @see JpaCompliance#isJpaQueryComplianceEnabled()
|
||||
*/
|
||||
SessionFactoryBuilder enableJpaOrderByMappingCompliance(boolean enabled);
|
||||
|
||||
/**
|
||||
* @see JpaCompliance#isJpaTransactionComplianceEnabled()
|
||||
*/
|
||||
|
|
|
@ -416,6 +416,12 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SessionFactoryBuilder enableJpaOrderByMappingCompliance(boolean enabled) {
|
||||
this.optionsBuilder.enableJpaOrderByMappingCompliance( enabled );
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SessionFactoryBuilder enableJpaTransactionCompliance(boolean enabled) {
|
||||
this.optionsBuilder.enableJpaTransactionCompliance( enabled );
|
||||
|
|
|
@ -1478,6 +1478,14 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
|
|||
mutableJpaCompliance().setCachingCompliance( enabled );
|
||||
}
|
||||
|
||||
public void enableJpaOrderByMappingCompliance(boolean enabled) {
|
||||
mutableJpaCompliance().setOrderByMappingCompliance( enabled );
|
||||
}
|
||||
|
||||
public void enableGeneratorNameScopeCompliance(boolean enabled) {
|
||||
mutableJpaCompliance().setGeneratorNameScopeCompliance( enabled );
|
||||
}
|
||||
|
||||
public void disableRefreshDetachedEntity() {
|
||||
this.allowRefreshDetachedEntity = false;
|
||||
}
|
||||
|
|
|
@ -394,6 +394,12 @@ public abstract class AbstractDelegatingSessionFactoryBuilder<T extends SessionF
|
|||
return getThis();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SessionFactoryBuilder enableJpaOrderByMappingCompliance(boolean enabled) {
|
||||
delegate.enableJpaOrderByMappingCompliance( enabled );
|
||||
return getThis();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SessionFactoryBuilder enableJpaTransactionCompliance(boolean enabled) {
|
||||
delegate.enableJpaTransactionCompliance( enabled );
|
||||
|
|
|
@ -2006,6 +2006,19 @@ public interface AvailableSettings extends org.hibernate.jpa.AvailableSettings {
|
|||
*/
|
||||
String JPA_LIST_COMPLIANCE = "hibernate.jpa.compliance.list";
|
||||
|
||||
/**
|
||||
* Controls whether Hibernate should recognize what it considers a "bag"
|
||||
* ({@link org.hibernate.collection.internal.PersistentBag}) as a List
|
||||
* ({@link org.hibernate.collection.internal.PersistentList}) or as a bag.
|
||||
*
|
||||
* If enabled, we will recognize it as a List where {@link javax.persistence.OrderColumn}
|
||||
* is just missing (and its defaults will apply).
|
||||
*
|
||||
* @see JpaCompliance#isJpaOrderByMappingComplianceEnabled() ()
|
||||
* @since 6.0
|
||||
*/
|
||||
String JPA_ORDER_BY_MAPPING_COMPLIANCE = "hibernate.jpa.compliance.orderby";
|
||||
|
||||
/**
|
||||
* JPA defines specific exceptions on specific methods when called on
|
||||
* {@link javax.persistence.EntityManager} and {@link javax.persistence.EntityManagerFactory}
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Contract for exceptions describing JPA compliance violations
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface JpaComplianceViolation {
|
||||
}
|
|
@ -12,22 +12,24 @@ import org.hibernate.jpa.spi.JpaCompliance;
|
|||
* @author Andrea Boriero
|
||||
*/
|
||||
public class JpaComplianceImpl implements JpaCompliance {
|
||||
private boolean queryCompliance;
|
||||
private boolean transactionCompliance;
|
||||
private boolean listCompliance;
|
||||
private boolean closedCompliance;
|
||||
private boolean proxyCompliance;
|
||||
private boolean cachingCompliance;
|
||||
private boolean globalGeneratorNameScopeCompliance;
|
||||
private final boolean listCompliance;
|
||||
private final boolean orderByMappingCompliance;
|
||||
private final boolean proxyCompliance;
|
||||
private final boolean globalGeneratorNameScopeCompliance;
|
||||
private final boolean queryCompliance;
|
||||
private final boolean transactionCompliance;
|
||||
private final boolean closedCompliance;
|
||||
private final boolean cachingCompliance;
|
||||
|
||||
private JpaComplianceImpl(
|
||||
boolean listCompliance,
|
||||
boolean orderByMappingCompliance,
|
||||
boolean proxyCompliance,
|
||||
boolean globalGeneratorNameScopeCompliance,
|
||||
boolean queryCompliance,
|
||||
boolean transactionCompliance,
|
||||
boolean listCompliance,
|
||||
boolean closedCompliance,
|
||||
boolean proxyCompliance,
|
||||
boolean cachingCompliance,
|
||||
boolean globalGeneratorNameScopeCompliance) {
|
||||
boolean cachingCompliance) {
|
||||
this.queryCompliance = queryCompliance;
|
||||
this.transactionCompliance = transactionCompliance;
|
||||
this.listCompliance = listCompliance;
|
||||
|
@ -35,6 +37,7 @@ public class JpaComplianceImpl implements JpaCompliance {
|
|||
this.proxyCompliance = proxyCompliance;
|
||||
this.cachingCompliance = cachingCompliance;
|
||||
this.globalGeneratorNameScopeCompliance = globalGeneratorNameScopeCompliance;
|
||||
this.orderByMappingCompliance = orderByMappingCompliance;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -72,18 +75,39 @@ public class JpaComplianceImpl implements JpaCompliance {
|
|||
return globalGeneratorNameScopeCompliance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isJpaOrderByMappingComplianceEnabled() {
|
||||
return orderByMappingCompliance;
|
||||
}
|
||||
|
||||
public static class JpaComplianceBuilder {
|
||||
private boolean queryCompliance;
|
||||
private boolean transactionCompliance;
|
||||
private boolean listCompliance;
|
||||
private boolean closedCompliance;
|
||||
private boolean orderByMappingCompliance;
|
||||
private boolean proxyCompliance;
|
||||
private boolean cachingCompliance;
|
||||
private boolean globalGeneratorNameScopeCompliance;
|
||||
private boolean cachingCompliance;
|
||||
private boolean transactionCompliance;
|
||||
private boolean closedCompliance;
|
||||
|
||||
public JpaComplianceBuilder() {
|
||||
}
|
||||
|
||||
public JpaComplianceBuilder setListCompliance(boolean listCompliance) {
|
||||
this.listCompliance = listCompliance;
|
||||
return this;
|
||||
}
|
||||
|
||||
public JpaComplianceBuilder setOrderByMappingCompliance(boolean orderByMappingCompliance) {
|
||||
this.orderByMappingCompliance = orderByMappingCompliance;
|
||||
return this;
|
||||
}
|
||||
|
||||
public JpaComplianceBuilder setProxyCompliance(boolean proxyCompliance) {
|
||||
this.proxyCompliance = proxyCompliance;
|
||||
return this;
|
||||
}
|
||||
|
||||
public JpaComplianceBuilder setQueryCompliance(boolean queryCompliance) {
|
||||
this.queryCompliance = queryCompliance;
|
||||
return this;
|
||||
|
@ -94,21 +118,11 @@ public class JpaComplianceImpl implements JpaCompliance {
|
|||
return this;
|
||||
}
|
||||
|
||||
public JpaComplianceBuilder setListCompliance(boolean listCompliance) {
|
||||
this.listCompliance = listCompliance;
|
||||
return this;
|
||||
}
|
||||
|
||||
public JpaComplianceBuilder setClosedCompliance(boolean closedCompliance) {
|
||||
this.closedCompliance = closedCompliance;
|
||||
return this;
|
||||
}
|
||||
|
||||
public JpaComplianceBuilder setProxyCompliance(boolean proxyCompliance) {
|
||||
this.proxyCompliance = proxyCompliance;
|
||||
return this;
|
||||
}
|
||||
|
||||
public JpaComplianceBuilder setCachingCompliance(boolean cachingCompliance) {
|
||||
this.cachingCompliance = cachingCompliance;
|
||||
return this;
|
||||
|
@ -121,13 +135,14 @@ public class JpaComplianceImpl implements JpaCompliance {
|
|||
|
||||
JpaCompliance createJpaCompliance() {
|
||||
return new JpaComplianceImpl(
|
||||
listCompliance,
|
||||
orderByMappingCompliance,
|
||||
proxyCompliance,
|
||||
globalGeneratorNameScopeCompliance,
|
||||
queryCompliance,
|
||||
transactionCompliance,
|
||||
listCompliance,
|
||||
closedCompliance,
|
||||
proxyCompliance,
|
||||
cachingCompliance,
|
||||
globalGeneratorNameScopeCompliance
|
||||
cachingCompliance
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,50 +17,60 @@ import org.hibernate.jpa.spi.MutableJpaCompliance;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class MutableJpaComplianceImpl implements MutableJpaCompliance {
|
||||
private boolean listCompliance;
|
||||
private boolean orderByMappingCompliance;
|
||||
private boolean proxyCompliance;
|
||||
private boolean generatorNameScopeCompliance;
|
||||
private boolean queryCompliance;
|
||||
private boolean transactionCompliance;
|
||||
private boolean listCompliance;
|
||||
private boolean closedCompliance;
|
||||
private boolean proxyCompliance;
|
||||
private boolean cachingCompliance;
|
||||
private final boolean globalGeneratorNameScopeCompliance;
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
public MutableJpaComplianceImpl(Map configurationSettings, boolean jpaByDefault) {
|
||||
final Object legacyQueryCompliance = configurationSettings.get( AvailableSettings.JPAQL_STRICT_COMPLIANCE );
|
||||
|
||||
queryCompliance = ConfigurationHelper.getBoolean(
|
||||
AvailableSettings.JPA_QUERY_COMPLIANCE,
|
||||
configurationSettings,
|
||||
ConfigurationHelper.toBoolean( legacyQueryCompliance, jpaByDefault )
|
||||
);
|
||||
transactionCompliance = ConfigurationHelper.getBoolean(
|
||||
AvailableSettings.JPA_TRANSACTION_COMPLIANCE,
|
||||
configurationSettings,
|
||||
jpaByDefault
|
||||
);
|
||||
listCompliance = ConfigurationHelper.getBoolean(
|
||||
AvailableSettings.JPA_LIST_COMPLIANCE,
|
||||
configurationSettings,
|
||||
jpaByDefault
|
||||
);
|
||||
closedCompliance = ConfigurationHelper.getBoolean(
|
||||
AvailableSettings.JPA_CLOSED_COMPLIANCE,
|
||||
configurationSettings,
|
||||
jpaByDefault
|
||||
);
|
||||
proxyCompliance = ConfigurationHelper.getBoolean(
|
||||
AvailableSettings.JPA_PROXY_COMPLIANCE,
|
||||
configurationSettings,
|
||||
jpaByDefault
|
||||
);
|
||||
cachingCompliance = ConfigurationHelper.getBoolean(
|
||||
AvailableSettings.JPA_CACHING_COMPLIANCE,
|
||||
generatorNameScopeCompliance = ConfigurationHelper.getBoolean(
|
||||
AvailableSettings.JPA_ID_GENERATOR_GLOBAL_SCOPE_COMPLIANCE,
|
||||
configurationSettings,
|
||||
jpaByDefault
|
||||
);
|
||||
globalGeneratorNameScopeCompliance = ConfigurationHelper.getBoolean(
|
||||
AvailableSettings.JPA_ID_GENERATOR_GLOBAL_SCOPE_COMPLIANCE,
|
||||
orderByMappingCompliance = ConfigurationHelper.getBoolean(
|
||||
AvailableSettings.JPA_ORDER_BY_MAPPING_COMPLIANCE,
|
||||
configurationSettings,
|
||||
jpaByDefault
|
||||
);
|
||||
|
||||
queryCompliance = ConfigurationHelper.getBoolean(
|
||||
AvailableSettings.JPA_QUERY_COMPLIANCE,
|
||||
configurationSettings,
|
||||
ConfigurationHelper.toBoolean( legacyQueryCompliance, jpaByDefault )
|
||||
);
|
||||
|
||||
transactionCompliance = ConfigurationHelper.getBoolean(
|
||||
AvailableSettings.JPA_TRANSACTION_COMPLIANCE,
|
||||
configurationSettings,
|
||||
jpaByDefault
|
||||
);
|
||||
|
||||
closedCompliance = ConfigurationHelper.getBoolean(
|
||||
AvailableSettings.JPA_CLOSED_COMPLIANCE,
|
||||
configurationSettings,
|
||||
jpaByDefault
|
||||
);
|
||||
|
||||
cachingCompliance = ConfigurationHelper.getBoolean(
|
||||
AvailableSettings.JPA_CACHING_COMPLIANCE,
|
||||
configurationSettings,
|
||||
jpaByDefault
|
||||
);
|
||||
|
@ -98,46 +108,69 @@ public class MutableJpaComplianceImpl implements MutableJpaCompliance {
|
|||
|
||||
@Override
|
||||
public boolean isGlobalGeneratorScopeEnabled() {
|
||||
return globalGeneratorNameScopeCompliance;
|
||||
return generatorNameScopeCompliance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isJpaOrderByMappingComplianceEnabled() {
|
||||
return orderByMappingCompliance;
|
||||
}
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Mutators
|
||||
|
||||
public void setQueryCompliance(boolean queryCompliance) {
|
||||
this.queryCompliance = queryCompliance;
|
||||
}
|
||||
|
||||
public void setTransactionCompliance(boolean transactionCompliance) {
|
||||
this.transactionCompliance = transactionCompliance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setListCompliance(boolean listCompliance) {
|
||||
this.listCompliance = listCompliance;
|
||||
}
|
||||
|
||||
public void setClosedCompliance(boolean closedCompliance) {
|
||||
this.closedCompliance = closedCompliance;
|
||||
@Override
|
||||
public void setOrderByMappingCompliance(boolean orderByMappingCompliance) {
|
||||
this.orderByMappingCompliance = orderByMappingCompliance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProxyCompliance(boolean proxyCompliance) {
|
||||
this.proxyCompliance = proxyCompliance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGeneratorNameScopeCompliance(boolean enabled) {
|
||||
this.generatorNameScopeCompliance = enabled;
|
||||
}
|
||||
|
||||
public void setQueryCompliance(boolean queryCompliance) {
|
||||
this.queryCompliance = queryCompliance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTransactionCompliance(boolean transactionCompliance) {
|
||||
this.transactionCompliance = transactionCompliance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setClosedCompliance(boolean closedCompliance) {
|
||||
this.closedCompliance = closedCompliance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCachingCompliance(boolean cachingCompliance) {
|
||||
this.cachingCompliance = cachingCompliance;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public JpaCompliance immutableCopy() {
|
||||
JpaComplianceImpl.JpaComplianceBuilder builder = new JpaComplianceImpl.JpaComplianceBuilder();
|
||||
builder.setQueryCompliance( queryCompliance )
|
||||
.setTransactionCompliance( transactionCompliance )
|
||||
.setListCompliance( listCompliance )
|
||||
.setClosedCompliance( closedCompliance )
|
||||
builder = builder.setListCompliance( listCompliance )
|
||||
.setProxyCompliance( proxyCompliance )
|
||||
.setCachingCompliance( cachingCompliance )
|
||||
.setGlobalGeneratorNameCompliance( globalGeneratorNameScopeCompliance );
|
||||
.setOrderByMappingCompliance( orderByMappingCompliance )
|
||||
.setGlobalGeneratorNameCompliance( generatorNameScopeCompliance )
|
||||
.setQueryCompliance( queryCompliance )
|
||||
.setTransactionCompliance( transactionCompliance )
|
||||
.setClosedCompliance( closedCompliance )
|
||||
.setCachingCompliance( cachingCompliance );
|
||||
return builder.createJpaCompliance();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -97,4 +97,12 @@ public interface JpaCompliance {
|
|||
* @return {@code true} indicates the generator name scope is considered global.
|
||||
*/
|
||||
boolean isGlobalGeneratorScopeEnabled();
|
||||
|
||||
/**
|
||||
* Should we strictly handle {@link javax.persistence.OrderBy} expressions?
|
||||
*
|
||||
* JPA says the order-items can only be attribute references whereas Hibernate supports a wide range of items. With
|
||||
* this enabled, Hibernate will throw a compliance error when a non-attribute-reference is used.
|
||||
*/
|
||||
boolean isJpaOrderByMappingComplianceEnabled();
|
||||
}
|
||||
|
|
|
@ -10,17 +10,21 @@ package org.hibernate.jpa.spi;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface MutableJpaCompliance extends JpaCompliance {
|
||||
void setListCompliance(boolean listCompliance);
|
||||
|
||||
void setOrderByMappingCompliance(boolean orderByCompliance);
|
||||
|
||||
void setProxyCompliance(boolean proxyCompliance);
|
||||
|
||||
void setQueryCompliance(boolean queryCompliance);
|
||||
|
||||
void setTransactionCompliance(boolean transactionCompliance);
|
||||
|
||||
void setListCompliance(boolean listCompliance);
|
||||
|
||||
void setClosedCompliance(boolean closedCompliance);
|
||||
|
||||
void setProxyCompliance(boolean proxyCompliance);
|
||||
|
||||
void setCachingCompliance(boolean cachingCompliance);
|
||||
|
||||
void setGeneratorNameScopeCompliance(boolean generatorScopeCompliance);
|
||||
|
||||
JpaCompliance immutableCopy();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* 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.metamodel.mapping;
|
||||
|
||||
import org.hibernate.query.QueryLogger;
|
||||
|
||||
import org.jboss.logging.BasicLogger;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.jboss.logging.annotations.MessageLogger;
|
||||
import org.jboss.logging.annotations.ValidIdRange;
|
||||
|
||||
/**
|
||||
* Logger used during mapping-model creation
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@MessageLogger( projectCode = "HHH" )
|
||||
@ValidIdRange( min = 90005701, max = 90005800 )
|
||||
public interface MappingModelCreationLogger extends BasicLogger {
|
||||
String LOGGER_NAME = "org.hibernate.orm.model.mapping.creation";
|
||||
|
||||
MappingModelCreationLogger LOGGER = Logger.getMessageLogger( MappingModelCreationLogger.class, LOGGER_NAME );
|
||||
|
||||
boolean TRACE_ENABLED = LOGGER.isTraceEnabled();
|
||||
boolean DEBUG_ENABLED = LOGGER.isDebugEnabled();
|
||||
}
|
|
@ -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.metamodel.mapping;
|
||||
|
||||
/**
|
||||
* Marker interface for exceptions thrown during mapping-model creation which
|
||||
* are not transient errors - they will never succeed
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface NonTransientException {
|
||||
}
|
|
@ -61,6 +61,7 @@ import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
|
|||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||
import org.hibernate.metamodel.mapping.ManagedMappingType;
|
||||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
import org.hibernate.metamodel.mapping.NonTransientException;
|
||||
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.SingularAttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.StateArrayContributorMetadata;
|
||||
|
@ -793,7 +794,11 @@ public class MappingModelCreationHelper {
|
|||
catch (NotYetImplementedFor6Exception nye) {
|
||||
throw nye;
|
||||
}
|
||||
catch (Exception wait) {
|
||||
catch (Exception e) {
|
||||
if ( e instanceof NonTransientException ) {
|
||||
throw e;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,9 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.metamodel.mapping.MappingModelCreationLogger;
|
||||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
import org.hibernate.metamodel.mapping.NonTransientException;
|
||||
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
|
||||
|
@ -69,25 +71,40 @@ public class MappingModelCreationProcess {
|
|||
entityPersister.prepareMappingModel( this );
|
||||
}
|
||||
|
||||
executePostInitCallbakcs( postInitCallbacks );
|
||||
MappingModelCreationLogger.LOGGER.debugf( "Starting generic post-init callbacks" );
|
||||
executePostInitCallbacks( postInitCallbacks );
|
||||
|
||||
executePostInitCallbakcs( foreignKeyPostInitCallbacks );
|
||||
MappingModelCreationLogger.LOGGER.debugf( "Starting foreign-key post-init callbacks" );
|
||||
executePostInitCallbacks( foreignKeyPostInitCallbacks );
|
||||
}
|
||||
|
||||
private void executePostInitCallbakcs(List<PostInitCallback> postInitCallbacks) {
|
||||
private void executePostInitCallbacks(List<PostInitCallback> postInitCallbacks) {
|
||||
while ( postInitCallbacks != null && !postInitCallbacks.isEmpty() ) {
|
||||
// copy to avoid CCME
|
||||
final ArrayList<PostInitCallback> copy = new ArrayList<>( new ArrayList<>( postInitCallbacks ) );
|
||||
|
||||
for ( PostInitCallback callback : copy ) {
|
||||
final boolean completed = callback.process();
|
||||
if ( completed ) {
|
||||
postInitCallbacks.remove( callback );
|
||||
// copy to avoid CCME
|
||||
final ArrayList<PostInitCallback> copy = new ArrayList<>( postInitCallbacks );
|
||||
|
||||
for ( int i = 0; i < copy.size(); i++ ) {
|
||||
final PostInitCallback callback = copy.get( i );
|
||||
|
||||
try {
|
||||
final boolean completed = callback.process();
|
||||
if ( completed ) {
|
||||
postInitCallbacks.remove( callback );
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
if ( e instanceof NonTransientException ) {
|
||||
MappingModelCreationLogger.LOGGER.debugf( "Mapping-model creation encountered non-transient error : %s", e );
|
||||
throw e;
|
||||
}
|
||||
|
||||
MappingModelCreationLogger.LOGGER.debugf( "Mapping-model creation encountered (possibly) transient error : %s", e );
|
||||
}
|
||||
}
|
||||
|
||||
if ( copy.size() == postInitCallbacks.size() ) {
|
||||
// none of the processes could complete fully, this is an error
|
||||
// none of the remaining callbacks could complete fully, this is an error
|
||||
throw new IllegalStateException( "No post-init callbacks could complete" );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ import org.hibernate.engine.FetchStrategy;
|
|||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.engine.spi.CascadeStyle;
|
||||
import org.hibernate.engine.spi.LoadQueryInfluencers;
|
||||
import org.hibernate.jpa.spi.JpaCompliance;
|
||||
import org.hibernate.mapping.Collection;
|
||||
import org.hibernate.mapping.IndexedCollection;
|
||||
import org.hibernate.mapping.List;
|
||||
|
@ -246,6 +247,10 @@ public class PluralAttributeMappingImpl extends AbstractAttributeMapping impleme
|
|||
|
||||
if ( hasOrder || hasManyToManyOrder ) {
|
||||
final TranslationContext context = new TranslationContext() {
|
||||
@Override
|
||||
public JpaCompliance getJpaCompliance() {
|
||||
return collectionDescriptor.getFactory().getSessionFactoryOptions().getJpaCompliance();
|
||||
}
|
||||
};
|
||||
|
||||
if ( hasOrder ) {
|
||||
|
|
|
@ -6,10 +6,13 @@
|
|||
*/
|
||||
package org.hibernate.metamodel.mapping.ordering;
|
||||
|
||||
import org.hibernate.jpa.spi.JpaCompliance;
|
||||
|
||||
/**
|
||||
* Access to information needed while translating a collection's order-by fragment
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface TranslationContext {
|
||||
JpaCompliance getJpaCompliance();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* 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.metamodel.mapping.ordering.ast;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.jpa.JpaComplianceViolation;
|
||||
import org.hibernate.metamodel.mapping.NonTransientException;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class OrderByComplianceViolation extends HibernateException implements JpaComplianceViolation, NonTransientException {
|
||||
public OrderByComplianceViolation(String message) {
|
||||
super( message );
|
||||
}
|
||||
|
||||
public OrderByComplianceViolation(String message, Throwable cause) {
|
||||
super( message, cause );
|
||||
}
|
||||
}
|
|
@ -17,16 +17,12 @@ import org.hibernate.grammars.ordering.OrderingParserBaseVisitor;
|
|||
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.ordering.TranslationContext;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.antlr.v4.runtime.tree.TerminalNode;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class ParseTreeVisitor extends OrderingParserBaseVisitor {
|
||||
private static final Logger log = Logger.getLogger( ParseTreeVisitor.class );
|
||||
|
||||
public class ParseTreeVisitor extends OrderingParserBaseVisitor<Object> {
|
||||
private final PathConsumer pathConsumer;
|
||||
private final TranslationContext translationContext;
|
||||
|
||||
|
@ -60,7 +56,21 @@ public class ParseTreeVisitor extends OrderingParserBaseVisitor {
|
|||
assert parsedSpec != null;
|
||||
assert parsedSpec.expression() != null;
|
||||
|
||||
final OrderingSpecification result = new OrderingSpecification( visitExpression( parsedSpec.expression() ) );
|
||||
final OrderingExpression orderingExpression = visitExpression( parsedSpec.expression() );
|
||||
if ( translationContext.getJpaCompliance().isJpaOrderByMappingComplianceEnabled() ) {
|
||||
if ( orderingExpression instanceof DomainPath ) {
|
||||
// nothing to do
|
||||
}
|
||||
else {
|
||||
throw new OrderByComplianceViolation(
|
||||
"`@OrderBy` expression (" + parsedSpec.expression().getText()
|
||||
+ ") resolved to `" + orderingExpression
|
||||
+ "` which is not a domain-model reference which violates the JPA specification"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
final OrderingSpecification result = new OrderingSpecification( orderingExpression );
|
||||
|
||||
if ( parsedSpec.collationSpecification() != null ) {
|
||||
result.setCollation( parsedSpec.collationSpecification().identifier().getText() );
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
import org.hibernate.jpa.spi.JpaCompliance;
|
||||
|
||||
/**
|
||||
* Stubbed impl of JpaCompliance
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class JpaComplianceStub implements JpaCompliance {
|
||||
@Override
|
||||
public boolean isJpaQueryComplianceEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isJpaTransactionComplianceEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isJpaListComplianceEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isJpaClosedComplianceEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isJpaProxyComplianceEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isJpaCacheComplianceEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGlobalGeneratorScopeEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isJpaOrderByMappingComplianceEnabled() {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -47,6 +47,7 @@ public class JpaComplianceTestingImpl implements JpaCompliance {
|
|||
private boolean proxyCompliance;
|
||||
private boolean cacheCompliance;
|
||||
private boolean idGeneratorNameScopeCompliance;
|
||||
private boolean orderByCompliance;
|
||||
|
||||
@Override
|
||||
public boolean isJpaQueryComplianceEnabled() {
|
||||
|
@ -63,6 +64,11 @@ public class JpaComplianceTestingImpl implements JpaCompliance {
|
|||
return listCompliance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isJpaOrderByMappingComplianceEnabled() {
|
||||
return orderByCompliance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isJpaClosedComplianceEnabled() {
|
||||
return closedCompliance;
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* 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.binding.annotations.plural.orderby.compliance;
|
||||
|
||||
import java.util.Set;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.OrderBy;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.boot.Metadata;
|
||||
import org.hibernate.boot.MetadataSources;
|
||||
import org.hibernate.boot.SessionFactoryBuilder;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.metamodel.mapping.ordering.ast.OrderByComplianceViolation;
|
||||
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.DomainModelScope;
|
||||
import org.hibernate.testing.orm.junit.ServiceRegistry;
|
||||
import org.hibernate.testing.transaction.TransactionUtil2;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class OrderByMappingComplianceTest {
|
||||
|
||||
@Test
|
||||
public void testComplianceChecking() {
|
||||
check( false );
|
||||
|
||||
try {
|
||||
check( true );
|
||||
fail( "Expecting an exception" );
|
||||
}
|
||||
catch (OrderByComplianceViolation expected) {
|
||||
// nothing to do
|
||||
}
|
||||
}
|
||||
|
||||
private void check(boolean complianceEnabled) {
|
||||
final StandardServiceRegistry ssr = new StandardServiceRegistryBuilder()
|
||||
.applySetting( AvailableSettings.HBM2DDL_AUTO, "create-drop" )
|
||||
.build();
|
||||
|
||||
try {
|
||||
final Metadata bootModel = new MetadataSources( ssr )
|
||||
.addAnnotatedClass( Order.class )
|
||||
.addAnnotatedClass( LineItem.class )
|
||||
.buildMetadata();
|
||||
|
||||
final SessionFactory sf = bootModel.getSessionFactoryBuilder()
|
||||
.enableJpaOrderByMappingCompliance( complianceEnabled )
|
||||
.build();
|
||||
|
||||
try {
|
||||
TransactionUtil2.inTransaction(
|
||||
(SessionFactoryImplementor) sf,
|
||||
session -> session.createQuery( "from Order" ).list()
|
||||
);
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
sf.close();
|
||||
}
|
||||
catch (Exception ignore) {
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
StandardServiceRegistryBuilder.destroy( ssr );
|
||||
}
|
||||
}
|
||||
|
||||
@Entity( name = "Order" )
|
||||
@Table( name = "orders" )
|
||||
public static class Order {
|
||||
@Id
|
||||
private Integer id;
|
||||
private String invoice;
|
||||
@OneToMany
|
||||
@OrderBy( "qty" )
|
||||
private Set<LineItem> lineItems;
|
||||
}
|
||||
|
||||
@Entity( name = "LineItem" )
|
||||
@Table( name = "line_items" )
|
||||
public static class LineItem {
|
||||
@Id
|
||||
private Integer id;
|
||||
private String sku;
|
||||
@Column( name = "qty" )
|
||||
private int quantity;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue