HHH-12376 Apply some ThreadLocal optimisations made possible by new Java 8 API
This commit is contained in:
parent
0daa2400dd
commit
c1fbee79ae
|
@ -103,12 +103,12 @@ public class ManagedSessionContext extends AbstractCurrentSessionContext {
|
|||
}
|
||||
|
||||
private static Session existingSession(SessionFactory factory) {
|
||||
final Map sessionMap = sessionMap();
|
||||
final Map<SessionFactory,Session> sessionMap = sessionMap();
|
||||
if ( sessionMap == null ) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
return (Session) sessionMap.get( factory );
|
||||
return sessionMap.get( factory );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -129,7 +129,7 @@ public class ManagedSessionContext extends AbstractCurrentSessionContext {
|
|||
final Map<SessionFactory,Session> sessionMap = sessionMap( false );
|
||||
if ( sessionMap != null ) {
|
||||
if ( sessionMap.isEmpty() ) {
|
||||
CONTEXT_TL.set( null );
|
||||
CONTEXT_TL.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import org.hibernate.ConnectionReleaseMode;
|
|||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.Transaction;
|
||||
import org.hibernate.context.spi.AbstractCurrentSessionContext;
|
||||
import org.hibernate.engine.jdbc.LobCreationContext;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
|
@ -54,6 +55,7 @@ import org.jboss.logging.Logger;
|
|||
* subclassing (for long-running session scenarios, for example).
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
* @author Sanne Grinovero
|
||||
*/
|
||||
public class ThreadLocalSessionContext extends AbstractCurrentSessionContext {
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
|
||||
|
@ -74,7 +76,7 @@ public class ThreadLocalSessionContext extends AbstractCurrentSessionContext {
|
|||
* the possibility for multiple SessionFactory instances being used during execution
|
||||
* of the given thread.
|
||||
*/
|
||||
private static final ThreadLocal<Map> CONTEXT_TL = new ThreadLocal<Map>();
|
||||
private static final ThreadLocal<Map<SessionFactory,Session>> CONTEXT_TL = ThreadLocal.withInitial( HashMap::new );
|
||||
|
||||
/**
|
||||
* Constructs a ThreadLocal
|
||||
|
@ -107,12 +109,10 @@ public class ThreadLocalSessionContext extends AbstractCurrentSessionContext {
|
|||
|
||||
private boolean needsWrapping(Session session) {
|
||||
// try to make sure we don't wrap and already wrapped session
|
||||
if ( session != null ) {
|
||||
if ( Proxy.isProxyClass( session.getClass() ) ) {
|
||||
final InvocationHandler invocationHandler = Proxy.getInvocationHandler( session );
|
||||
if ( invocationHandler != null && TransactionProtectionWrapper.class.isInstance( invocationHandler ) ) {
|
||||
return false;
|
||||
}
|
||||
if ( Proxy.isProxyClass( session.getClass() ) ) {
|
||||
final InvocationHandler invocationHandler = Proxy.getInvocationHandler( session );
|
||||
if ( invocationHandler != null && TransactionProtectionWrapper.class.isInstance( invocationHandler ) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -194,28 +194,32 @@ public class ThreadLocalSessionContext extends AbstractCurrentSessionContext {
|
|||
*/
|
||||
public static void bind(org.hibernate.Session session) {
|
||||
final SessionFactory factory = session.getSessionFactory();
|
||||
cleanupAnyOrphanedSession( factory );
|
||||
doBind( session, factory );
|
||||
}
|
||||
|
||||
private static void cleanupAnyOrphanedSession(SessionFactory factory) {
|
||||
final Session orphan = doUnbind( factory, false );
|
||||
private static void terminateOrphanedSession(Session orphan) {
|
||||
if ( orphan != null ) {
|
||||
LOG.alreadySessionBound();
|
||||
try {
|
||||
if ( orphan.getTransaction() != null && orphan.getTransaction().getStatus() == TransactionStatus.ACTIVE ) {
|
||||
final Transaction orphanTransaction = orphan.getTransaction();
|
||||
if ( orphanTransaction != null && orphanTransaction.getStatus() == TransactionStatus.ACTIVE ) {
|
||||
try {
|
||||
orphan.getTransaction().rollback();
|
||||
orphanTransaction.rollback();
|
||||
}
|
||||
catch( Throwable t ) {
|
||||
LOG.debug( "Unable to rollback transaction for orphaned session", t );
|
||||
}
|
||||
}
|
||||
orphan.close();
|
||||
}
|
||||
catch( Throwable t ) {
|
||||
LOG.debug( "Unable to close orphaned session", t );
|
||||
finally {
|
||||
try {
|
||||
orphan.close();
|
||||
}
|
||||
catch( Throwable t ) {
|
||||
LOG.debug( "Unable to close orphaned session", t );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -230,35 +234,25 @@ public class ThreadLocalSessionContext extends AbstractCurrentSessionContext {
|
|||
}
|
||||
|
||||
private static Session existingSession(SessionFactory factory) {
|
||||
final Map sessionMap = sessionMap();
|
||||
if ( sessionMap == null ) {
|
||||
return null;
|
||||
}
|
||||
return (Session) sessionMap.get( factory );
|
||||
return sessionMap().get( factory );
|
||||
}
|
||||
|
||||
protected static Map sessionMap() {
|
||||
protected static Map<SessionFactory,Session> sessionMap() {
|
||||
return CONTEXT_TL.get();
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private static void doBind(org.hibernate.Session session, SessionFactory factory) {
|
||||
Map sessionMap = sessionMap();
|
||||
if ( sessionMap == null ) {
|
||||
sessionMap = new HashMap();
|
||||
CONTEXT_TL.set( sessionMap );
|
||||
}
|
||||
sessionMap.put( factory, session );
|
||||
Session orphanedPreviousSession = sessionMap().put( factory, session );
|
||||
terminateOrphanedSession( orphanedPreviousSession );
|
||||
}
|
||||
|
||||
private static Session doUnbind(SessionFactory factory, boolean releaseMapIfEmpty) {
|
||||
Session session = null;
|
||||
final Map sessionMap = sessionMap();
|
||||
if ( sessionMap != null ) {
|
||||
session = (Session) sessionMap.remove( factory );
|
||||
if ( releaseMapIfEmpty && sessionMap.isEmpty() ) {
|
||||
CONTEXT_TL.set( null );
|
||||
}
|
||||
final Map<SessionFactory, Session> sessionMap = sessionMap();
|
||||
final Session session = sessionMap.remove( factory );
|
||||
if ( releaseMapIfEmpty && sessionMap.isEmpty() ) {
|
||||
//Do not use set(null) as it would prevent the initialValue to be invoked again in case of need.
|
||||
CONTEXT_TL.remove();
|
||||
}
|
||||
return session;
|
||||
}
|
||||
|
|
|
@ -56,10 +56,9 @@ public class PooledLoThreadLocalOptimizer extends AbstractOptimizer {
|
|||
|
||||
@Override
|
||||
public Serializable generate(AccessCallback callback) {
|
||||
GenerationState local = null;
|
||||
if ( callback.getTenantIdentifier() == null ) {
|
||||
local = localAssignedIds.get();
|
||||
if ( local != null && local.value.lt( local.upperLimitValue ) ) {
|
||||
final GenerationState local = localAssignedIds.get();
|
||||
if ( local.value != null && local.value.lt( local.upperLimitValue ) ) {
|
||||
return local.value.makeValueThenIncrement();
|
||||
}
|
||||
}
|
||||
|
@ -82,16 +81,11 @@ public class PooledLoThreadLocalOptimizer extends AbstractOptimizer {
|
|||
}
|
||||
|
||||
private Map<String, GenerationState> tenantSpecificState;
|
||||
private final ThreadLocal<GenerationState> localAssignedIds = new ThreadLocal<GenerationState>();
|
||||
private final ThreadLocal<GenerationState> localAssignedIds = ThreadLocal.withInitial( GenerationState::new );
|
||||
|
||||
private GenerationState locateGenerationState(String tenantIdentifier) {
|
||||
if ( tenantIdentifier == null ) {
|
||||
GenerationState noTenantState = localAssignedIds.get();
|
||||
if ( noTenantState == null ) {
|
||||
noTenantState = new GenerationState();
|
||||
localAssignedIds.set(noTenantState);
|
||||
}
|
||||
return noTenantState;
|
||||
return localAssignedIds.get();
|
||||
}
|
||||
else {
|
||||
GenerationState state;
|
||||
|
|
Loading…
Reference in New Issue