Various fixes from Search integration testing

- do not cache Criteria query plans (added Trello card to revisit)
  - support for StatelessSession in JUnit 5 extensions (SessionFactoryScope)
This commit is contained in:
Steve Ebersole 2020-10-30 12:04:52 -05:00
parent 23f64fc675
commit 4402843d1c
9 changed files with 225 additions and 150 deletions

View File

@ -17,6 +17,7 @@ import org.hibernate.jdbc.ReturningWork;
import org.hibernate.jdbc.Work; import org.hibernate.jdbc.Work;
import org.hibernate.procedure.ProcedureCall; import org.hibernate.procedure.ProcedureCall;
import org.hibernate.query.QueryProducer; import org.hibernate.query.QueryProducer;
import org.hibernate.query.criteria.HibernateCriteriaBuilder;
/** /**
* Contract methods shared between {@link Session} and {@link StatelessSession}. * Contract methods shared between {@link Session} and {@link StatelessSession}.
@ -153,7 +154,7 @@ public interface SharedSessionContract extends QueryProducer, Serializable {
* @return an instance of CriteriaBuilder * @return an instance of CriteriaBuilder
* @throws IllegalStateException if the StatelessSession has been closed * @throws IllegalStateException if the StatelessSession has been closed
*/ */
CriteriaBuilder getCriteriaBuilder(); HibernateCriteriaBuilder getCriteriaBuilder();
@Override @Override
<T> org.hibernate.query.Query<T> createQuery(String queryString, Class<T> resultType); <T> org.hibernate.query.Query<T> createQuery(String queryString, Class<T> resultType);

View File

@ -18,7 +18,6 @@ import javax.persistence.EntityManagerFactory;
import javax.persistence.FlushModeType; import javax.persistence.FlushModeType;
import javax.persistence.LockModeType; import javax.persistence.LockModeType;
import javax.persistence.StoredProcedureQuery; import javax.persistence.StoredProcedureQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaDelete; import javax.persistence.criteria.CriteriaDelete;
import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.CriteriaUpdate; import javax.persistence.criteria.CriteriaUpdate;
@ -54,6 +53,7 @@ import org.hibernate.jdbc.ReturningWork;
import org.hibernate.jdbc.Work; import org.hibernate.jdbc.Work;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.procedure.ProcedureCall; import org.hibernate.procedure.ProcedureCall;
import org.hibernate.query.criteria.HibernateCriteriaBuilder;
import org.hibernate.query.spi.QueryImplementor; import org.hibernate.query.spi.QueryImplementor;
import org.hibernate.query.spi.ScrollableResultsImplementor; import org.hibernate.query.spi.ScrollableResultsImplementor;
import org.hibernate.query.sql.spi.NativeQueryImplementor; import org.hibernate.query.sql.spi.NativeQueryImplementor;
@ -432,7 +432,7 @@ public class SessionDelegatorBaseImpl implements SessionImplementor {
} }
@Override @Override
public CriteriaBuilder getCriteriaBuilder() { public HibernateCriteriaBuilder getCriteriaBuilder() {
return delegate.getCriteriaBuilder(); return delegate.getCriteriaBuilder();
} }

View File

@ -15,7 +15,6 @@ import java.util.TimeZone;
import java.util.UUID; import java.util.UUID;
import javax.persistence.FlushModeType; import javax.persistence.FlushModeType;
import javax.persistence.TransactionRequiredException; import javax.persistence.TransactionRequiredException;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaDelete; import javax.persistence.criteria.CriteriaDelete;
import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.CriteriaUpdate; import javax.persistence.criteria.CriteriaUpdate;
@ -61,6 +60,7 @@ import org.hibernate.procedure.ProcedureCall;
import org.hibernate.procedure.internal.ProcedureCallImpl; import org.hibernate.procedure.internal.ProcedureCallImpl;
import org.hibernate.procedure.spi.NamedCallableQueryMemento; import org.hibernate.procedure.spi.NamedCallableQueryMemento;
import org.hibernate.query.Query; import org.hibernate.query.Query;
import org.hibernate.query.criteria.HibernateCriteriaBuilder;
import org.hibernate.query.hql.spi.HqlQueryImplementor; import org.hibernate.query.hql.spi.HqlQueryImplementor;
import org.hibernate.query.hql.spi.NamedHqlQueryMemento; import org.hibernate.query.hql.spi.NamedHqlQueryMemento;
import org.hibernate.query.named.NamedResultSetMappingMemento; import org.hibernate.query.named.NamedResultSetMappingMemento;
@ -908,7 +908,7 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
} }
@Override @Override
public CriteriaBuilder getCriteriaBuilder() { public HibernateCriteriaBuilder getCriteriaBuilder() {
checkOpen(); checkOpen();
return getFactory().getCriteriaBuilder(); return getFactory().getCriteriaBuilder();
} }

