alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Hibernate example source code file (LogicalConnectionImpl.java)

This example Hibernate source code file (LogicalConnectionImpl.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Hibernate tags/keywords

connection, connection, connectionobserver, connectionobserver, connectionreleasemode, illegalstateexception, io, jdbc, jdbc, jdbcservices, list, logicalconnectionimpl, override, override, sql, sqlexception, util

The Hibernate LogicalConnectionImpl.java source code

/*
 * Hibernate, Relational Persistence for Idiomatic Java
 *
 * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
 * indicated by the @author tags or express copyright attribution
 * statements applied by the authors.  All third-party contributions are
 * distributed under license by Red Hat Inc.
 *
 * This copyrighted material is made available to anyone wishing to use, modify,
 * copy, or redistribute it subject to the terms and conditions of the GNU
 * Lesser General Public License, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
 * for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this distribution; if not, write to:
 * Free Software Foundation, Inc.
 * 51 Franklin Street, Fifth Floor
 * Boston, MA  02110-1301  USA
 */
package org.hibernate.engine.jdbc.internal;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.hibernate.ConnectionReleaseMode;
import org.hibernate.HibernateException;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.JDBCException;
import org.hibernate.engine.jdbc.internal.proxy.ProxyBuilder;
import org.hibernate.engine.jdbc.spi.ConnectionObserver;
import org.hibernate.engine.jdbc.spi.JdbcConnectionAccess;
import org.hibernate.engine.jdbc.spi.JdbcResourceRegistry;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.jdbc.spi.LogicalConnectionImplementor;
import org.hibernate.engine.jdbc.spi.NonDurableConnectionObserver;
import org.hibernate.engine.transaction.spi.TransactionContext;
import org.hibernate.internal.util.collections.CollectionHelper;

import org.jboss.logging.Logger;

/**
 * Standard Hibernate {@link org.hibernate.engine.jdbc.spi.LogicalConnection} implementation
 * <p/>
 * IMPL NOTE : Custom serialization handling!
 *
 * @author Steve Ebersole
 */
public class LogicalConnectionImpl implements LogicalConnectionImplementor {

    private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, LogicalConnectionImpl.class.getName());

	private transient Connection physicalConnection;
	private transient Connection shareableConnectionProxy;

	private final transient ConnectionReleaseMode connectionReleaseMode;
	private final transient JdbcServices jdbcServices;
	private final transient JdbcConnectionAccess jdbcConnectionAccess;
	private final transient JdbcResourceRegistry jdbcResourceRegistry;
	private final transient List<ConnectionObserver> observers;

	private boolean releasesEnabled = true;

	private final boolean isUserSuppliedConnection;

	private boolean isClosed;

	public LogicalConnectionImpl(
			Connection userSuppliedConnection,
			ConnectionReleaseMode connectionReleaseMode,
			JdbcServices jdbcServices,
			JdbcConnectionAccess jdbcConnectionAccess) {
		this(
				connectionReleaseMode,
				jdbcServices,
				jdbcConnectionAccess,
				(userSuppliedConnection != null),
				false,
				new ArrayList<ConnectionObserver>()
		);
		this.physicalConnection = userSuppliedConnection;
	}

	private LogicalConnectionImpl(
			ConnectionReleaseMode connectionReleaseMode,
			JdbcServices jdbcServices,
			JdbcConnectionAccess jdbcConnectionAccess,
			boolean isUserSuppliedConnection,
			boolean isClosed,
			List<ConnectionObserver> observers) {
		this.connectionReleaseMode = determineConnectionReleaseMode(
				jdbcServices, isUserSuppliedConnection, connectionReleaseMode
		);
		this.jdbcServices = jdbcServices;
		this.jdbcConnectionAccess = jdbcConnectionAccess;
		this.jdbcResourceRegistry = new JdbcResourceRegistryImpl( getJdbcServices().getSqlExceptionHelper() );
		this.observers = observers;

		this.isUserSuppliedConnection = isUserSuppliedConnection;
		this.isClosed = isClosed;
	}

	private static ConnectionReleaseMode determineConnectionReleaseMode(
			JdbcServices jdbcServices,
			boolean isUserSuppliedConnection,
			ConnectionReleaseMode connectionReleaseMode) {
		if ( isUserSuppliedConnection ) {
			return ConnectionReleaseMode.ON_CLOSE;
		}
		else if ( connectionReleaseMode == ConnectionReleaseMode.AFTER_STATEMENT &&
				! jdbcServices.getConnectionProvider().supportsAggressiveRelease() ) {
            LOG.debugf("Connection provider reports to not support aggressive release; overriding");
			return ConnectionReleaseMode.AFTER_TRANSACTION;
		}
		else {
			return connectionReleaseMode;
		}
	}

	@Override
	public JdbcServices getJdbcServices() {
		return jdbcServices;
	}

	@Override
	public JdbcResourceRegistry getResourceRegistry() {
		return jdbcResourceRegistry;
	}

	@Override
	public void addObserver(ConnectionObserver observer) {
		observers.add( observer );
	}

	@Override
	public void removeObserver(ConnectionObserver connectionObserver) {
		observers.remove( connectionObserver );
	}

	@Override
	public boolean isOpen() {
		return !isClosed;
	}

	@Override
	public boolean isPhysicallyConnected() {
		return physicalConnection != null;
	}

	@Override
	public Connection getConnection() throws HibernateException {
		if ( isClosed ) {
			throw new HibernateException( "Logical connection is closed" );
		}
		if ( physicalConnection == null ) {
			if ( isUserSuppliedConnection ) {
				// should never happen
				throw new HibernateException( "User-supplied connection was null" );
			}
			obtainConnection();
		}
		return physicalConnection;
	}

	@Override
	public Connection getShareableConnectionProxy() {
		if ( shareableConnectionProxy == null ) {
			shareableConnectionProxy = buildConnectionProxy();
		}
		return shareableConnectionProxy;
	}

	private Connection buildConnectionProxy() {
		return ProxyBuilder.buildConnection( this );
	}

	@Override
	public Connection getDistinctConnectionProxy() {
		return buildConnectionProxy();
	}

	/**
	 * {@inheritDoc}
	 */
	public Connection close() {
		LOG.trace( "Closing logical connection" );
		Connection c = isUserSuppliedConnection ? physicalConnection : null;
		try {
			releaseProxies();
			jdbcResourceRegistry.close();
			if ( !isUserSuppliedConnection && physicalConnection != null ) {
				releaseConnection();
			}
			return c;
		}
		finally {
			// no matter what
			physicalConnection = null;
			isClosed = true;
            LOG.trace("Logical connection closed");
			for ( ConnectionObserver observer : observers ) {
				observer.logicalConnectionClosed();
			}
			observers.clear();
		}
	}

	private void releaseProxies() {
		if ( shareableConnectionProxy != null ) {
			try {
				shareableConnectionProxy.close();
			}
			catch (SQLException e) {
				LOG.debug( "Error releasing shared connection proxy", e );
			}
		}
		shareableConnectionProxy = null;
	}

	@Override
	public ConnectionReleaseMode getConnectionReleaseMode() {
		return connectionReleaseMode;
	}

	@Override
	public void afterStatementExecution() {
        LOG.trace("Starting after statement execution processing [" + connectionReleaseMode + "]");
		if ( connectionReleaseMode == ConnectionReleaseMode.AFTER_STATEMENT ) {
			if ( ! releasesEnabled ) {
                LOG.debugf("Skipping aggressive release due to manual disabling");
				return;
			}
			if ( jdbcResourceRegistry.hasRegisteredResources() ) {
                LOG.debugf("Skipping aggressive release due to registered resources");
				return;
			}
			releaseConnection();
		}
	}

	@Override
	public void afterTransaction() {
		if ( connectionReleaseMode == ConnectionReleaseMode.AFTER_STATEMENT ||
				connectionReleaseMode == ConnectionReleaseMode.AFTER_TRANSACTION ) {
			if ( jdbcResourceRegistry.hasRegisteredResources() ) {
                LOG.forcingContainerResourceCleanup();
				jdbcResourceRegistry.releaseResources();
			}
			aggressiveRelease();
		}
	}

	@Override
	public void disableReleases() {
        LOG.trace("Disabling releases");
		releasesEnabled = false;
	}

	@Override
	public void enableReleases() {
        LOG.trace("(Re)enabling releases");
		releasesEnabled = true;
		afterStatementExecution();
	}

	/**
	 * Force aggressive release of the underlying connection.
	 */
	public void aggressiveRelease() {
        if (isUserSuppliedConnection) LOG.debugf("Cannot aggressively release user-supplied connection; skipping");
		else {
            LOG.debugf("Aggressively releasing JDBC connection");
			if ( physicalConnection != null ) {
				releaseConnection();
			}
		}
	}


	/**
	 * Physically opens a JDBC Connection.
	 *
	 * @throws org.hibernate.JDBCException Indicates problem opening a connection
	 */
	private void obtainConnection() throws JDBCException {
        LOG.debugf("Obtaining JDBC connection");
		try {
			physicalConnection = jdbcConnectionAccess.obtainConnection();
			for ( ConnectionObserver observer : observers ) {
				observer.physicalConnectionObtained( physicalConnection );
			}
            LOG.debugf("Obtained JDBC connection");
		}
		catch ( SQLException sqle) {
			throw getJdbcServices().getSqlExceptionHelper().convert( sqle, "Could not open connection" );
		}
	}

	/**
	 * Physically closes the JDBC Connection.
	 *
	 * @throws JDBCException Indicates problem closing a connection
	 */
	private void releaseConnection() throws JDBCException {
        LOG.debugf("Releasing JDBC connection");
		if ( physicalConnection == null ) {
			return;
		}
		try {
            if ( ! physicalConnection.isClosed() ) {
				getJdbcServices().getSqlExceptionHelper().logAndClearWarnings( physicalConnection );
			}
            if ( ! isUserSuppliedConnection ) {
				jdbcConnectionAccess.releaseConnection( physicalConnection );
			}
		}
		catch (SQLException e) {
			throw getJdbcServices().getSqlExceptionHelper().convert( e, "Could not close connection" );
		}
		finally {
			physicalConnection = null;
		}
        LOG.debugf("Released JDBC connection");
		for ( ConnectionObserver observer : observers ) {
			observer.physicalConnectionReleased();
		}
		releaseNonDurableObservers();
	}

	private void releaseNonDurableObservers() {
		Iterator observers = this.observers.iterator();
		while ( observers.hasNext() ) {
			if ( NonDurableConnectionObserver.class.isInstance( observers.next() ) ) {
				observers.remove();
			}
		}
	}

	@Override
	public Connection manualDisconnect() {
		if ( isClosed ) {
			throw new IllegalStateException( "cannot manually disconnect because logical connection is already closed" );
		}
		releaseProxies();
		Connection c = physicalConnection;
		jdbcResourceRegistry.releaseResources();
		releaseConnection();
		return c;
	}

	@Override
	public void manualReconnect(Connection suppliedConnection) {
		if ( isClosed ) {
			throw new IllegalStateException( "cannot manually reconnect because logical connection is already closed" );
		}
		if ( !isUserSuppliedConnection ) {
			throw new IllegalStateException( "cannot manually reconnect unless Connection was originally supplied" );
		}
		else {
			if ( suppliedConnection == null ) {
				throw new IllegalArgumentException( "cannot reconnect a null user-supplied connection" );
			}
			else if ( suppliedConnection == physicalConnection ) {
                LOG.debug("reconnecting the same connection that is already connected; should this connection have been disconnected?");
			}
			else if ( physicalConnection != null ) {
				throw new IllegalArgumentException(
						"cannot reconnect to a new user-supplied connection because currently connected; must disconnect before reconnecting."
				);
			}
			physicalConnection = suppliedConnection;
            LOG.debugf("Reconnected JDBC connection");
		}
	}

	@Override
	public boolean isAutoCommit() {
		if ( !isOpen() || ! isPhysicallyConnected() ) {
			return true;
		}

		try {
			return getConnection().getAutoCommit();
		}
		catch (SQLException e) {
			throw jdbcServices.getSqlExceptionHelper().convert( e, "could not inspect JDBC autocommit mode" );
		}
	}

	@Override
	public void notifyObserversStatementPrepared() {
		for ( ConnectionObserver observer : observers ) {
			observer.statementPrepared();
		}
	}

	@Override
	public boolean isReadyForSerialization() {
		return isUserSuppliedConnection
				? ! isPhysicallyConnected()
				: ! getResourceRegistry().hasRegisteredResources();
	}

	public void serialize(ObjectOutputStream oos) throws IOException {
		oos.writeBoolean( isUserSuppliedConnection );
		oos.writeBoolean( isClosed );
		List<ConnectionObserver> durableConnectionObservers = new ArrayList();
		for ( ConnectionObserver observer : observers ) {
			if ( ! NonDurableConnectionObserver.class.isInstance( observer ) ) {
				durableConnectionObservers.add( observer );
			}
		}
		oos.writeInt( durableConnectionObservers.size() );
		for ( ConnectionObserver observer : durableConnectionObservers ) {
			oos.writeObject( observer );
		}
	}

	public static LogicalConnectionImpl deserialize(
			ObjectInputStream ois,
			TransactionContext transactionContext) throws IOException, ClassNotFoundException {
		boolean isUserSuppliedConnection = ois.readBoolean();
		boolean isClosed = ois.readBoolean();
		int observerCount = ois.readInt();
		List<ConnectionObserver> observers = CollectionHelper.arrayList( observerCount );
		for ( int i = 0; i < observerCount; i++ ) {
			observers.add( (ConnectionObserver) ois.readObject() );
		}
		return new LogicalConnectionImpl(
				transactionContext.getConnectionReleaseMode(),
				transactionContext.getTransactionEnvironment().getJdbcServices(),
				transactionContext.getJdbcConnectionAccess(),
				isUserSuppliedConnection,
				isClosed,
				observers
		);
 	}
}

Other Hibernate examples (source code examples)

Here is a short list of links related to this Hibernate LogicalConnectionImpl.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.