View File

@ -72,6 +72,11 @@ public class QuerySqmImpl<R>
extends AbstractQuery<R> extends AbstractQuery<R>
implements HqlQueryImplementor<R>, ExecutionContext { implements HqlQueryImplementor<R>, ExecutionContext {
/**
* The value used for {@link #getQueryString} for Criteria-based queries
*/
public static final String CRITERIA_HQL_STRING = "<criteria>";
private final String hqlString; private final String hqlString;
private final SqmStatement sqmStatement; private final SqmStatement sqmStatement;
private final Class resultType; private final Class resultType;
@ -212,7 +217,7 @@ public class QuerySqmImpl<R>
throw new IllegalArgumentException( "Non-select queries cannot be typed" ); throw new IllegalArgumentException( "Non-select queries cannot be typed" );
} }
this.hqlString = "<criteria>"; this.hqlString = CRITERIA_HQL_STRING;
this.sqmStatement = sqmStatement; this.sqmStatement = sqmStatement;
this.resultType = resultType; this.resultType = resultType;

View File

@ -21,7 +21,7 @@ import org.hibernate.query.spi.QueryInterpretationCache;
public class SqmInterpretationsKey implements QueryInterpretationCache.Key { public class SqmInterpretationsKey implements QueryInterpretationCache.Key {
@SuppressWarnings("WeakerAccess") @SuppressWarnings("WeakerAccess")
public static SqmInterpretationsKey generateFrom(QuerySqmImpl query) { public static SqmInterpretationsKey generateFrom(QuerySqmImpl query) {
if ( !isCacheable( query ) ) { if ( ! isCacheable( query ) ) {
return null; return null;
} }
@ -45,6 +45,13 @@ public class SqmInterpretationsKey implements QueryInterpretationCache.Key {
private static boolean isCacheable(QuerySqmImpl<?> query) { private static boolean isCacheable(QuerySqmImpl<?> query) {
assert query.getQueryOptions().getAppliedGraph() != null; assert query.getQueryOptions().getAppliedGraph() != null;
if ( QuerySqmImpl.CRITERIA_HQL_STRING.equals( query.getQueryString() ) ) {
// for now at least, skip caching Criteria-based plans
// - especially wrt parameters atm; this works with HQL because the parameters
// are part of the query string; with Criteria, they are not.
return false;
}
if ( query.getSession().getLoadQueryInfluencers().hasEnabledFilters() ) { if ( query.getSession().getLoadQueryInfluencers().hasEnabledFilters() ) {
// At the moment we cannot cache query plan if there is filter enabled. // At the moment we cannot cache query plan if there is filter enabled.
return false; return false;

View File

@ -25,12 +25,13 @@ import org.hibernate.metamodel.model.domain.MapPersistentAttribute;
import org.hibernate.metamodel.model.domain.PluralPersistentAttribute; import org.hibernate.metamodel.model.domain.PluralPersistentAttribute;
import org.hibernate.metamodel.model.domain.SingularPersistentAttribute; import org.hibernate.metamodel.model.domain.SingularPersistentAttribute;
import org.hibernate.query.NavigablePath; import org.hibernate.query.NavigablePath;
import org.hibernate.query.hql.spi.SqmCreationState;
import org.hibernate.query.sqm.IllegalPathUsageException; import org.hibernate.query.sqm.IllegalPathUsageException;
import org.hibernate.query.sqm.NodeBuilder; import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.hql.spi.SqmCreationState;
import org.hibernate.query.sqm.tree.expression.AbstractSqmExpression; import org.hibernate.query.sqm.tree.expression.AbstractSqmExpression;
import org.hibernate.query.sqm.tree.expression.SqmExpression; import org.hibernate.query.sqm.tree.expression.SqmExpression;
import org.hibernate.type.BasicType;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor; import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
/** /**
@ -217,24 +218,32 @@ public abstract class AbstractSqmPath<T> extends AbstractSqmExpression<T> implem
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public SqmPath get(String attributeName) { public SqmPath<?> get(String attributeName) {
// todo (6.0) : this is similar to the idea of creating an SqmExpression for a Navigable // todo (6.0) : this is similar to the idea of creating an SqmExpression for a Navigable
// should make these stylistically consistent, either - // should make these stylistically consistent, either -
// 1) add `Navigable#createCriteriaExpression` (ala, the exist `#createSqmExpression`) // 1) add `Navigable#createCriteriaExpression` (ala, the exist `#createSqmExpression`)
// 2) remove `Navigable#createSqmExpression` and use the approach used here instead. // 2) remove `Navigable#createSqmExpression` and use the approach used here instead.
if ( getReferencedPathSource().getSqmPathType() instanceof BasicType ) {
throw new IllegalStateException( "Cannot resolve path `" + attributeName + "` relative to a basic-valued path: `" + getNavigablePath() + "`" );
}
return resolvePath( return resolvePath(
attributeName, attributeName,
(pathSource, name) -> { (pathSource, name) -> {
final SqmPathSource subNavigable = getReferencedPathSource().findSubPathSource( attributeName ); final SqmPathSource<?> subNavigable = getReferencedPathSource().findSubPathSource( attributeName );
if ( subNavigable == null ) {
throw new IllegalArgumentException( "Could not resolve attribute named `" + attributeName + "` relative to `" + getNavigablePath() + "`" );
}
if ( subNavigable instanceof SingularPersistentAttribute ) { if ( subNavigable instanceof SingularPersistentAttribute ) {
return createSingularPath( (SingularPersistentAttribute) subNavigable ); return createSingularPath( (SingularPersistentAttribute<?,?>) subNavigable );
} }
else { else {
assert subNavigable instanceof PluralPersistentAttribute; assert subNavigable instanceof PluralPersistentAttribute;
return createPluralPath( (PluralPersistentAttribute) subNavigable ); return createPluralPath( (PluralPersistentAttribute<?,?,?>) subNavigable );
} }
} }
); );

View File

@ -6,175 +6,153 @@
*/ */
package org.hibernate.orm.test.query.criteria; package org.hibernate.orm.test.query.criteria;
import java.util.List;
import java.util.Map;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.ParameterExpression; import javax.persistence.criteria.ParameterExpression;
import javax.persistence.criteria.Root; import javax.persistence.criteria.Root;
import org.hibernate.IrrelevantEntity;
import org.hibernate.query.criteria.HibernateCriteriaBuilder; import org.hibernate.query.criteria.HibernateCriteriaBuilder;
import org.hibernate.query.criteria.JpaCriteriaQuery; import org.hibernate.query.criteria.JpaCriteriaQuery;
import org.hibernate.query.criteria.JpaRoot; import org.hibernate.query.criteria.JpaRoot;
import org.hibernate.query.spi.QueryParameterImplementor;
import org.hibernate.query.sqm.tree.expression.SqmParameter;
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase; import org.hibernate.testing.orm.domain.gambit.BasicEntity;
import org.junit.Test; import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;
/** @DomainModel( annotatedClasses = BasicEntity.class )
* @author Steve Ebersole @SessionFactory
*/ public class BasicCriteriaExecutionTests {
public class BasicCriteriaExecutionTests extends BaseNonConfigCoreFunctionalTestCase {
@Override
protected Class[] getAnnotatedClasses() {
return new Class[] { BasicEntity.class };
}
@Test @Test
public void testExecutingBasicCriteriaQuery() { public void testExecutingBasicCriteriaQuery(SessionFactoryScope scope) {
final CriteriaBuilder criteriaBuilder = sessionFactory().getCriteriaBuilder(); scope.inTransaction(
final CriteriaQuery<Object> criteria = criteriaBuilder.createQuery();
final Root<BasicEntity> root = criteria.from( BasicEntity.class );
criteria.select( root );
inSession(
session -> session.createQuery( criteria ).list()
);
}
@Test
public void testIt() {
inSession(
session -> { session -> {
CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder(); final HibernateCriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
CriteriaQuery<BasicEntity> criteria = criteriaBuilder.createQuery( BasicEntity.class );
criteria.from( BasicEntity.class ); final CriteriaQuery<Object> criteria = criteriaBuilder.createQuery();
List<BasicEntity> results = session.createQuery( criteria ).list(); final Root<BasicEntity> root = criteria.from( BasicEntity.class );
criteria.select( root );
session.createQuery( criteria ).list();
} }
); );
} }
@Test @Test
public void testExecutingBasicCriteriaQueryInStatelessSession() { public void testIt(SessionFactoryScope scope) {
final CriteriaBuilder criteriaBuilder = sessionFactory().getCriteriaBuilder(); scope.inTransaction(
session -> {
final CriteriaQuery<Object> criteria = criteriaBuilder.createQuery(); final HibernateCriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
CriteriaQuery<BasicEntity> criteria = criteriaBuilder.createQuery( BasicEntity.class );
final Root<BasicEntity> root = criteria.from( BasicEntity.class ); criteria.from( BasicEntity.class );
session.createQuery( criteria ).list();
criteria.select( root ); }
inStatelessSession(
session -> session.createQuery( criteria ).list()
); );
} }
@Test @Test
public void testExecutingBasicCriteriaQueryLiteralPredicate() { public void testExecutingBasicCriteriaQueryInStatelessSession(SessionFactoryScope scope) {
final CriteriaBuilder criteriaBuilder = sessionFactory().getCriteriaBuilder(); scope.inTransaction(
session -> {
final HibernateCriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
final CriteriaQuery<Object> criteria = criteriaBuilder.createQuery(); final CriteriaQuery<Object> criteria = criteriaBuilder.createQuery();
final Root<BasicEntity> root = criteria.from( BasicEntity.class );
criteria.select( root );
final Root<BasicEntity> root = criteria.from( BasicEntity.class ); session.createQuery( criteria ).list();
}
criteria.select( root );
criteria.where( criteriaBuilder.equal( criteriaBuilder.literal( 1 ), criteriaBuilder.literal( 1 ) ) );
inSession(
session -> session.createQuery( criteria ).list()
); );
} }
@Test @Test
public void testExecutingBasicCriteriaQueryLiteralPredicateInStatelessSession() { public void testExecutingBasicCriteriaQueryLiteralPredicate(SessionFactoryScope scope) {
final CriteriaBuilder criteriaBuilder = sessionFactory().getCriteriaBuilder(); scope.inTransaction(
session -> {
final HibernateCriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
final CriteriaQuery<Object> criteria = criteriaBuilder.createQuery(); final CriteriaQuery<Object> criteria = criteriaBuilder.createQuery();
final Root<BasicEntity> root = criteria.from( BasicEntity.class );
criteria.select( root );
criteria.where(
criteriaBuilder.equal(
criteriaBuilder.literal( 1 ),
criteriaBuilder.literal( 1 )
)
);
final Root<BasicEntity> root = criteria.from( BasicEntity.class ); session.createQuery( criteria ).list();
}
criteria.select( root );
criteria.where( criteriaBuilder.equal( criteriaBuilder.literal( 1 ), criteriaBuilder.literal( 1 ) ) );
inStatelessSession(
session -> session.createQuery( criteria ).list()
); );
} }
@Test @Test
public void testExecutingBasicCriteriaQueryParameterPredicate() { public void testExecutingBasicCriteriaQueryLiteralPredicateInStatelessSession(SessionFactoryScope scope) {
final CriteriaBuilder criteriaBuilder = sessionFactory().getCriteriaBuilder(); scope.inStatelessTransaction(
session -> {
final CriteriaQuery<Object> criteria = criteriaBuilder.createQuery(); final HibernateCriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
final CriteriaQuery<Object> criteria = criteriaBuilder.createQuery();
final Root<BasicEntity> root = criteria.from( BasicEntity.class ); final Root<BasicEntity> root = criteria.from( BasicEntity.class );
criteria.select( root );
criteria.select( root ); criteria.where(
criteriaBuilder.equal(
Map<QueryParameterImplementor,Map<SqmParameter, List<JdbcParameter>>> parameterResolutionMap; criteriaBuilder.literal( 1 ),
criteriaBuilder.literal( 1 )
final ParameterExpression<Integer> param = criteriaBuilder.parameter( Integer.class ); )
);
criteria.where( criteriaBuilder.equal( param, param ) ); session.createQuery( criteria ).list();
}
inSession(
session -> session.createQuery( criteria ).setParameter( param, 1 ).list()
); );
} }
@Test @Test
public void testExecutingBasicCriteriaQueryParameterPredicateInStatelessSession() { public void testExecutingBasicCriteriaQueryParameterPredicate(SessionFactoryScope scope) {
final CriteriaBuilder criteriaBuilder = sessionFactory().getCriteriaBuilder(); scope.inStatelessTransaction(
session -> {
final HibernateCriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
final CriteriaQuery<Object> criteria = criteriaBuilder.createQuery(); final CriteriaQuery<Object> criteria = criteriaBuilder.createQuery();
final Root<BasicEntity> root = criteria.from( BasicEntity.class );
criteria.select( root );
final ParameterExpression<Integer> param = criteriaBuilder.parameter( Integer.class );
criteria.where( criteriaBuilder.equal( param, param ) );
final Root<BasicEntity> root = criteria.from( BasicEntity.class ); session.createQuery( criteria ).setParameter( param, 1 ).list();
}
criteria.select( root );
final ParameterExpression<Integer> param = criteriaBuilder.parameter( Integer.class );
criteria.where( criteriaBuilder.equal( param, param ) );
inStatelessSession(
session -> session.createQuery( criteria ).setParameter( param, 1 ).list()
); );
} }
@Test @Test
public void testCriteriaEntityJoin() { public void testExecutingBasicCriteriaQueryParameterPredicateInStatelessSession(SessionFactoryScope scope) {
final HibernateCriteriaBuilder criteriaBuilder = sessionFactory().getCriteriaBuilder(); scope.inStatelessTransaction(
session -> {
final HibernateCriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
final JpaCriteriaQuery<Object> criteria = criteriaBuilder.createQuery(); final CriteriaQuery<Object> criteria = criteriaBuilder.createQuery();
final Root<BasicEntity> root = criteria.from( BasicEntity.class );
criteria.select( root );
final ParameterExpression<Integer> param = criteriaBuilder.parameter( Integer.class );
criteria.where( criteriaBuilder.equal( param, param ) );
final JpaRoot<BasicEntity> root = criteria.from( BasicEntity.class ); session.createQuery( criteria ).setParameter( param, 1 ).list();
root.join( BasicEntity.class ); }
criteria.select( root );
inSession(
session -> session.createQuery( criteria ).list()
); );
} }
@Entity(name = "BasicEntity") @Test
public static class BasicEntity { public void testCriteriaEntityJoin(SessionFactoryScope scope) {
scope.inStatelessTransaction(
session -> {
final HibernateCriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
@Id final JpaCriteriaQuery<Object> criteria = criteriaBuilder.createQuery();
@GeneratedValue final JpaRoot<BasicEntity> root = criteria.from( BasicEntity.class );
private Integer id; root.join( BasicEntity.class );
criteria.select( root );
session.createQuery( criteria ).list();
}
);
} }
} }

View File

@ -14,6 +14,7 @@ import java.util.function.Function;
import org.hibernate.Interceptor; import org.hibernate.Interceptor;
import org.hibernate.SessionFactoryObserver; import org.hibernate.SessionFactoryObserver;
import org.hibernate.StatelessSession;
import org.hibernate.Transaction; import org.hibernate.Transaction;
import org.hibernate.boot.SessionFactoryBuilder; import org.hibernate.boot.SessionFactoryBuilder;
import org.hibernate.boot.registry.StandardServiceRegistry; import org.hibernate.boot.registry.StandardServiceRegistry;
@ -231,6 +232,25 @@ public class SessionFactoryExtension
this.sessionFactory = createSessionFactory(); this.sessionFactory = createSessionFactory();
} }
@Override
public SessionFactoryImplementor getSessionFactory() {
if ( sessionFactory == null ) {
sessionFactory = createSessionFactory();
}
return sessionFactory;
}
@Override
public MetadataImplementor getMetadataImplementor() {
return modelScope.getDomainModel();
}
@Override
public StatementInspector getStatementInspector() {
return getSessionFactory().getSessionFactoryOptions().getStatementInspector();
}
@Override @Override
public void close() { public void close() {
if ( ! active ) { if ( ! active ) {
@ -259,15 +279,6 @@ public class SessionFactoryExtension
} }
} }
@Override
public SessionFactoryImplementor getSessionFactory() {
if ( sessionFactory == null ) {
sessionFactory = createSessionFactory();
}
return sessionFactory;
}
private SessionFactoryImplementor createSessionFactory() { private SessionFactoryImplementor createSessionFactory() {
if ( ! active ) { if ( ! active ) {
throw new IllegalStateException( "SessionFactoryScope is no longer active" ); throw new IllegalStateException( "SessionFactoryScope is no longer active" );
@ -415,13 +426,76 @@ public class SessionFactoryExtension
} }
@Override @Override
public MetadataImplementor getMetadataImplementor() { public void inStatelessSession(Consumer<StatelessSession> action) {
return modelScope.getDomainModel(); log.trace( "#inStatelessSession(Consumer)" );
try ( final StatelessSession statelessSession = getSessionFactory().openStatelessSession(); ) {
log.trace( "StatelessSession opened, calling action" );
action.accept( statelessSession );
}
finally {
log.trace( "StatelessSession close - auto-close block" );
}
} }
@Override @Override
public StatementInspector getStatementInspector() { public void inStatelessTransaction(Consumer<StatelessSession> action) {
return getSessionFactory().getSessionFactoryOptions().getStatementInspector(); log.trace( "#inStatelessTransaction(Consumer)" );
try ( final StatelessSession statelessSession = getSessionFactory().openStatelessSession(); ) {
log.trace( "StatelessSession opened, calling action" );
inStatelessTransaction( statelessSession, action );
}
finally {
log.trace( "StatelessSession close - auto-close block" );
}
}
@Override
public void inStatelessTransaction(StatelessSession session, Consumer<StatelessSession> action) {
log.trace( "inStatelessTransaction(StatelessSession,Consumer)" );
final Transaction txn = session.beginTransaction();
log.trace( "Started transaction" );
try {
log.trace( "Calling action in txn" );
action.accept( session );
log.trace( "Called action - in txn" );
if ( !txn.getRollbackOnly() ) {
log.trace( "Committing transaction" );
txn.commit();
log.trace( "Committed transaction" );
}
else {
try {
log.trace( "Rollback transaction marked for rollback only" );
txn.rollback();
}
catch (Exception e) {
log.error( "Rollback failure", e );
}
}
}
catch (Exception e) {
log.tracef(
"Error calling action: %s (%s) - rolling back",
e.getClass().getName(),
e.getMessage()
);
try {
txn.rollback();
}
catch (Exception ignore) {
log.trace( "Was unable to roll back transaction" );
// really nothing else we can do here - the attempt to
// rollback already failed and there is nothing else
// to clean up.
}
throw e;
}
} }
} }
} }

View File

@ -9,6 +9,7 @@ package org.hibernate.testing.orm.junit;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Function; import java.util.function.Function;
import org.hibernate.StatelessSession;
import org.hibernate.boot.spi.MetadataImplementor; import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.engine.spi.SessionImplementor;
@ -19,18 +20,18 @@ import org.hibernate.resource.jdbc.spi.StatementInspector;
*/ */
public interface SessionFactoryScope { public interface SessionFactoryScope {
SessionFactoryImplementor getSessionFactory(); SessionFactoryImplementor getSessionFactory();
MetadataImplementor getMetadataImplementor();
StatementInspector getStatementInspector();
void inSession(Consumer<SessionImplementor> action); void inSession(Consumer<SessionImplementor> action);
void inTransaction(Consumer<SessionImplementor> action); void inTransaction(Consumer<SessionImplementor> action);
void inTransaction(SessionImplementor session, Consumer<SessionImplementor> action); void inTransaction(SessionImplementor session, Consumer<SessionImplementor> action);
<T> T fromSession(Function<SessionImplementor, T> action); <T> T fromSession(Function<SessionImplementor, T> action);
<T> T fromTransaction(Function<SessionImplementor, T> action); <T> T fromTransaction(Function<SessionImplementor, T> action);
<T> T fromTransaction(SessionImplementor session, Function<SessionImplementor, T> action); <T> T fromTransaction(SessionImplementor session, Function<SessionImplementor, T> action);
MetadataImplementor getMetadataImplementor(); void inStatelessSession(Consumer<StatelessSession> action);
void inStatelessTransaction(Consumer<StatelessSession> action);
StatementInspector getStatementInspector(); void inStatelessTransaction(StatelessSession session, Consumer<StatelessSession> action);
} }