mirror of
https://github.com/hibernate/hibernate-orm
synced 2025-02-07 03:38:16 +00:00
HHH-5638 HHH-5639 HHH-5640 : Import DialectFactory. DialectResolver, ConnectionProvider, and JDBC batching services
This commit is contained in:
parent
1f5c6f9578
commit
0bfe7869e4
@ -0,0 +1,188 @@
|
||||
/*
|
||||
* 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.batch.internal;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.hibernate.engine.jdbc.batch.spi.Batch;
|
||||
import org.hibernate.engine.jdbc.batch.spi.BatchObserver;
|
||||
import org.hibernate.service.jdbc.spi.JdbcServices;
|
||||
import org.hibernate.service.jdbc.spi.LogicalConnectionImplementor;
|
||||
import org.hibernate.engine.jdbc.proxy.ProxyBuilder;
|
||||
|
||||
/**
|
||||
* Convenience base class for implementors of the Batch interface.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public abstract class AbstractBatchImpl implements Batch {
|
||||
private static final Logger log = LoggerFactory.getLogger( AbstractBatchImpl.class );
|
||||
|
||||
private Object key;
|
||||
private LogicalConnectionImplementor logicalConnection;
|
||||
private Connection connectionProxy;
|
||||
private LinkedHashMap<String,PreparedStatement> statements = new LinkedHashMap<String,PreparedStatement>();
|
||||
private LinkedHashSet<BatchObserver> observers = new LinkedHashSet<BatchObserver>();
|
||||
|
||||
protected AbstractBatchImpl(Object key, LogicalConnectionImplementor logicalConnection) {
|
||||
this.key = key;
|
||||
this.logicalConnection = logicalConnection;
|
||||
this.connectionProxy = ProxyBuilder.buildConnection( logicalConnection );
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform batch execution.
|
||||
* <p/>
|
||||
* This is called from the explicit {@link #execute() execution}, but may also be called from elsewhere
|
||||
* depending on the exact implementation.
|
||||
*/
|
||||
protected abstract void doExecuteBatch();
|
||||
|
||||
/**
|
||||
* Convenience access to the underlying JDBC services.
|
||||
*
|
||||
* @return The underlying JDBC services.
|
||||
*/
|
||||
protected JdbcServices getJdbcServices() {
|
||||
return logicalConnection.getJdbcServices();
|
||||
}
|
||||
|
||||
/**
|
||||
* Access to the batch's map of statements (keyed by SQL statement string).
|
||||
*
|
||||
* @return This batch's statements.
|
||||
*/
|
||||
protected LinkedHashMap<String,PreparedStatement> getStatements() {
|
||||
return statements;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public final Object getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void addObserver(BatchObserver observer) {
|
||||
observers.add( observer );
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public final PreparedStatement getBatchStatement(String sql, boolean callable) {
|
||||
PreparedStatement statement = statements.get( sql );
|
||||
if ( statement == null ) {
|
||||
statement = buildBatchStatement( sql, callable );
|
||||
statements.put( sql, statement );
|
||||
}
|
||||
else {
|
||||
log.debug( "reusing batch statement" );
|
||||
getJdbcServices().getSqlStatementLogger().logStatement( sql );
|
||||
}
|
||||
return statement;
|
||||
}
|
||||
|
||||
private PreparedStatement buildBatchStatement(String sql, boolean callable) {
|
||||
try {
|
||||
if ( callable ) {
|
||||
return connectionProxy.prepareCall( sql );
|
||||
}
|
||||
else {
|
||||
return connectionProxy.prepareStatement( sql );
|
||||
}
|
||||
}
|
||||
catch ( SQLException sqle ) {
|
||||
log.error( "sqlexception escaped proxy", sqle );
|
||||
throw getJdbcServices().getSqlExceptionHelper().convert( sqle, "could not prepare batch statement", sql );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public final void execute() {
|
||||
notifyObserversExplicitExecution();
|
||||
if ( statements.isEmpty() ) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
try {
|
||||
doExecuteBatch();
|
||||
}
|
||||
finally {
|
||||
releaseStatements();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
statements.clear();
|
||||
}
|
||||
}
|
||||
|
||||
private void releaseStatements() {
|
||||
for ( PreparedStatement statement : getStatements().values() ) {
|
||||
try {
|
||||
statement.close();
|
||||
}
|
||||
catch ( SQLException e ) {
|
||||
log.error( "unable to release batch statement..." );
|
||||
log.error( "sqlexception escaped proxy", e );
|
||||
}
|
||||
}
|
||||
getStatements().clear();
|
||||
}
|
||||
|
||||
private void notifyObserversExplicitExecution() {
|
||||
for ( BatchObserver observer : observers ) {
|
||||
observer.batchExplicitlyExecuted();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to notify registered observers of an implicit execution of this batch.
|
||||
*/
|
||||
protected void notifyObserversImplicitExecution() {
|
||||
for ( BatchObserver observer : observers ) {
|
||||
observer.batchImplicitlyExecuted();
|
||||
}
|
||||
}
|
||||
|
||||
public void release() {
|
||||
if ( getStatements() != null && !getStatements().isEmpty() ) {
|
||||
log.info( "On release of batch it still contained JDBC statements" );
|
||||
}
|
||||
releaseStatements();
|
||||
observers.clear();
|
||||
}
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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.batch.internal;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.hibernate.engine.jdbc.batch.spi.Batch;
|
||||
import org.hibernate.service.jdbc.spi.LogicalConnectionImplementor;
|
||||
|
||||
/**
|
||||
* A builder for {@link Batch} instances.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class BatchBuilder {
|
||||
private static final Logger log = LoggerFactory.getLogger( BatchBuilder.class );
|
||||
|
||||
private int size;
|
||||
|
||||
public BatchBuilder() {
|
||||
}
|
||||
|
||||
public BatchBuilder(int size) {
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
public void setSize(int size) {
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
public Batch buildBatch(Object key, LogicalConnectionImplementor logicalConnection) {
|
||||
log.trace( "building batch [size={}]", size );
|
||||
return size > 1
|
||||
? new BatchingBatch( key, logicalConnection, size )
|
||||
: new NonBatchingBatch( key, logicalConnection );
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,125 @@
|
||||
/*
|
||||
* 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.batch.internal;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Map;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.service.jdbc.spi.LogicalConnectionImplementor;
|
||||
import org.hibernate.jdbc.Expectation;
|
||||
|
||||
/**
|
||||
* A {@link org.hibernate.engine.jdbc.batch.spi.Batch} implementation which does batching based on a given size. Once the batch size is exceeded, the
|
||||
* batch is implicitly executed.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class BatchingBatch extends AbstractBatchImpl {
|
||||
private static final Logger log = LoggerFactory.getLogger( BatchingBatch.class );
|
||||
|
||||
private final int batchSize;
|
||||
private Expectation[] expectations;
|
||||
private int batchPosition;
|
||||
|
||||
public BatchingBatch(Object key, LogicalConnectionImplementor logicalConnection, int batchSize) {
|
||||
super( key, logicalConnection );
|
||||
this.batchSize = batchSize;
|
||||
this.expectations = new Expectation[ batchSize ];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void addToBatch(Expectation expectation) {
|
||||
if ( !expectation.canBeBatched() ) {
|
||||
throw new HibernateException( "attempting to batch an operation which cannot be batched" );
|
||||
}
|
||||
for ( Map.Entry<String,PreparedStatement> entry : getStatements().entrySet() ) {
|
||||
try {
|
||||
entry.getValue().addBatch();
|
||||
}
|
||||
catch ( SQLException e ) {
|
||||
log.error( "sqlexception escaped proxy", e );
|
||||
throw getJdbcServices().getSqlExceptionHelper().convert( e, "could not perform addBatch", entry.getKey() );
|
||||
}
|
||||
}
|
||||
expectations[ batchPosition++ ] = expectation;
|
||||
if ( batchPosition == batchSize ) {
|
||||
notifyObserversImplicitExecution();
|
||||
doExecuteBatch();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected void doExecuteBatch() {
|
||||
if ( batchPosition == 0 ) {
|
||||
log.debug( "no batched statements to execute" );
|
||||
}
|
||||
else {
|
||||
if ( log.isDebugEnabled() ) {
|
||||
log.debug( "Executing batch size: " + batchPosition );
|
||||
}
|
||||
|
||||
try {
|
||||
for ( Map.Entry<String,PreparedStatement> entry : getStatements().entrySet() ) {
|
||||
try {
|
||||
final PreparedStatement statement = entry.getValue();
|
||||
checkRowCounts( statement.executeBatch(), statement );
|
||||
}
|
||||
catch ( SQLException e ) {
|
||||
log.error( "sqlexception escaped proxy", e );
|
||||
throw getJdbcServices().getSqlExceptionHelper()
|
||||
.convert( e, "could not perform addBatch", entry.getKey() );
|
||||
}
|
||||
}
|
||||
}
|
||||
catch ( RuntimeException re ) {
|
||||
log.error( "Exception executing batch [{}]", re.getMessage() );
|
||||
throw re;
|
||||
}
|
||||
finally {
|
||||
batchPosition = 0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void checkRowCounts(int[] rowCounts, PreparedStatement ps) throws SQLException, HibernateException {
|
||||
int numberOfRowCounts = rowCounts.length;
|
||||
if ( numberOfRowCounts != batchPosition ) {
|
||||
log.warn( "JDBC driver did not return the expected number of row counts" );
|
||||
}
|
||||
for ( int i = 0; i < numberOfRowCounts; i++ ) {
|
||||
expectations[i].verifyOutcome( rowCounts[i], ps, i );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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.batch.internal;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Map;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.hibernate.service.jdbc.spi.LogicalConnectionImplementor;
|
||||
import org.hibernate.jdbc.Expectation;
|
||||
|
||||
/**
|
||||
* An implementation of {@link org.hibernate.engine.jdbc.batch.spi.Batch} which does not perform batching. It simply executes each statement as it is
|
||||
* encountered.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class NonBatchingBatch extends AbstractBatchImpl {
|
||||
private static final Logger log = LoggerFactory.getLogger( NonBatchingBatch.class );
|
||||
|
||||
protected NonBatchingBatch(Object key, LogicalConnectionImplementor logicalConnection) {
|
||||
super( key, logicalConnection );
|
||||
}
|
||||
|
||||
public void addToBatch(Expectation expectation) {
|
||||
notifyObserversImplicitExecution();
|
||||
for ( Map.Entry<String,PreparedStatement> entry : getStatements().entrySet() ) {
|
||||
try {
|
||||
final PreparedStatement statement = entry.getValue();
|
||||
final int rowCount = statement.executeUpdate();
|
||||
expectation.verifyOutcome( rowCount, statement, 0 );
|
||||
}
|
||||
catch ( SQLException e ) {
|
||||
log.error( "sqlexception escaped proxy", e );
|
||||
throw getJdbcServices().getSqlExceptionHelper().convert( e, "could not execute batch statement", entry.getKey() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void doExecuteBatch() {
|
||||
// nothing to do
|
||||
}
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* 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.batch.spi;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
|
||||
import org.hibernate.jdbc.Expectation;
|
||||
|
||||
/**
|
||||
* Conceptually models a batch.
|
||||
* <p/>
|
||||
* Unlike directly in JDBC, here we add the ability to batch together multiple statements at a time. In the underlying
|
||||
* JDBC this correlates to multiple {@link java.sql.PreparedStatement} objects (one for each DML string) maintained within the
|
||||
* batch.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface Batch {
|
||||
/**
|
||||
* Retrieves the object being used to key (uniquely identify) this batch.
|
||||
*
|
||||
* @return The batch key.
|
||||
*/
|
||||
public Object getKey();
|
||||
|
||||
/**
|
||||
* Adds an observer to this batch.
|
||||
*
|
||||
* @param observer The batch observer.
|
||||
*/
|
||||
public void addObserver(BatchObserver observer);
|
||||
|
||||
/**
|
||||
* Get a statement which is part of the batch, creating if necessary (and storing for next time).
|
||||
*
|
||||
* @param sql The SQL statement.
|
||||
* @param callable Is the SQL statement callable?
|
||||
* @return The prepared statement instance, representing the SQL statement.
|
||||
*/
|
||||
public PreparedStatement getBatchStatement(String sql, boolean callable);
|
||||
|
||||
/**
|
||||
* Indicates completion of the current part of the batch.
|
||||
*
|
||||
* @param expectation The expectation for the part's result.
|
||||
*/
|
||||
public void addToBatch(Expectation expectation);
|
||||
|
||||
/**
|
||||
* Execute this batch.
|
||||
*/
|
||||
public void execute();
|
||||
|
||||
/**
|
||||
* Used to indicate that the batch instance is no longer needed and that, therefore, it can release its
|
||||
* resources.
|
||||
*/
|
||||
public void release();
|
||||
}
|
||||
|
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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.batch.spi;
|
||||
|
||||
/**
|
||||
* An observer contract for batch events.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface BatchObserver {
|
||||
/**
|
||||
* Indicates explicit execution of the batch via a call to {@link Batch#execute()}.
|
||||
*/
|
||||
public void batchExplicitlyExecuted();
|
||||
|
||||
/**
|
||||
* Indicates an implicit execution of the batch.
|
||||
*/
|
||||
public void batchImplicitlyExecuted();
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* 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.proxy;
|
||||
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
|
||||
/**
|
||||
* Basic support for building proxy handlers.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public abstract class AbstractProxyHandler implements InvocationHandler {
|
||||
private boolean valid = true;
|
||||
private final int hashCode;
|
||||
|
||||
public AbstractProxyHandler(int hashCode) {
|
||||
this.hashCode = hashCode;
|
||||
}
|
||||
|
||||
protected abstract Object continueInvocation(Object proxy, Method method, Object[] args) throws Throwable;
|
||||
|
||||
public String toString() {
|
||||
return super.toString() + "[valid=" + valid + "]";
|
||||
}
|
||||
|
||||
public final int hashCode() {
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
protected final boolean isValid() {
|
||||
return valid;
|
||||
}
|
||||
|
||||
protected final void invalidate() {
|
||||
valid = false;
|
||||
}
|
||||
|
||||
protected final void errorIfInvalid() {
|
||||
if ( !isValid() ) {
|
||||
throw new HibernateException( "proxy handle is no longer valid" );
|
||||
}
|
||||
}
|
||||
|
||||
public final Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
String methodName = method.getName();
|
||||
|
||||
// basic Object methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
if ( "toString".equals( methodName ) ) {
|
||||
return this.toString();
|
||||
}
|
||||
if ( "hashCode".equals( methodName ) ) {
|
||||
return this.hashCode();
|
||||
}
|
||||
if ( "equals".equals( methodName ) ) {
|
||||
return this.equals( args[0] );
|
||||
}
|
||||
|
||||
return continueInvocation( proxy, method, args );
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,126 @@
|
||||
/*
|
||||
* 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.proxy;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.hibernate.service.jdbc.spi.JdbcResourceRegistry;
|
||||
import org.hibernate.service.jdbc.spi.JdbcServices;
|
||||
|
||||
/**
|
||||
* Basic support for building {@link ResultSet}-based proxy handlers
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public abstract class AbstractResultSetProxyHandler extends AbstractProxyHandler {
|
||||
private static final Logger log = LoggerFactory.getLogger( AbstractResultSetProxyHandler.class );
|
||||
|
||||
private ResultSet resultSet;
|
||||
|
||||
public AbstractResultSetProxyHandler(ResultSet resultSet) {
|
||||
super( resultSet.hashCode() );
|
||||
this.resultSet = resultSet;
|
||||
}
|
||||
|
||||
protected abstract JdbcServices getJdbcServices();
|
||||
|
||||
protected abstract JdbcResourceRegistry getResourceRegistry();
|
||||
|
||||
protected abstract Statement getExposableStatement();
|
||||
|
||||
protected final ResultSet getResultSet() {
|
||||
errorIfInvalid();
|
||||
return resultSet;
|
||||
}
|
||||
|
||||
protected final ResultSet getResultSetWithoutChecks() {
|
||||
return resultSet;
|
||||
}
|
||||
|
||||
protected Object continueInvocation(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
String methodName = method.getName();
|
||||
log.trace( "Handling invocation of ResultSet method [{}]", methodName );
|
||||
|
||||
// other methods allowed while invalid ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
if ( "close".equals( methodName ) ) {
|
||||
explicitClose( ( ResultSet ) proxy );
|
||||
return null;
|
||||
}
|
||||
if ( "invalidate".equals( methodName ) ) {
|
||||
invalidateHandle();
|
||||
return null;
|
||||
}
|
||||
|
||||
errorIfInvalid();
|
||||
|
||||
// handle the JDBC 4 Wrapper#isWrapperFor and Wrapper#unwrap calls
|
||||
// these cause problems to the whole proxy scheme though as we need to return the raw objects
|
||||
if ( "isWrapperFor".equals( methodName ) && args.length == 1 ) {
|
||||
return method.invoke( getResultSetWithoutChecks(), args );
|
||||
}
|
||||
if ( "unwrap".equals( methodName ) && args.length == 1 ) {
|
||||
return method.invoke( getResultSetWithoutChecks(), args );
|
||||
}
|
||||
|
||||
if ( "getWrappedObject".equals( methodName ) ) {
|
||||
return getResultSetWithoutChecks();
|
||||
}
|
||||
|
||||
if ( "getStatement".equals( methodName ) ) {
|
||||
return getExposableStatement();
|
||||
}
|
||||
|
||||
try {
|
||||
return method.invoke( resultSet, args );
|
||||
}
|
||||
catch ( InvocationTargetException e ) {
|
||||
Throwable realException = e.getTargetException();
|
||||
if ( SQLException.class.isInstance( realException ) ) {
|
||||
throw getJdbcServices().getSqlExceptionHelper()
|
||||
.convert( ( SQLException ) realException, realException.getMessage() );
|
||||
}
|
||||
else {
|
||||
throw realException;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void explicitClose(ResultSet proxy) {
|
||||
if ( isValid() ) {
|
||||
getResourceRegistry().release( proxy );
|
||||
}
|
||||
}
|
||||
|
||||
protected void invalidateHandle() {
|
||||
resultSet = null;
|
||||
invalidate();
|
||||
}
|
||||
}
|
@ -0,0 +1,168 @@
|
||||
/*
|
||||
* 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.proxy;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.sql.Connection;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.hibernate.service.jdbc.spi.JdbcResourceRegistry;
|
||||
import org.hibernate.service.jdbc.spi.JdbcServices;
|
||||
import org.hibernate.service.jdbc.spi.LogicalConnectionImplementor;
|
||||
|
||||
/**
|
||||
* Basic support for building {@link Statement}-based proxy handlers
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public abstract class AbstractStatementProxyHandler extends AbstractProxyHandler {
|
||||
private static final Logger log = LoggerFactory.getLogger( AbstractStatementProxyHandler.class );
|
||||
|
||||
private ConnectionProxyHandler connectionProxyHandler;
|
||||
private Connection connectionProxy;
|
||||
private Statement statement;
|
||||
|
||||
protected AbstractStatementProxyHandler(
|
||||
Statement statement,
|
||||
ConnectionProxyHandler connectionProxyHandler,
|
||||
Connection connectionProxy) {
|
||||
super( statement.hashCode() );
|
||||
this.statement = statement;
|
||||
this.connectionProxyHandler = connectionProxyHandler;
|
||||
this.connectionProxy = connectionProxy;
|
||||
}
|
||||
|
||||
protected ConnectionProxyHandler getConnectionProxy() {
|
||||
errorIfInvalid();
|
||||
return connectionProxyHandler;
|
||||
}
|
||||
|
||||
protected JdbcServices getJdbcServices() {
|
||||
return getConnectionProxy().getJdbcServices();
|
||||
}
|
||||
|
||||
protected JdbcResourceRegistry getResourceRegistry() {
|
||||
return getConnectionProxy().getResourceRegistry();
|
||||
}
|
||||
|
||||
protected Statement getStatement() {
|
||||
errorIfInvalid();
|
||||
return statement;
|
||||
}
|
||||
|
||||
protected Statement getStatementWithoutChecks() {
|
||||
return statement;
|
||||
}
|
||||
|
||||
protected Object continueInvocation(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
String methodName = method.getName();
|
||||
log.trace( "Handling invocation of statement method [{}]", methodName );
|
||||
|
||||
// other methods allowed while invalid ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
if ( "close".equals( methodName ) ) {
|
||||
explicitClose( ( Statement ) proxy );
|
||||
return null;
|
||||
}
|
||||
if ( "invalidate".equals( methodName ) ) {
|
||||
invalidateHandle();
|
||||
return null;
|
||||
}
|
||||
|
||||
errorIfInvalid();
|
||||
|
||||
// handle the JDBC 4 Wrapper#isWrapperFor and Wrapper#unwrap calls
|
||||
// these cause problems to the whole proxy scheme though as we need to return the raw objects
|
||||
if ( "isWrapperFor".equals( methodName ) && args.length == 1 ) {
|
||||
return method.invoke( getStatementWithoutChecks(), args );
|
||||
}
|
||||
if ( "unwrap".equals( methodName ) && args.length == 1 ) {
|
||||
return method.invoke( getStatementWithoutChecks(), args );
|
||||
}
|
||||
|
||||
if ( "getWrappedObject".equals( methodName ) ) {
|
||||
return getStatementWithoutChecks();
|
||||
}
|
||||
|
||||
if ( "getConnection".equals( methodName ) ) {
|
||||
return connectionProxy;
|
||||
}
|
||||
|
||||
beginningInvocationHandling( method, args );
|
||||
|
||||
try {
|
||||
Object result = method.invoke( statement, args );
|
||||
result = wrapIfNecessary( result, proxy, method );
|
||||
return result;
|
||||
}
|
||||
catch ( InvocationTargetException e ) {
|
||||
Throwable realException = e.getTargetException();
|
||||
if ( SQLException.class.isInstance( realException ) ) {
|
||||
throw connectionProxyHandler.getJdbcServices().getSqlExceptionHelper()
|
||||
.convert( ( SQLException ) realException, realException.getMessage() );
|
||||
}
|
||||
else {
|
||||
throw realException;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Object wrapIfNecessary(Object result, Object proxy, Method method) {
|
||||
if ( !( ResultSet.class.isAssignableFrom( method.getReturnType() ) ) ) {
|
||||
return result;
|
||||
}
|
||||
|
||||
final ResultSet wrapper;
|
||||
if ( "getGeneratedKeys".equals( method.getName() ) ) {
|
||||
wrapper = ProxyBuilder.buildImplicitResultSet( ( ResultSet ) result, connectionProxyHandler, connectionProxy );
|
||||
}
|
||||
else {
|
||||
wrapper = ProxyBuilder.buildResultSet( ( ResultSet ) result, this, ( Statement ) proxy );
|
||||
}
|
||||
getResourceRegistry().register( wrapper );
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
protected void beginningInvocationHandling(Method method, Object[] args) {
|
||||
}
|
||||
|
||||
private void explicitClose(Statement proxy) {
|
||||
if ( isValid() ) {
|
||||
LogicalConnectionImplementor lc = getConnectionProxy().getLogicalConnection();
|
||||
getResourceRegistry().release( proxy );
|
||||
lc.afterStatementExecution();
|
||||
}
|
||||
}
|
||||
|
||||
private void invalidateHandle() {
|
||||
connectionProxyHandler = null;
|
||||
statement = null;
|
||||
invalidate();
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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.proxy;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.sql.Connection;
|
||||
import java.sql.Statement;
|
||||
|
||||
/**
|
||||
* Invocation handler for {@link Statement} proxies
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class BasicStatementProxyHandler extends AbstractStatementProxyHandler {
|
||||
public BasicStatementProxyHandler(
|
||||
Statement statement,
|
||||
ConnectionProxyHandler connectionProxyHandler,
|
||||
Connection connectionProxy) {
|
||||
super( statement, connectionProxyHandler, connectionProxy );
|
||||
}
|
||||
|
||||
protected void beginningInvocationHandling(Method method, Object[] args) {
|
||||
if ( isExecution( method ) ) {
|
||||
getJdbcServices().getSqlStatementLogger().logStatement( ( String ) args[0] );
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isExecution(Method method) {
|
||||
String methodName = method.getName();
|
||||
return "execute".equals( methodName )
|
||||
|| "executeQuery".equals( methodName )
|
||||
|| "executeUpdate".equals( methodName );
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,213 @@
|
||||
/*
|
||||
* 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.proxy;
|
||||
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.hibernate.service.jdbc.spi.JdbcResourceRegistry;
|
||||
import org.hibernate.service.jdbc.spi.JdbcServices;
|
||||
import org.hibernate.service.jdbc.spi.ConnectionObserver;
|
||||
import org.hibernate.service.jdbc.spi.LogicalConnectionImplementor;
|
||||
|
||||
/**
|
||||
* The {@link InvocationHandler} for intercepting messages to {@link java.sql.Connection} proxies.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class ConnectionProxyHandler extends AbstractProxyHandler implements InvocationHandler, ConnectionObserver {
|
||||
private static final Logger log = LoggerFactory.getLogger( ConnectionProxyHandler.class );
|
||||
|
||||
private LogicalConnectionImplementor logicalConnection;
|
||||
|
||||
public ConnectionProxyHandler(LogicalConnectionImplementor logicalConnection) {
|
||||
super( logicalConnection.hashCode() );
|
||||
this.logicalConnection = logicalConnection;
|
||||
this.logicalConnection.addObserver( this );
|
||||
}
|
||||
|
||||
/**
|
||||
* Access to our logical connection.
|
||||
*
|
||||
* @return the logical connection
|
||||
*/
|
||||
protected LogicalConnectionImplementor getLogicalConnection() {
|
||||
errorIfInvalid();
|
||||
return logicalConnection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get reference to physical connection.
|
||||
* <p/>
|
||||
* NOTE : be sure this handler is still valid before calling!
|
||||
*
|
||||
* @return The physical connection
|
||||
*/
|
||||
private Connection extractPhysicalConnection() {
|
||||
return logicalConnection.getConnection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide access to JDBCServices.
|
||||
* <p/>
|
||||
* NOTE : package-protected
|
||||
*
|
||||
* @return JDBCServices
|
||||
*/
|
||||
JdbcServices getJdbcServices() {
|
||||
return logicalConnection.getJdbcServices();
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide access to JDBCContainer.
|
||||
* <p/>
|
||||
* NOTE : package-protected
|
||||
*
|
||||
* @return JDBCContainer
|
||||
*/
|
||||
JdbcResourceRegistry getResourceRegistry() {
|
||||
return logicalConnection.getResourceRegistry();
|
||||
}
|
||||
|
||||
protected Object continueInvocation(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
String methodName = method.getName();
|
||||
log.trace( "Handling invocation of connection method [{}]", methodName );
|
||||
|
||||
// other methods allowed while invalid ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
if ( "close".equals( methodName ) ) {
|
||||
explicitClose();
|
||||
return null;
|
||||
}
|
||||
|
||||
errorIfInvalid();
|
||||
|
||||
// handle the JDBC 4 Wrapper#isWrapperFor and Wrapper#unwrap calls
|
||||
// these cause problems to the whole proxy scheme though as we need to return the raw objects
|
||||
if ( "isWrapperFor".equals( methodName ) && args.length == 1 ) {
|
||||
return method.invoke( extractPhysicalConnection(), args );
|
||||
}
|
||||
if ( "unwrap".equals( methodName ) && args.length == 1 ) {
|
||||
return method.invoke( extractPhysicalConnection(), args );
|
||||
}
|
||||
|
||||
if ( "getWrappedObject".equals( methodName ) ) {
|
||||
return extractPhysicalConnection();
|
||||
}
|
||||
|
||||
try {
|
||||
Object result = method.invoke( extractPhysicalConnection(), args );
|
||||
result = wrapIfNecessary( result, proxy, method, args );
|
||||
|
||||
return result;
|
||||
}
|
||||
catch( InvocationTargetException e ) {
|
||||
Throwable realException = e.getTargetException();
|
||||
if ( SQLException.class.isInstance( realException ) ) {
|
||||
throw logicalConnection.getJdbcServices().getSqlExceptionHelper()
|
||||
.convert( ( SQLException ) realException, realException.getMessage() );
|
||||
}
|
||||
else {
|
||||
throw realException;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Object wrapIfNecessary(Object result, Object proxy, Method method, Object[] args) {
|
||||
String methodName = method.getName();
|
||||
Object wrapped = result;
|
||||
if ( "createStatement".equals( methodName ) ) {
|
||||
wrapped = ProxyBuilder.buildStatement(
|
||||
(Statement) result,
|
||||
this,
|
||||
( Connection ) proxy
|
||||
);
|
||||
getResourceRegistry().register( ( Statement ) wrapped );
|
||||
}
|
||||
else if ( "prepareStatement".equals( methodName ) ) {
|
||||
wrapped = ProxyBuilder.buildPreparedStatement(
|
||||
( String ) args[0],
|
||||
(PreparedStatement) result,
|
||||
this,
|
||||
( Connection ) proxy
|
||||
);
|
||||
getResourceRegistry().register( ( Statement ) wrapped );
|
||||
}
|
||||
else if ( "prepareCall".equals( methodName ) ) {
|
||||
wrapped = ProxyBuilder.buildCallableStatement(
|
||||
( String ) args[0],
|
||||
(CallableStatement) result,
|
||||
this,
|
||||
( Connection ) proxy
|
||||
);
|
||||
getResourceRegistry().register( ( Statement ) wrapped );
|
||||
}
|
||||
else if ( "getMetaData".equals( methodName ) ) {
|
||||
wrapped = ProxyBuilder.buildDatabaseMetaData( (DatabaseMetaData) result, this, ( Connection ) proxy );
|
||||
}
|
||||
return wrapped;
|
||||
}
|
||||
|
||||
private void explicitClose() {
|
||||
if ( isValid() ) {
|
||||
invalidateHandle();
|
||||
}
|
||||
}
|
||||
|
||||
private void invalidateHandle() {
|
||||
log.trace( "Invalidating connection handle" );
|
||||
logicalConnection = null;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void physicalConnectionObtained(Connection connection) {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void physicalConnectionReleased() {
|
||||
log.info( "logical connection releasing its physical connection");
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void logicalConnectionClosed() {
|
||||
log.info( "*** logical connection closed ***" );
|
||||
invalidateHandle();
|
||||
}
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* 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.proxy;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* The InvocationHandler for intercepting messages to {@link java.sql.DatabaseMetaData} proxies.
|
||||
* <p/>
|
||||
* Mainly we need to intercept the methods defined on {@link java.sql.DatabaseMetaData} which expose
|
||||
* {@link java.sql.ResultSet} instances, which in turn expose {@link java.sql.Statement}
|
||||
* instances, which in turn...
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class DatabaseMetaDataProxyHandler extends AbstractProxyHandler {
|
||||
private ConnectionProxyHandler connectionProxyHandler;
|
||||
private Connection connectionProxy;
|
||||
private DatabaseMetaData databaseMetaData;
|
||||
|
||||
public DatabaseMetaDataProxyHandler(DatabaseMetaData databaseMetaData, ConnectionProxyHandler connectionProxyHandler, Connection connectionProxy) {
|
||||
super( databaseMetaData.hashCode() );
|
||||
this.connectionProxyHandler = connectionProxyHandler;
|
||||
this.connectionProxy = connectionProxy;
|
||||
this.databaseMetaData = databaseMetaData;
|
||||
}
|
||||
|
||||
protected Object continueInvocation(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
// handle the JDBC 4 Wrapper#isWrapperFor and Wrapper#unwrap calls
|
||||
// these cause problems to the whole proxy scheme though as we need to return the raw objects
|
||||
if ( "isWrapperFor".equals( method.getName() ) && args.length == 1 ) {
|
||||
return method.invoke( databaseMetaData, args );
|
||||
}
|
||||
if ( "unwrap".equals( method.getName() ) && args.length == 1 ) {
|
||||
return method.invoke( databaseMetaData, args );
|
||||
}
|
||||
|
||||
try {
|
||||
boolean exposingResultSet = doesMethodExposeResultSet( method );
|
||||
|
||||
Object result = method.invoke( databaseMetaData, args );
|
||||
|
||||
if ( exposingResultSet ) {
|
||||
result = ProxyBuilder.buildImplicitResultSet( (ResultSet) result, connectionProxyHandler, connectionProxy );
|
||||
connectionProxyHandler.getResourceRegistry().register( ( ResultSet ) result );
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
catch ( InvocationTargetException e ) {
|
||||
Throwable realException = e.getTargetException();
|
||||
if ( SQLException.class.isInstance( realException ) ) {
|
||||
throw connectionProxyHandler.getJdbcServices().getSqlExceptionHelper()
|
||||
.convert( ( SQLException ) realException, realException.getMessage() );
|
||||
}
|
||||
else {
|
||||
throw realException;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean doesMethodExposeResultSet(Method method) {
|
||||
return ResultSet.class.isAssignableFrom( method.getReturnType() );
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* 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.proxy;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
|
||||
import org.hibernate.service.jdbc.spi.JdbcResourceRegistry;
|
||||
import org.hibernate.service.jdbc.spi.JdbcServices;
|
||||
|
||||
/**
|
||||
* Invocation handler for {@link java.sql.ResultSet} proxies obtained from other JDBC object proxies
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class ImplicitResultSetProxyHandler extends AbstractResultSetProxyHandler {
|
||||
private ConnectionProxyHandler connectionProxyHandler;
|
||||
private Connection connectionProxy;
|
||||
private Statement sourceStatement;
|
||||
|
||||
public ImplicitResultSetProxyHandler(ResultSet resultSet, ConnectionProxyHandler connectionProxyHandler, Connection connectionProxy) {
|
||||
super( resultSet );
|
||||
this.connectionProxyHandler = connectionProxyHandler;
|
||||
this.connectionProxy = connectionProxy;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JdbcServices getJdbcServices() {
|
||||
return connectionProxyHandler.getJdbcServices();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JdbcResourceRegistry getResourceRegistry() {
|
||||
return connectionProxyHandler.getResourceRegistry();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Statement getExposableStatement() {
|
||||
if ( sourceStatement == null ) {
|
||||
try {
|
||||
Statement stmnt = getResultSet().getStatement();
|
||||
if ( stmnt == null ) {
|
||||
return null;
|
||||
}
|
||||
sourceStatement = ProxyBuilder.buildImplicitStatement( stmnt, connectionProxyHandler, connectionProxy );
|
||||
}
|
||||
catch ( SQLException e ) {
|
||||
throw getJdbcServices().getSqlExceptionHelper().convert( e, e.getMessage() );
|
||||
}
|
||||
}
|
||||
return sourceStatement;
|
||||
}
|
||||
|
||||
protected void invalidateHandle() {
|
||||
sourceStatement = null;
|
||||
super.invalidateHandle();
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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.proxy;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.sql.Connection;
|
||||
import java.sql.Statement;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
|
||||
/**
|
||||
* Invocation handler for {@link java.sql.Statement} proxies obtained from other JDBC object proxies
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class ImplicitStatementProxyHandler extends AbstractStatementProxyHandler {
|
||||
protected ImplicitStatementProxyHandler(Statement statement, ConnectionProxyHandler connectionProxyHandler, Connection connectionProxy) {
|
||||
super( statement, connectionProxyHandler, connectionProxy );
|
||||
}
|
||||
|
||||
protected void beginningInvocationHandling(Method method, Object[] args) {
|
||||
// disallow executions...
|
||||
if ( method.getName().startsWith( "execute" ) ) {
|
||||
throw new HibernateException( "execution not allowed on implicit statement object" );
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* 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.proxy;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.sql.Connection;
|
||||
import java.sql.Statement;
|
||||
|
||||
/**
|
||||
* Invocation handler for {@link java.sql.PreparedStatement} proxies
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class PreparedStatementProxyHandler extends AbstractStatementProxyHandler {
|
||||
private final String sql;
|
||||
|
||||
protected PreparedStatementProxyHandler(
|
||||
String sql,
|
||||
Statement statement,
|
||||
ConnectionProxyHandler connectionProxyHandler,
|
||||
Connection connectionProxy) {
|
||||
super( statement, connectionProxyHandler, connectionProxy );
|
||||
connectionProxyHandler.getJdbcServices().getSqlStatementLogger().logStatement( sql );
|
||||
this.sql = sql;
|
||||
}
|
||||
|
||||
protected void beginningInvocationHandling(Method method, Object[] args) {
|
||||
if ( isExecution( method ) ) {
|
||||
logExecution();
|
||||
}
|
||||
else {
|
||||
journalPossibleParameterBind( method, args );
|
||||
}
|
||||
}
|
||||
|
||||
private void journalPossibleParameterBind(Method method, Object[] args) {
|
||||
String methodName = method.getName();
|
||||
// todo : is this enough???
|
||||
if ( methodName.startsWith( "set" ) && args != null && args.length >= 2 ) {
|
||||
journalParameterBind( method, args );
|
||||
}
|
||||
}
|
||||
|
||||
private void journalParameterBind(Method method, Object[] args) {
|
||||
}
|
||||
|
||||
private boolean isExecution(Method method) {
|
||||
return false;
|
||||
}
|
||||
|
||||
private void logExecution() {
|
||||
}
|
||||
}
|
@ -0,0 +1,208 @@
|
||||
/*
|
||||
* 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.proxy;
|
||||
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.Statement;
|
||||
|
||||
import org.hibernate.service.jdbc.spi.JdbcWrapper;
|
||||
import org.hibernate.service.jdbc.spi.InvalidatableWrapper;
|
||||
import org.hibernate.service.jdbc.spi.LogicalConnectionImplementor;
|
||||
|
||||
/**
|
||||
* Centralized builder for proxy instances
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class ProxyBuilder {
|
||||
|
||||
// Connection ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
public static final Class[] CONNECTION_PROXY_INTERFACES = new Class[] {
|
||||
Connection.class,
|
||||
JdbcWrapper.class
|
||||
};
|
||||
|
||||
public static Connection buildConnection(LogicalConnectionImplementor logicalConnection) {
|
||||
ConnectionProxyHandler proxyHandler = new ConnectionProxyHandler( logicalConnection );
|
||||
return ( Connection ) Proxy.newProxyInstance(
|
||||
JdbcWrapper.class.getClassLoader(),
|
||||
CONNECTION_PROXY_INTERFACES,
|
||||
proxyHandler
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// Statement ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
public static final Class[] STMNT_PROXY_INTERFACES = new Class[] {
|
||||
Statement.class,
|
||||
JdbcWrapper.class,
|
||||
InvalidatableWrapper.class
|
||||
};
|
||||
|
||||
public static Statement buildStatement(
|
||||
Statement statement,
|
||||
ConnectionProxyHandler connectionProxyHandler,
|
||||
Connection connectionProxy) {
|
||||
BasicStatementProxyHandler proxyHandler = new BasicStatementProxyHandler(
|
||||
statement,
|
||||
connectionProxyHandler,
|
||||
connectionProxy
|
||||
);
|
||||
return ( Statement ) Proxy.newProxyInstance(
|
||||
JdbcWrapper.class.getClassLoader(),
|
||||
STMNT_PROXY_INTERFACES,
|
||||
proxyHandler
|
||||
);
|
||||
}
|
||||
|
||||
public static Statement buildImplicitStatement(
|
||||
Statement statement,
|
||||
ConnectionProxyHandler connectionProxyHandler,
|
||||
Connection connectionProxy) {
|
||||
if ( statement == null ) {
|
||||
return null;
|
||||
}
|
||||
ImplicitStatementProxyHandler handler = new ImplicitStatementProxyHandler( statement, connectionProxyHandler, connectionProxy );
|
||||
return ( Statement ) Proxy.newProxyInstance(
|
||||
JdbcWrapper.class.getClassLoader(),
|
||||
STMNT_PROXY_INTERFACES,
|
||||
handler
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// PreparedStatement ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
public static final Class[] PREPARED_STMNT_PROXY_INTERFACES = new Class[] {
|
||||
PreparedStatement.class,
|
||||
JdbcWrapper.class,
|
||||
InvalidatableWrapper.class
|
||||
};
|
||||
|
||||
public static PreparedStatement buildPreparedStatement(
|
||||
String sql,
|
||||
Statement statement,
|
||||
ConnectionProxyHandler connectionProxyHandler,
|
||||
Connection connectionProxy) {
|
||||
PreparedStatementProxyHandler proxyHandler = new PreparedStatementProxyHandler(
|
||||
sql,
|
||||
statement,
|
||||
connectionProxyHandler,
|
||||
connectionProxy
|
||||
);
|
||||
return ( PreparedStatement ) Proxy.newProxyInstance(
|
||||
JdbcWrapper.class.getClassLoader(),
|
||||
PREPARED_STMNT_PROXY_INTERFACES,
|
||||
proxyHandler
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// CallableStatement ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
public static final Class[] CALLABLE_STMNT_PROXY_INTERFACES = new Class[] {
|
||||
CallableStatement.class,
|
||||
JdbcWrapper.class,
|
||||
InvalidatableWrapper.class
|
||||
};
|
||||
|
||||
public static CallableStatement buildCallableStatement(
|
||||
String sql,
|
||||
CallableStatement statement,
|
||||
ConnectionProxyHandler connectionProxyHandler,
|
||||
Connection connectionProxy) {
|
||||
PreparedStatementProxyHandler proxyHandler = new PreparedStatementProxyHandler(
|
||||
sql,
|
||||
statement,
|
||||
connectionProxyHandler,
|
||||
connectionProxy
|
||||
);
|
||||
return ( CallableStatement ) Proxy.newProxyInstance(
|
||||
JdbcWrapper.class.getClassLoader(),
|
||||
CALLABLE_STMNT_PROXY_INTERFACES,
|
||||
proxyHandler
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// ResultSet ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
public static final Class[] RESULTSET_PROXY_INTERFACES = new Class[] {
|
||||
ResultSet.class,
|
||||
JdbcWrapper.class,
|
||||
InvalidatableWrapper.class
|
||||
};
|
||||
|
||||
|
||||
public static ResultSet buildResultSet(
|
||||
ResultSet resultSet,
|
||||
AbstractStatementProxyHandler statementProxyHandler,
|
||||
Statement statementProxy) {
|
||||
ResultSetProxyHandler proxyHandler = new ResultSetProxyHandler( resultSet, statementProxyHandler, statementProxy );
|
||||
return ( ResultSet ) Proxy.newProxyInstance(
|
||||
JdbcWrapper.class.getClassLoader(),
|
||||
RESULTSET_PROXY_INTERFACES,
|
||||
proxyHandler
|
||||
);
|
||||
}
|
||||
|
||||
public static ResultSet buildImplicitResultSet(
|
||||
ResultSet resultSet,
|
||||
ConnectionProxyHandler connectionProxyHandler,
|
||||
Connection connectionProxy) {
|
||||
ImplicitResultSetProxyHandler proxyHandler = new ImplicitResultSetProxyHandler( resultSet, connectionProxyHandler, connectionProxy );
|
||||
return ( ResultSet ) Proxy.newProxyInstance(
|
||||
JdbcWrapper.class.getClassLoader(),
|
||||
RESULTSET_PROXY_INTERFACES,
|
||||
proxyHandler
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// DatabaseMetaData ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
public static final Class[] METADATA_PROXY_INTERFACES = new Class[] {
|
||||
DatabaseMetaData.class,
|
||||
JdbcWrapper.class
|
||||
};
|
||||
|
||||
public static DatabaseMetaData buildDatabaseMetaData(
|
||||
DatabaseMetaData metaData,
|
||||
ConnectionProxyHandler connectionProxyHandler,
|
||||
Connection connectionProxy) {
|
||||
DatabaseMetaDataProxyHandler handler = new DatabaseMetaDataProxyHandler( metaData, connectionProxyHandler, connectionProxy );
|
||||
return ( DatabaseMetaData ) Proxy.newProxyInstance(
|
||||
JdbcWrapper.class.getClassLoader(),
|
||||
METADATA_PROXY_INTERFACES,
|
||||
handler
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* 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.proxy;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.Statement;
|
||||
|
||||
import org.hibernate.service.jdbc.spi.JdbcResourceRegistry;
|
||||
import org.hibernate.service.jdbc.spi.JdbcServices;
|
||||
|
||||
/**
|
||||
* Invocation handler for {@link java.sql.ResultSet} proxies
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class ResultSetProxyHandler extends AbstractResultSetProxyHandler {
|
||||
private AbstractStatementProxyHandler statementProxyHandler;
|
||||
private Statement statementProxy;
|
||||
|
||||
public ResultSetProxyHandler(
|
||||
ResultSet resultSet,
|
||||
AbstractStatementProxyHandler statementProxyHandler,
|
||||
Statement statementProxy) {
|
||||
super( resultSet );
|
||||
this.statementProxyHandler = statementProxyHandler;
|
||||
this.statementProxy = statementProxy;
|
||||
}
|
||||
|
||||
protected AbstractStatementProxyHandler getStatementProxy() {
|
||||
return statementProxyHandler;
|
||||
}
|
||||
|
||||
protected Statement getExposableStatement() {
|
||||
return statementProxy;
|
||||
}
|
||||
|
||||
protected JdbcServices getJdbcServices() {
|
||||
return getStatementProxy().getJdbcServices();
|
||||
}
|
||||
|
||||
protected JdbcResourceRegistry getResourceRegistry() {
|
||||
return getStatementProxy().getResourceRegistry();
|
||||
}
|
||||
|
||||
protected void invalidateHandle() {
|
||||
statementProxyHandler = null;
|
||||
super.invalidateHandle();
|
||||
}
|
||||
}
|
@ -0,0 +1,242 @@
|
||||
/*
|
||||
* 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.service.jdbc.connections.internal;
|
||||
|
||||
import java.beans.BeanInfo;
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.service.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
|
||||
import org.hibernate.internal.util.beans.BeanInfoHelper;
|
||||
import org.hibernate.service.spi.ServicesRegistry;
|
||||
import org.hibernate.service.spi.ServiceInitiator;
|
||||
|
||||
/**
|
||||
* Instantiates and configures an appropriate {@link ConnectionProvider}.
|
||||
*
|
||||
* @author Gavin King
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class ConnectionProviderInitiator implements ServiceInitiator<ConnectionProvider> {
|
||||
public static final ConnectionProviderInitiator INSTANCE = new ConnectionProviderInitiator();
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger( ConnectionProviderInitiator.class );
|
||||
|
||||
public static final String C3P0_CONFIG_PREFIX = "hibernate.c3p0";
|
||||
public static final String C3P0_PROVIDER_CLASS_NAME = "org.hibernate.connection.C3P0ConnectionProvider";
|
||||
|
||||
public static final String PROXOOL_CONFIG_PREFIX = "hibernate.proxool";
|
||||
public static final String PROXOOL_PROVIDER_CLASS_NAME = "org.hibernate.connection.ProxoolConnectionProvider";
|
||||
|
||||
public static final String INJECTION_DATA = "hibernate.connection_provider.injection_data";
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Class<ConnectionProvider> getServiceInitiated() {
|
||||
return ConnectionProvider.class;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public ConnectionProvider initiateService(Map configurationValues, ServicesRegistry registry) {
|
||||
final ClassLoaderService classLoaderService = registry.getService( ClassLoaderService.class );
|
||||
|
||||
ConnectionProvider connectionProvider = null;
|
||||
String providerClassName = (String) configurationValues.get( Environment.CONNECTION_PROVIDER );
|
||||
if ( providerClassName != null ) {
|
||||
connectionProvider = instantiateExplicitConnectionProvider( providerClassName, classLoaderService );
|
||||
}
|
||||
else if ( configurationValues.get( Environment.DATASOURCE ) != null ) {
|
||||
connectionProvider = new DatasourceConnectionProviderImpl();
|
||||
}
|
||||
|
||||
if ( connectionProvider == null ) {
|
||||
if ( c3p0ConfigDefined( configurationValues ) && c3p0ProviderPresent( classLoaderService ) ) {
|
||||
connectionProvider = instantiateExplicitConnectionProvider( C3P0_PROVIDER_CLASS_NAME,
|
||||
classLoaderService
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if ( connectionProvider == null ) {
|
||||
if ( proxoolConfigDefined( configurationValues ) && proxoolProviderPresent( classLoaderService ) ) {
|
||||
connectionProvider = instantiateExplicitConnectionProvider( PROXOOL_PROVIDER_CLASS_NAME,
|
||||
classLoaderService
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if ( connectionProvider == null ) {
|
||||
if ( configurationValues.get( Environment.URL ) != null ) {
|
||||
connectionProvider = new DriverManagerConnectionProviderImpl();
|
||||
}
|
||||
}
|
||||
|
||||
if ( connectionProvider == null ) {
|
||||
log.warn( "No appropriate connection provider encountered, assuming application will be supplying connections" );
|
||||
connectionProvider = new UserSuppliedConnectionProviderImpl();
|
||||
}
|
||||
|
||||
|
||||
final Map injectionData = (Map) configurationValues.get( INJECTION_DATA );
|
||||
if ( injectionData != null && injectionData.size() > 0 ) {
|
||||
final ConnectionProvider theConnectionProvider = connectionProvider;
|
||||
new BeanInfoHelper( connectionProvider.getClass() ).applyToBeanInfo(
|
||||
connectionProvider,
|
||||
new BeanInfoHelper.BeanInfoDelegate() {
|
||||
public void processBeanInfo(BeanInfo beanInfo) throws Exception {
|
||||
PropertyDescriptor[] descritors = beanInfo.getPropertyDescriptors();
|
||||
for ( int i = 0, size = descritors.length; i < size; i++ ) {
|
||||
String propertyName = descritors[i].getName();
|
||||
if ( injectionData.containsKey( propertyName ) ) {
|
||||
Method method = descritors[i].getWriteMethod();
|
||||
method.invoke(
|
||||
theConnectionProvider,
|
||||
injectionData.get( propertyName )
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return connectionProvider;
|
||||
}
|
||||
|
||||
private ConnectionProvider instantiateExplicitConnectionProvider(
|
||||
String providerClassName,
|
||||
ClassLoaderService classLoaderService) {
|
||||
try {
|
||||
log.info( "Instantiating explicit connection provider: " + providerClassName );
|
||||
return (ConnectionProvider) classLoaderService.classForName( providerClassName ).newInstance();
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
throw new HibernateException( "Could not instantiate connection provider [" + providerClassName + "]", e );
|
||||
}
|
||||
}
|
||||
|
||||
private boolean c3p0ProviderPresent(ClassLoaderService classLoaderService) {
|
||||
try {
|
||||
classLoaderService.classForName( C3P0_PROVIDER_CLASS_NAME );
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
log.warn(
|
||||
"c3p0 properties were encountered, but the " + C3P0_PROVIDER_CLASS_NAME +
|
||||
" provider class was not found on the classpath; these properties are going to be ignored."
|
||||
);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean c3p0ConfigDefined(Map configValues) {
|
||||
for ( Object key : configValues.keySet() ) {
|
||||
if ( String.class.isInstance( key )
|
||||
&& ( (String) key ).startsWith( C3P0_CONFIG_PREFIX ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean proxoolProviderPresent(ClassLoaderService classLoaderService) {
|
||||
try {
|
||||
classLoaderService.classForName( PROXOOL_PROVIDER_CLASS_NAME );
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
log.warn(
|
||||
"proxool properties were encountered, but the " + PROXOOL_PROVIDER_CLASS_NAME +
|
||||
" provider class was not found on the classpath; these properties are going to be ignored."
|
||||
);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean proxoolConfigDefined(Map configValues) {
|
||||
for ( Object key : configValues.keySet() ) {
|
||||
if ( String.class.isInstance( key )
|
||||
&& ( (String) key ).startsWith( PROXOOL_CONFIG_PREFIX ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform JDBC connection properties.
|
||||
*
|
||||
* Passed in the form <tt>hibernate.connection.*</tt> to the
|
||||
* format accepted by <tt>DriverManager</tt> by trimming the leading "<tt>hibernate.connection</tt>".
|
||||
*/
|
||||
public static Properties getConnectionProperties(Map<?,?> properties) {
|
||||
Properties result = new Properties();
|
||||
for ( Map.Entry entry : properties.entrySet() ) {
|
||||
if ( ! ( String.class.isInstance( entry.getKey() ) ) && String.class.isInstance( entry.getValue() ) ) {
|
||||
continue;
|
||||
}
|
||||
final String key = (String) entry.getKey();
|
||||
final String value = (String) entry.getValue();
|
||||
if ( key.startsWith( Environment.CONNECTION_PREFIX ) ) {
|
||||
if ( SPECIAL_PROPERTIES.contains( key ) ) {
|
||||
if ( Environment.USER.equals( key ) ) {
|
||||
result.setProperty( "user", value );
|
||||
}
|
||||
}
|
||||
else {
|
||||
final String passThruKey = key.substring( Environment.CONNECTION_PREFIX.length() + 1 );
|
||||
result.setProperty( passThruKey, value );
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static final Set<String> SPECIAL_PROPERTIES;
|
||||
|
||||
static {
|
||||
SPECIAL_PROPERTIES = new HashSet<String>();
|
||||
SPECIAL_PROPERTIES.add( Environment.DATASOURCE );
|
||||
SPECIAL_PROPERTIES.add( Environment.URL );
|
||||
SPECIAL_PROPERTIES.add( Environment.CONNECTION_PROVIDER );
|
||||
SPECIAL_PROPERTIES.add( Environment.POOL_SIZE );
|
||||
SPECIAL_PROPERTIES.add( Environment.ISOLATION );
|
||||
SPECIAL_PROPERTIES.add( Environment.DRIVER );
|
||||
SPECIAL_PROPERTIES.add( Environment.USER );
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,139 @@
|
||||
/*
|
||||
* 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.service.jdbc.connections.internal;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Map;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.service.jndi.spi.JndiService;
|
||||
import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
|
||||
import org.hibernate.service.spi.Configurable;
|
||||
import org.hibernate.service.spi.InjectService;
|
||||
import org.hibernate.service.spi.Stoppable;
|
||||
|
||||
/**
|
||||
* A {@link ConnectionProvider} that manages connections from an underlying {@link DataSource}.
|
||||
* <p/>
|
||||
* The {@link DataSource} to use may be specified by either:<ul>
|
||||
* <li>injection via {@link #setDataSource}</li>
|
||||
* <li>decaring the {@link DataSource} instance using the {@link Environment#DATASOURCE} config property</li>
|
||||
* <li>decaring the JNDI name under which the {@link DataSource} can be found via {@link Environment#DATASOURCE} config property</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Gavin King
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class DatasourceConnectionProviderImpl implements ConnectionProvider, Configurable, Stoppable {
|
||||
private static final Logger log = LoggerFactory.getLogger( DatasourceConnectionProviderImpl.class );
|
||||
|
||||
private DataSource dataSource;
|
||||
private String user;
|
||||
private String pass;
|
||||
private boolean useCredentials;
|
||||
private JndiService jndiService;
|
||||
|
||||
private boolean available;
|
||||
|
||||
public DataSource getDataSource() {
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
public void setDataSource(DataSource dataSource) {
|
||||
this.dataSource = dataSource;
|
||||
}
|
||||
|
||||
@InjectService( required = false )
|
||||
public void setJndiService(JndiService jndiService) {
|
||||
this.jndiService = jndiService;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void configure(Map configValues) {
|
||||
if ( this.dataSource == null ) {
|
||||
final Object dataSource = configValues.get( Environment.DATASOURCE );
|
||||
if ( DataSource.class.isInstance( dataSource ) ) {
|
||||
this.dataSource = (DataSource) dataSource;
|
||||
}
|
||||
else {
|
||||
final String dataSourceJndiName = (String) dataSource;
|
||||
if ( dataSourceJndiName == null ) {
|
||||
throw new HibernateException(
|
||||
"DataSource to use was not injected nor specified by [" + Environment.DATASOURCE
|
||||
+ "] configuration property"
|
||||
);
|
||||
}
|
||||
if ( jndiService == null ) {
|
||||
throw new HibernateException( "Unable to locate JndiService to lookup Datasource" );
|
||||
}
|
||||
this.dataSource = (DataSource) jndiService.locate( dataSourceJndiName );
|
||||
}
|
||||
}
|
||||
if ( this.dataSource == null ) {
|
||||
throw new HibernateException( "Unable to determine appropriate DataSource to use" );
|
||||
}
|
||||
|
||||
user = (String) configValues.get( Environment.USER );
|
||||
pass = (String) configValues.get( Environment.PASS );
|
||||
useCredentials = user != null || pass != null;
|
||||
available = true;
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
available = false;
|
||||
dataSource = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Connection getConnection() throws SQLException {
|
||||
if ( !available ) {
|
||||
throw new HibernateException( "Provider is closed!" );
|
||||
}
|
||||
return useCredentials ? dataSource.getConnection( user, pass ) : dataSource.getConnection();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void closeConnection(Connection connection) throws SQLException {
|
||||
connection.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public boolean supportsAggressiveRelease() {
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,196 @@
|
||||
/*
|
||||
* 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.service.jdbc.connections.internal;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
|
||||
import org.hibernate.service.spi.Configurable;
|
||||
import org.hibernate.service.spi.Stoppable;
|
||||
import org.hibernate.internal.util.config.ConfigurationHelper;
|
||||
import org.hibernate.util.ReflectHelper;
|
||||
|
||||
/**
|
||||
* A connection provider that uses the {@link java.sql.DriverManager} directly to open connections and provides
|
||||
* a very rudimentary connection pool.
|
||||
* <p/>
|
||||
* IMPL NOTE : not intended for production use!
|
||||
*
|
||||
* @author Gavin King
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class DriverManagerConnectionProviderImpl implements ConnectionProvider, Configurable, Stoppable {
|
||||
private static final Logger log = LoggerFactory.getLogger( DriverManagerConnectionProviderImpl.class );
|
||||
|
||||
private String url;
|
||||
private Properties connectionProps;
|
||||
private Integer isolation;
|
||||
private int poolSize;
|
||||
private boolean autocommit;
|
||||
|
||||
private final ArrayList<Connection> pool = new ArrayList<Connection>();
|
||||
private int checkedOut = 0;
|
||||
|
||||
public void configure(Map configurationValues) {
|
||||
log.info( "Using Hibernate built-in connection pool (not for production use!)" );
|
||||
|
||||
String driverClassName = (String) configurationValues.get( Environment.DRIVER );
|
||||
if ( driverClassName == null ) {
|
||||
log.warn( "no JDBC Driver class was specified by property " + Environment.DRIVER );
|
||||
}
|
||||
else {
|
||||
try {
|
||||
// trying via forName() first to be as close to DriverManager's semantics
|
||||
Class.forName( driverClassName );
|
||||
}
|
||||
catch ( ClassNotFoundException cnfe ) {
|
||||
try {
|
||||
ReflectHelper.classForName( driverClassName );
|
||||
}
|
||||
catch ( ClassNotFoundException e ) {
|
||||
throw new HibernateException( "Specified JDBC Driver " + driverClassName + " class not found", e );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
poolSize = ConfigurationHelper.getInt( Environment.POOL_SIZE, configurationValues, 20 ); // default pool size 20
|
||||
log.info( "Hibernate connection pool size: " + poolSize );
|
||||
|
||||
autocommit = ConfigurationHelper.getBoolean( Environment.AUTOCOMMIT, configurationValues );
|
||||
log.info("autocommit mode: " + autocommit);
|
||||
|
||||
isolation = ConfigurationHelper.getInteger( Environment.ISOLATION, configurationValues );
|
||||
if (isolation!=null)
|
||||
log.info( "JDBC isolation level: " + Environment.isolationLevelToString( isolation.intValue() ) );
|
||||
|
||||
url = (String) configurationValues.get( Environment.URL );
|
||||
if ( url == null ) {
|
||||
String msg = "JDBC URL was not specified by property " + Environment.URL;
|
||||
log.error( msg );
|
||||
throw new HibernateException( msg );
|
||||
}
|
||||
|
||||
connectionProps = ConnectionProviderInitiator.getConnectionProperties( configurationValues );
|
||||
|
||||
log.info( "using driver [" + driverClassName + "] at URL [" + url + "]" );
|
||||
// if debug level is enabled, then log the password, otherwise mask it
|
||||
if ( log.isDebugEnabled() ) {
|
||||
log.info( "connection properties: " + connectionProps );
|
||||
}
|
||||
else if ( log.isInfoEnabled() ) {
|
||||
log.info( "connection properties: " + ConfigurationHelper.maskOut( connectionProps, "password" ) );
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
log.info( "cleaning up connection pool [" + url + "]" );
|
||||
|
||||
for ( Connection connection : pool ) {
|
||||
try {
|
||||
connection.close();
|
||||
}
|
||||
catch (SQLException sqle) {
|
||||
log.warn( "problem closing pooled connection", sqle );
|
||||
}
|
||||
}
|
||||
pool.clear();
|
||||
}
|
||||
|
||||
public Connection getConnection() throws SQLException {
|
||||
log.trace( "total checked-out connections: " + checkedOut );
|
||||
|
||||
// essentially, if we have available connections in the pool, use one...
|
||||
synchronized (pool) {
|
||||
if ( !pool.isEmpty() ) {
|
||||
int last = pool.size() - 1;
|
||||
if ( log.isTraceEnabled() ) {
|
||||
log.trace( "using pooled JDBC connection, pool size: " + last );
|
||||
checkedOut++;
|
||||
}
|
||||
Connection pooled = (Connection) pool.remove(last);
|
||||
if ( isolation != null ) {
|
||||
pooled.setTransactionIsolation( isolation.intValue() );
|
||||
}
|
||||
if ( pooled.getAutoCommit() != autocommit ) {
|
||||
pooled.setAutoCommit( autocommit );
|
||||
}
|
||||
return pooled;
|
||||
}
|
||||
}
|
||||
|
||||
// otherwise we open a new connection...
|
||||
|
||||
log.debug( "opening new JDBC connection" );
|
||||
Connection conn = DriverManager.getConnection( url, connectionProps );
|
||||
if ( isolation != null ) {
|
||||
conn.setTransactionIsolation( isolation.intValue() );
|
||||
}
|
||||
if ( conn.getAutoCommit() != autocommit ) {
|
||||
conn.setAutoCommit(autocommit);
|
||||
}
|
||||
|
||||
if ( log.isDebugEnabled() ) {
|
||||
log.debug( "created connection to: " + url + ", Isolation Level: " + conn.getTransactionIsolation() );
|
||||
}
|
||||
|
||||
checkedOut++;
|
||||
|
||||
return conn;
|
||||
}
|
||||
|
||||
public void closeConnection(Connection conn) throws SQLException {
|
||||
checkedOut--;
|
||||
|
||||
// add to the pool if the max size is not yet reached.
|
||||
synchronized (pool) {
|
||||
int currentSize = pool.size();
|
||||
if ( currentSize < poolSize ) {
|
||||
if ( log.isTraceEnabled() ) log.trace("returning connection to pool, pool size: " + (currentSize + 1) );
|
||||
pool.add(conn);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
log.debug("closing JDBC connection");
|
||||
conn.close();
|
||||
}
|
||||
|
||||
protected void finalize() {
|
||||
stop();
|
||||
}
|
||||
|
||||
public boolean supportsAggressiveRelease() {
|
||||
return false;
|
||||
}
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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.service.jdbc.connections.internal;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
|
||||
|
||||
/**
|
||||
* An implementation of the {@link ConnectionProvider} interface that simply throws an exception when a connection
|
||||
* is requested, the assumption being that the application is responsible for handing the connection to use to
|
||||
* the session
|
||||
*
|
||||
* @author Gavin King
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class UserSuppliedConnectionProviderImpl implements ConnectionProvider {
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Connection getConnection() throws SQLException {
|
||||
throw new UnsupportedOperationException( "The application must supply JDBC connections" );
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void closeConnection(Connection conn) throws SQLException {
|
||||
throw new UnsupportedOperationException( "The application must supply JDBC connections" );
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public boolean supportsAggressiveRelease() {
|
||||
return false;
|
||||
}
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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.service.jdbc.connections.spi;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.service.spi.Service;
|
||||
|
||||
/**
|
||||
* A contract for obtaining JDBC connections.
|
||||
* <p/>
|
||||
* Implementors might also implement connection pooling.
|
||||
* <p/>
|
||||
* Implementors should provide a public default constructor.
|
||||
*
|
||||
* @author Gavin King
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface ConnectionProvider extends Service {
|
||||
/**
|
||||
* Obtains a connection for Hibernate use according to the underlying strategy of this provider.
|
||||
*
|
||||
* @return The obtained JDBC connection
|
||||
*
|
||||
* @throws SQLException Indicates a problem opening a connection
|
||||
* @throws HibernateException Inidcates a problem otherwise obtaining a connnection.
|
||||
*/
|
||||
public Connection getConnection() throws SQLException;
|
||||
|
||||
/**
|
||||
* Release a connection from Hibernate use.
|
||||
*
|
||||
* @param conn The JDBC connection to release
|
||||
*
|
||||
* @throws SQLException Indicates a problem closing the connection
|
||||
* @throws HibernateException Inidcates a problem otherwise releasing a connnection.
|
||||
*/
|
||||
public void closeConnection(Connection conn) throws SQLException;
|
||||
|
||||
/**
|
||||
* Does this connection provider support aggressive release of JDBC
|
||||
* connections and re-acquistion of those connections (if need be) later?
|
||||
* <p/>
|
||||
* This is used in conjunction with {@link org.hibernate.cfg.Environment.RELEASE_CONNECTIONS}
|
||||
* to aggressively release JDBC connections. However, the configured ConnectionProvider
|
||||
* must support re-acquisition of the same underlying connection for that semantic to work.
|
||||
* <p/>
|
||||
* Typically, this is only true in managed environments where a container
|
||||
* tracks connections by transaction or thread.
|
||||
*
|
||||
* Note that JTA semantic depends on the fact that the underlying connection provider does
|
||||
* support aggressive release.
|
||||
*/
|
||||
public boolean supportsAggressiveRelease();
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* 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.service.jdbc.dialect.internal;
|
||||
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.hibernate.JDBCException;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.dialect.resolver.BasicSQLExceptionConverter;
|
||||
import org.hibernate.service.jdbc.dialect.spi.DialectResolver;
|
||||
import org.hibernate.exception.JDBCConnectionException;
|
||||
|
||||
/**
|
||||
* A templated resolver impl which delegates to the {@link #resolveDialectInternal} method
|
||||
* and handles any thrown {@link SQLException SQL errors}.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public abstract class AbstractDialectResolver implements DialectResolver {
|
||||
private static final Logger log = LoggerFactory.getLogger( AbstractDialectResolver.class );
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* <p/>
|
||||
* Here we template the resolution, delegating to {@link #resolveDialectInternal} and handling
|
||||
* {@link java.sql.SQLException}s properly.
|
||||
*/
|
||||
public final Dialect resolveDialect(DatabaseMetaData metaData) {
|
||||
try {
|
||||
return resolveDialectInternal( metaData );
|
||||
}
|
||||
catch ( SQLException sqlException ) {
|
||||
JDBCException jdbcException = BasicSQLExceptionConverter.INSTANCE.convert( sqlException );
|
||||
if ( jdbcException instanceof JDBCConnectionException ) {
|
||||
throw jdbcException;
|
||||
}
|
||||
else {
|
||||
log.warn( BasicSQLExceptionConverter.MSG + " : " + sqlException.getMessage() );
|
||||
return null;
|
||||
}
|
||||
}
|
||||
catch ( Throwable t ) {
|
||||
log.warn( "Error executing resolver [" + this + "] : " + t.getMessage() );
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the actual resolution without caring about handling {@link SQLException}s.
|
||||
*
|
||||
* @param metaData The database metadata
|
||||
* @return The resolved dialect, or null if we could not resolve.
|
||||
* @throws SQLException Indicates problems accessing the metadata.
|
||||
*/
|
||||
protected abstract Dialect resolveDialectInternal(DatabaseMetaData metaData) throws SQLException;
|
||||
}
|
@ -0,0 +1,123 @@
|
||||
/*
|
||||
* 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.service.jdbc.dialect.internal;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.service.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.service.classloading.spi.ClassLoadingException;
|
||||
import org.hibernate.service.jdbc.dialect.spi.DialectFactory;
|
||||
import org.hibernate.service.jdbc.dialect.spi.DialectResolver;
|
||||
import org.hibernate.service.spi.InjectService;
|
||||
|
||||
/**
|
||||
* Standard implementation of the {@link DialectFactory} service.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class DialectFactoryImpl implements DialectFactory {
|
||||
private ClassLoaderService classLoaderService;
|
||||
|
||||
@InjectService
|
||||
public void setClassLoaderService(ClassLoaderService classLoaderService) {
|
||||
this.classLoaderService = classLoaderService;
|
||||
}
|
||||
|
||||
private DialectResolver dialectResolver;
|
||||
|
||||
@InjectService
|
||||
public void setDialectResolver(DialectResolver dialectResolver) {
|
||||
this.dialectResolver = dialectResolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Dialect buildDialect(Map configValues, Connection connection) throws HibernateException {
|
||||
final String dialectName = (String) configValues.get( Environment.DIALECT );
|
||||
if ( dialectName != null ) {
|
||||
return constructDialect( dialectName );
|
||||
}
|
||||
else {
|
||||
return determineDialect( connection );
|
||||
}
|
||||
}
|
||||
|
||||
private Dialect constructDialect(String dialectName) {
|
||||
try {
|
||||
return ( Dialect ) classLoaderService.classForName( dialectName ).newInstance();
|
||||
}
|
||||
catch ( ClassLoadingException cnfe ) {
|
||||
throw new HibernateException( "Dialect class not found: " + dialectName, cnfe );
|
||||
}
|
||||
catch ( HibernateException e ) {
|
||||
throw e;
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
throw new HibernateException( "Could not instantiate dialect class", e );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the appropriate Dialect to use given the connection.
|
||||
*
|
||||
* @param connection The configured connection.
|
||||
* @return The appropriate dialect instance.
|
||||
*
|
||||
* @throws HibernateException No connection given or no resolver could make
|
||||
* the determination from the given connection.
|
||||
*/
|
||||
private Dialect determineDialect(Connection connection) {
|
||||
if ( connection == null ) {
|
||||
throw new HibernateException( "Connection cannot be null when 'hibernate.dialect' not set" );
|
||||
}
|
||||
|
||||
try {
|
||||
final DatabaseMetaData databaseMetaData = connection.getMetaData();
|
||||
final Dialect dialect = dialectResolver.resolveDialect( databaseMetaData );
|
||||
|
||||
if ( dialect == null ) {
|
||||
throw new HibernateException(
|
||||
"Unable to determine Dialect to use [name=" + databaseMetaData.getDatabaseProductName() +
|
||||
", majorVersion=" + databaseMetaData.getDatabaseMajorVersion() +
|
||||
"]; user must register resolver or explicitly set 'hibernate.dialect'"
|
||||
);
|
||||
}
|
||||
|
||||
return dialect;
|
||||
}
|
||||
catch ( SQLException sqlException ) {
|
||||
throw new HibernateException(
|
||||
"Unable to access java.sql.DatabaseMetaData to determine appropriate Dialect to use",
|
||||
sqlException
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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.service.jdbc.dialect.internal;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.service.jdbc.dialect.spi.DialectFactory;
|
||||
import org.hibernate.service.spi.ServicesRegistry;
|
||||
import org.hibernate.service.spi.ServiceInitiator;
|
||||
|
||||
/**
|
||||
* Standard initiator for the standard {@link DialectFactory} service
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class DialectFactoryInitiator implements ServiceInitiator<DialectFactory> {
|
||||
public static final DialectFactoryInitiator INSTANCE = new DialectFactoryInitiator();
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Class<DialectFactory> getServiceInitiated() {
|
||||
return DialectFactory.class;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public DialectFactory initiateService(Map configVales, ServicesRegistry registry) {
|
||||
return new DialectFactoryImpl();
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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.service.jdbc.dialect.internal;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.service.jdbc.dialect.spi.DialectResolver;
|
||||
import org.hibernate.service.spi.ServicesRegistry;
|
||||
import org.hibernate.service.spi.ServiceInitiator;
|
||||
|
||||
/**
|
||||
* Standard initiator for the standard {@link DialectResolver} service
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class DialectResolverInitiator implements ServiceInitiator<DialectResolver> {
|
||||
public static final DialectResolverInitiator INSTANCE = new DialectResolverInitiator();
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Class<DialectResolver> getServiceInitiated() {
|
||||
return DialectResolver.class;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public DialectResolver initiateService(Map configVales, ServicesRegistry registry) {
|
||||
return new StandardDialectResolver();
|
||||
}
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* 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.service.jdbc.dialect.internal;
|
||||
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.service.jdbc.dialect.spi.DialectResolver;
|
||||
import org.hibernate.exception.JDBCConnectionException;
|
||||
|
||||
/**
|
||||
* A {@link DialectResolver} implementation which coordinates resolution by delegating to sub-resolvers.
|
||||
*
|
||||
* @author Tomoto Shimizu Washio
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class DialectResolverSet implements DialectResolver {
|
||||
private static final Logger log = LoggerFactory.getLogger( DialectResolverSet.class );
|
||||
|
||||
private List<DialectResolver> resolvers;
|
||||
|
||||
public DialectResolverSet() {
|
||||
this( new ArrayList<DialectResolver>() );
|
||||
}
|
||||
|
||||
public DialectResolverSet(List<DialectResolver> resolvers) {
|
||||
this.resolvers = resolvers;
|
||||
}
|
||||
|
||||
public DialectResolverSet(DialectResolver... resolvers) {
|
||||
this( Arrays.asList( resolvers ) );
|
||||
}
|
||||
|
||||
public Dialect resolveDialect(DatabaseMetaData metaData) throws JDBCConnectionException {
|
||||
for ( DialectResolver resolver : resolvers ) {
|
||||
try {
|
||||
Dialect dialect = resolver.resolveDialect( metaData );
|
||||
if ( dialect != null ) {
|
||||
return dialect;
|
||||
}
|
||||
}
|
||||
catch ( JDBCConnectionException e ) {
|
||||
throw e;
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
log.info( "sub-resolver threw unexpected exception, continuing to next : " + e.getMessage() );
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a resolver at the end of the underlying resolver list. The resolver added by this method is at lower
|
||||
* priority than any other existing resolvers.
|
||||
*
|
||||
* @param resolver The resolver to add.
|
||||
*/
|
||||
public void addResolver(DialectResolver resolver) {
|
||||
resolvers.add( resolver );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a resolver at the beginning of the underlying resolver list. The resolver added by this method is at higher
|
||||
* priority than any other existing resolvers.
|
||||
*
|
||||
* @param resolver The resolver to add.
|
||||
*/
|
||||
public void addResolverAtFirst(DialectResolver resolver) {
|
||||
resolvers.add( 0, resolver );
|
||||
}
|
||||
}
|
@ -0,0 +1,137 @@
|
||||
/*
|
||||
* 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.service.jdbc.dialect.internal;
|
||||
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.hibernate.dialect.DB2Dialect;
|
||||
import org.hibernate.dialect.DerbyDialect;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.dialect.H2Dialect;
|
||||
import org.hibernate.dialect.HSQLDialect;
|
||||
import org.hibernate.dialect.InformixDialect;
|
||||
import org.hibernate.dialect.Ingres10Dialect;
|
||||
import org.hibernate.dialect.Ingres9Dialect;
|
||||
import org.hibernate.dialect.IngresDialect;
|
||||
import org.hibernate.dialect.MySQLDialect;
|
||||
import org.hibernate.dialect.Oracle10gDialect;
|
||||
import org.hibernate.dialect.Oracle8iDialect;
|
||||
import org.hibernate.dialect.Oracle9iDialect;
|
||||
import org.hibernate.dialect.PostgreSQLDialect;
|
||||
import org.hibernate.dialect.SQLServerDialect;
|
||||
import org.hibernate.dialect.SybaseASE15Dialect;
|
||||
import org.hibernate.dialect.SybaseAnywhereDialect;
|
||||
|
||||
/**
|
||||
* The standard Hibernate Dialect resolver.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class StandardDialectResolver extends AbstractDialectResolver {
|
||||
private static final Logger log = LoggerFactory.getLogger( StandardDialectResolver.class );
|
||||
|
||||
protected Dialect resolveDialectInternal(DatabaseMetaData metaData) throws SQLException {
|
||||
String databaseName = metaData.getDatabaseProductName();
|
||||
int databaseMajorVersion = metaData.getDatabaseMajorVersion();
|
||||
|
||||
if ( "HSQL Database Engine".equals( databaseName ) ) {
|
||||
return new HSQLDialect();
|
||||
}
|
||||
|
||||
if ( "H2".equals( databaseName ) ) {
|
||||
return new H2Dialect();
|
||||
}
|
||||
|
||||
if ( "MySQL".equals( databaseName ) ) {
|
||||
return new MySQLDialect();
|
||||
}
|
||||
|
||||
if ( "PostgreSQL".equals( databaseName ) ) {
|
||||
return new PostgreSQLDialect();
|
||||
}
|
||||
|
||||
if ( "Apache Derby".equals( databaseName ) ) {
|
||||
return new DerbyDialect();
|
||||
}
|
||||
|
||||
if ( "ingres".equalsIgnoreCase( databaseName ) ) {
|
||||
switch( databaseMajorVersion ) {
|
||||
case 9:
|
||||
int databaseMinorVersion = metaData.getDatabaseMinorVersion();
|
||||
if (databaseMinorVersion > 2) {
|
||||
return new Ingres9Dialect();
|
||||
}
|
||||
return new IngresDialect();
|
||||
case 10:
|
||||
log.warn( "Ingres " + databaseMajorVersion + " is not yet fully supported; using Ingres 9.3 dialect" );
|
||||
return new Ingres10Dialect();
|
||||
default:
|
||||
log.warn( "Unknown Ingres major version [" + databaseMajorVersion + "] using Ingres 9.2 dialect" );
|
||||
}
|
||||
return new IngresDialect();
|
||||
}
|
||||
|
||||
if ( databaseName.startsWith( "Microsoft SQL Server" ) ) {
|
||||
return new SQLServerDialect();
|
||||
}
|
||||
|
||||
if ( "Sybase SQL Server".equals( databaseName ) || "Adaptive Server Enterprise".equals( databaseName ) ) {
|
||||
return new SybaseASE15Dialect();
|
||||
}
|
||||
|
||||
if ( databaseName.startsWith( "Adaptive Server Anywhere" ) ) {
|
||||
return new SybaseAnywhereDialect();
|
||||
}
|
||||
|
||||
if ( "Informix Dynamic Server".equals( databaseName ) ) {
|
||||
return new InformixDialect();
|
||||
}
|
||||
|
||||
if ( databaseName.startsWith( "DB2/" ) ) {
|
||||
return new DB2Dialect();
|
||||
}
|
||||
|
||||
if ( "Oracle".equals( databaseName ) ) {
|
||||
switch ( databaseMajorVersion ) {
|
||||
case 11:
|
||||
log.warn( "Oracle 11g is not yet fully supported; using 10g dialect" );
|
||||
return new Oracle10gDialect();
|
||||
case 10:
|
||||
return new Oracle10gDialect();
|
||||
case 9:
|
||||
return new Oracle9iDialect();
|
||||
case 8:
|
||||
return new Oracle8iDialect();
|
||||
default:
|
||||
log.warn( "unknown Oracle major version [" + databaseMajorVersion + "]" );
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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.service.jdbc.dialect.spi;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.service.spi.Service;
|
||||
|
||||
/**
|
||||
* A factory for generating Dialect instances.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface DialectFactory extends Service {
|
||||
/**
|
||||
* Builds an appropriate Dialect instance.
|
||||
* <p/>
|
||||
* If a dialect is explicitly named in the incoming properties, it should used. Otherwise, it is
|
||||
* determined by dialect resolvers based on the passed connection.
|
||||
* <p/>
|
||||
* An exception is thrown if a dialect was not explicitly set and no resolver could make
|
||||
* the determination from the given connection.
|
||||
*
|
||||
* @param configValues The configuration properties.
|
||||
* @param connection The configured connection.
|
||||
*
|
||||
* @return The appropriate dialect instance.
|
||||
*
|
||||
* @throws HibernateException No dialect specified and no resolver could make the determination.
|
||||
*/
|
||||
public Dialect buildDialect(Map configValues, Connection connection) throws HibernateException;
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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.service.jdbc.dialect.spi;
|
||||
|
||||
import java.sql.DatabaseMetaData;
|
||||
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.exception.JDBCConnectionException;
|
||||
import org.hibernate.service.spi.Service;
|
||||
|
||||
/**
|
||||
* Contract for determining the {@link Dialect} to use based on a JDBC {@link java.sql.Connection}.
|
||||
*
|
||||
* @author Tomoto Shimizu Washio
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface DialectResolver extends Service {
|
||||
/**
|
||||
* Determine the {@link Dialect} to use based on the given JDBC {@link DatabaseMetaData}. Implementations are
|
||||
* expected to return the {@link Dialect} instance to use, or null if the {@link DatabaseMetaData} does not match
|
||||
* the criteria handled by this impl.
|
||||
*
|
||||
* @param metaData The JDBC metadata.
|
||||
*
|
||||
* @return The dialect to use, or null.
|
||||
*
|
||||
* @throws JDBCConnectionException Indicates a 'non transient connection problem', which indicates that
|
||||
* we should stop resolution attempts.
|
||||
*/
|
||||
public Dialect resolveDialect(DatabaseMetaData metaData) throws JDBCConnectionException;
|
||||
|
||||
}
|
@ -0,0 +1,218 @@
|
||||
/*
|
||||
* 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.service.jdbc.internal;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.service.jdbc.spi.SQLExceptionHelper;
|
||||
import org.hibernate.service.jdbc.spi.JdbcResourceRegistry;
|
||||
import org.hibernate.service.jdbc.spi.InvalidatableWrapper;
|
||||
|
||||
/**
|
||||
* Standard implementation of the {@link org.hibernate.engine.jdbc.spi.JdbcResourceRegistry} contract
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class JdbcResourceRegistryImpl implements JdbcResourceRegistry {
|
||||
private static final Logger log = LoggerFactory.getLogger( JdbcResourceRegistryImpl.class );
|
||||
|
||||
private final HashMap<Statement,Set<ResultSet>> xref = new HashMap<Statement,Set<ResultSet>>();
|
||||
private final Set<ResultSet> unassociatedResultSets = new HashSet<ResultSet>();
|
||||
private final SQLExceptionHelper exceptionHelper;
|
||||
|
||||
public JdbcResourceRegistryImpl(SQLExceptionHelper exceptionHelper) {
|
||||
this.exceptionHelper = exceptionHelper;
|
||||
}
|
||||
|
||||
public void register(Statement statement) {
|
||||
log.trace( "registering statement [" + statement + "]" );
|
||||
if ( xref.containsKey( statement ) ) {
|
||||
throw new HibernateException( "statement already registered with JDBCContainer" );
|
||||
}
|
||||
xref.put( statement, null );
|
||||
}
|
||||
|
||||
public void release(Statement statement) {
|
||||
log.trace( "releasing statement [" + statement + "]" );
|
||||
Set<ResultSet> resultSets = xref.get( statement );
|
||||
if ( resultSets != null ) {
|
||||
for ( ResultSet resultSet : resultSets ) {
|
||||
close( resultSet );
|
||||
}
|
||||
resultSets.clear();
|
||||
}
|
||||
xref.remove( statement );
|
||||
close( statement );
|
||||
}
|
||||
|
||||
public void register(ResultSet resultSet) {
|
||||
log.trace( "registering result set [" + resultSet + "]" );
|
||||
Statement statement;
|
||||
try {
|
||||
statement = resultSet.getStatement();
|
||||
}
|
||||
catch ( SQLException e ) {
|
||||
throw exceptionHelper.convert( e, "unable to access statement from resultset" );
|
||||
}
|
||||
if ( statement != null ) {
|
||||
if ( log.isWarnEnabled() && !xref.containsKey( statement ) ) {
|
||||
log.warn( "resultset's statement was not yet registered" );
|
||||
}
|
||||
Set<ResultSet> resultSets = xref.get( statement );
|
||||
if ( resultSets == null ) {
|
||||
resultSets = new HashSet<ResultSet>();
|
||||
xref.put( statement, resultSets );
|
||||
}
|
||||
resultSets.add( resultSet );
|
||||
}
|
||||
else {
|
||||
unassociatedResultSets.add( resultSet );
|
||||
}
|
||||
}
|
||||
|
||||
public void release(ResultSet resultSet) {
|
||||
log.trace( "releasing result set [{}]", resultSet );
|
||||
Statement statement;
|
||||
try {
|
||||
statement = resultSet.getStatement();
|
||||
}
|
||||
catch ( SQLException e ) {
|
||||
throw exceptionHelper.convert( e, "unable to access statement from resultset" );
|
||||
}
|
||||
if ( statement != null ) {
|
||||
if ( log.isWarnEnabled() && !xref.containsKey( statement ) ) {
|
||||
log.warn( "resultset's statement was not registered" );
|
||||
}
|
||||
Set<ResultSet> resultSets = xref.get( statement );
|
||||
if ( resultSets != null ) {
|
||||
resultSets.remove( resultSet );
|
||||
if ( resultSets.isEmpty() ) {
|
||||
xref.remove( statement );
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
boolean removed = unassociatedResultSets.remove( resultSet );
|
||||
if ( !removed ) {
|
||||
log.warn( "ResultSet had no statement associated with it, but was not yet registered" );
|
||||
}
|
||||
}
|
||||
close( resultSet );
|
||||
}
|
||||
|
||||
public boolean hasRegisteredResources() {
|
||||
return ! ( xref.isEmpty() && unassociatedResultSets.isEmpty() );
|
||||
}
|
||||
|
||||
public void releaseResources() {
|
||||
log.trace( "releasing JDBC container resources [{}]", this );
|
||||
cleanup();
|
||||
}
|
||||
|
||||
private void cleanup() {
|
||||
for ( Map.Entry<Statement,Set<ResultSet>> entry : xref.entrySet() ) {
|
||||
if ( entry.getValue() != null ) {
|
||||
for ( ResultSet resultSet : entry.getValue() ) {
|
||||
close( resultSet );
|
||||
}
|
||||
entry.getValue().clear();
|
||||
}
|
||||
close( entry.getKey() );
|
||||
}
|
||||
xref.clear();
|
||||
|
||||
for ( ResultSet resultSet : unassociatedResultSets ) {
|
||||
close( resultSet );
|
||||
}
|
||||
unassociatedResultSets.clear();
|
||||
}
|
||||
|
||||
public void close() {
|
||||
log.trace( "closing JDBC container [{}]", this );
|
||||
cleanup();
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
protected void close(Statement statement) {
|
||||
log.trace( "closing prepared statement [{}]", statement );
|
||||
|
||||
if ( statement instanceof InvalidatableWrapper ) {
|
||||
InvalidatableWrapper<Statement> wrapper = ( InvalidatableWrapper<Statement> ) statement;
|
||||
close( wrapper.getWrappedObject() );
|
||||
wrapper.invalidate();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// if we are unable to "clean" the prepared statement,
|
||||
// we do not close it
|
||||
try {
|
||||
if ( statement.getMaxRows() != 0 ) {
|
||||
statement.setMaxRows( 0 );
|
||||
}
|
||||
if ( statement.getQueryTimeout() != 0 ) {
|
||||
statement.setQueryTimeout( 0 );
|
||||
}
|
||||
}
|
||||
catch( SQLException sqle ) {
|
||||
// there was a problem "cleaning" the prepared statement
|
||||
log.debug( "Exception clearing maxRows/queryTimeout [{}]", sqle.getMessage() );
|
||||
return; // EARLY EXIT!!!
|
||||
}
|
||||
statement.close();
|
||||
}
|
||||
catch( SQLException sqle ) {
|
||||
log.debug( "Unable to release statement [{}]", sqle.getMessage() );
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
protected void close(ResultSet resultSet) {
|
||||
log.trace( "closing result set [{}]", resultSet );
|
||||
|
||||
if ( resultSet instanceof InvalidatableWrapper ) {
|
||||
InvalidatableWrapper<ResultSet> wrapper = (InvalidatableWrapper<ResultSet>) resultSet;
|
||||
close( wrapper.getWrappedObject() );
|
||||
wrapper.invalidate();
|
||||
}
|
||||
|
||||
try {
|
||||
resultSet.close();
|
||||
}
|
||||
catch( SQLException e ) {
|
||||
log.debug( "Unable to release result set [{}]", e.getMessage() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,339 @@
|
||||
/*
|
||||
* 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.service.jdbc.internal;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
|
||||
import org.hibernate.service.jdbc.dialect.spi.DialectFactory;
|
||||
import org.hibernate.service.jdbc.spi.ExtractedDatabaseMetaData;
|
||||
import org.hibernate.service.jdbc.spi.JdbcServices;
|
||||
import org.hibernate.service.jdbc.spi.SQLExceptionHelper;
|
||||
import org.hibernate.service.jdbc.spi.SQLStatementLogger;
|
||||
import org.hibernate.service.jdbc.spi.SchemaNameResolver;
|
||||
import org.hibernate.internal.util.config.ConfigurationHelper;
|
||||
import org.hibernate.internal.util.jdbc.TypeInfo;
|
||||
import org.hibernate.service.spi.Configurable;
|
||||
import org.hibernate.service.spi.InjectService;
|
||||
import org.hibernate.util.ReflectHelper;
|
||||
import org.hibernate.internal.util.jdbc.TypeInfoExtracter;
|
||||
|
||||
/**
|
||||
* Standard implementation of the {@link JdbcServices} contract
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class JdbcServicesImpl implements JdbcServices, Configurable {
|
||||
private static final Logger log = LoggerFactory.getLogger( JdbcServicesImpl.class );
|
||||
|
||||
private ConnectionProvider connectionProvider;
|
||||
|
||||
@InjectService
|
||||
public void setConnectionProvider(ConnectionProvider connectionProvider) {
|
||||
this.connectionProvider = connectionProvider;
|
||||
}
|
||||
|
||||
private DialectFactory dialectFactory;
|
||||
|
||||
@InjectService
|
||||
public void setDialectFactory(DialectFactory dialectFactory) {
|
||||
this.dialectFactory = dialectFactory;
|
||||
}
|
||||
|
||||
private Dialect dialect;
|
||||
private SQLStatementLogger sqlStatementLogger;
|
||||
private SQLExceptionHelper sqlExceptionHelper;
|
||||
private ExtractedDatabaseMetaData extractedMetaDataSupport;
|
||||
|
||||
public void configure(Map configValues) {
|
||||
Dialect dialect = null;
|
||||
|
||||
boolean metaSupportsScrollable = false;
|
||||
boolean metaSupportsGetGeneratedKeys = false;
|
||||
boolean metaSupportsBatchUpdates = false;
|
||||
boolean metaReportsDDLCausesTxnCommit = false;
|
||||
boolean metaReportsDDLInTxnSupported = true;
|
||||
String extraKeywordsString = "";
|
||||
int sqlStateType = -1;
|
||||
boolean lobLocatorUpdateCopy = false;
|
||||
String catalogName = null;
|
||||
String schemaName = null;
|
||||
LinkedHashSet<TypeInfo> typeInfoSet = new LinkedHashSet<TypeInfo>();
|
||||
|
||||
// 'hibernate.temp.use_jdbc_metadata_defaults' is a temporary magic value.
|
||||
// The need for it is intended to be alleviated with future development, thus it is
|
||||
// not defined as an Environment constant...
|
||||
//
|
||||
// it is used to control whether we should consult the JDBC metadata to determine
|
||||
// certain Settings default values; it is useful to *not* do this when the database
|
||||
// may not be available (mainly in tools usage).
|
||||
boolean useJdbcMetadata = ConfigurationHelper.getBoolean( "hibernate.temp.use_jdbc_metadata_defaults", configValues, true );
|
||||
if ( useJdbcMetadata ) {
|
||||
try {
|
||||
Connection conn = connectionProvider.getConnection();
|
||||
try {
|
||||
DatabaseMetaData meta = conn.getMetaData();
|
||||
log.info( "Database ->\n" +
|
||||
" name : " + meta.getDatabaseProductName() + '\n' +
|
||||
" version : " + meta.getDatabaseProductVersion() + '\n' +
|
||||
" major : " + meta.getDatabaseMajorVersion() + '\n' +
|
||||
" minor : " + meta.getDatabaseMinorVersion()
|
||||
);
|
||||
log.info( "Driver ->\n" +
|
||||
" name : " + meta.getDriverName() + '\n' +
|
||||
" version : " + meta.getDriverVersion() + '\n' +
|
||||
" major : " + meta.getDriverMajorVersion() + '\n' +
|
||||
" minor : " + meta.getDriverMinorVersion()
|
||||
);
|
||||
log.info( "JDBC version : " + meta.getJDBCMajorVersion() + "." + meta.getJDBCMinorVersion() );
|
||||
|
||||
metaSupportsScrollable = meta.supportsResultSetType( ResultSet.TYPE_SCROLL_INSENSITIVE );
|
||||
metaSupportsBatchUpdates = meta.supportsBatchUpdates();
|
||||
metaReportsDDLCausesTxnCommit = meta.dataDefinitionCausesTransactionCommit();
|
||||
metaReportsDDLInTxnSupported = !meta.dataDefinitionIgnoredInTransactions();
|
||||
metaSupportsGetGeneratedKeys = meta.supportsGetGeneratedKeys();
|
||||
extraKeywordsString = meta.getSQLKeywords();
|
||||
sqlStateType = meta.getSQLStateType();
|
||||
lobLocatorUpdateCopy = meta.locatorsUpdateCopy();
|
||||
typeInfoSet.addAll( TypeInfoExtracter.extractTypeInfo( meta ) );
|
||||
|
||||
dialect = dialectFactory.buildDialect( configValues, conn );
|
||||
|
||||
catalogName = conn.getCatalog();
|
||||
SchemaNameResolver schemaNameResolver = determineExplicitSchemaNameResolver( configValues );
|
||||
if ( schemaNameResolver == null ) {
|
||||
// todo : add dialect method
|
||||
// schemaNameResolver = dialect.getSchemaNameResolver();
|
||||
}
|
||||
if ( schemaNameResolver != null ) {
|
||||
schemaName = schemaNameResolver.resolveSchemaName( conn );
|
||||
}
|
||||
}
|
||||
catch ( SQLException sqle ) {
|
||||
log.warn( "Could not obtain connection metadata", sqle );
|
||||
}
|
||||
finally {
|
||||
connectionProvider.closeConnection( conn );
|
||||
}
|
||||
}
|
||||
catch ( SQLException sqle ) {
|
||||
log.warn( "Could not obtain connection to query metadata", sqle );
|
||||
dialect = dialectFactory.buildDialect( configValues, null );
|
||||
}
|
||||
catch ( UnsupportedOperationException uoe ) {
|
||||
// user supplied JDBC connections
|
||||
dialect = dialectFactory.buildDialect( configValues, null );
|
||||
}
|
||||
}
|
||||
else {
|
||||
dialect = dialectFactory.buildDialect( configValues, null );
|
||||
}
|
||||
|
||||
final boolean showSQL = ConfigurationHelper.getBoolean( Environment.SHOW_SQL, configValues, false );
|
||||
final boolean formatSQL = ConfigurationHelper.getBoolean( Environment.FORMAT_SQL, configValues, false );
|
||||
|
||||
this.dialect = dialect;
|
||||
this.sqlStatementLogger = new SQLStatementLogger( showSQL, formatSQL );
|
||||
this.sqlExceptionHelper = new SQLExceptionHelper( dialect.buildSQLExceptionConverter() );
|
||||
this.extractedMetaDataSupport = new ExtractedDatabaseMetaDataImpl(
|
||||
metaSupportsScrollable,
|
||||
metaSupportsGetGeneratedKeys,
|
||||
metaSupportsBatchUpdates,
|
||||
metaReportsDDLInTxnSupported,
|
||||
metaReportsDDLCausesTxnCommit,
|
||||
parseKeywords( extraKeywordsString ),
|
||||
parseSQLStateType( sqlStateType ),
|
||||
lobLocatorUpdateCopy,
|
||||
schemaName,
|
||||
catalogName,
|
||||
typeInfoSet
|
||||
);
|
||||
}
|
||||
|
||||
// todo : add to Environment
|
||||
public static final String SCHEMA_NAME_RESOLVER = "hibernate.schema_name_resolver";
|
||||
|
||||
private SchemaNameResolver determineExplicitSchemaNameResolver(Map configValues) {
|
||||
Object setting = configValues.get( SCHEMA_NAME_RESOLVER );
|
||||
if ( SchemaNameResolver.class.isInstance( setting ) ) {
|
||||
return (SchemaNameResolver) setting;
|
||||
}
|
||||
|
||||
String resolverClassName = (String) setting;
|
||||
if ( resolverClassName != null ) {
|
||||
try {
|
||||
Class resolverClass = ReflectHelper.classForName( resolverClassName, getClass() );
|
||||
return (SchemaNameResolver) ReflectHelper.getDefaultConstructor( resolverClass ).newInstance();
|
||||
}
|
||||
catch ( ClassNotFoundException e ) {
|
||||
log.warn( "Unable to locate configured schema name resolver class [" + resolverClassName + "]" + e.toString() );
|
||||
}
|
||||
catch ( InvocationTargetException e ) {
|
||||
log.warn( "Unable to instantiate configured schema name resolver [" + resolverClassName + "]" + e.getTargetException().toString() );
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
log.warn( "Unable to instantiate configured schema name resolver [" + resolverClassName + "]" + e.toString() );
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Set<String> parseKeywords(String extraKeywordsString) {
|
||||
Set<String> keywordSet = new HashSet<String>();
|
||||
for ( String keyword : extraKeywordsString.split( "," ) ) {
|
||||
keywordSet.add( keyword );
|
||||
}
|
||||
return keywordSet;
|
||||
}
|
||||
|
||||
private ExtractedDatabaseMetaData.SQLStateType parseSQLStateType(int sqlStateType) {
|
||||
switch ( sqlStateType ) {
|
||||
case DatabaseMetaData.sqlStateSQL99 : {
|
||||
return ExtractedDatabaseMetaData.SQLStateType.SQL99;
|
||||
}
|
||||
case DatabaseMetaData.sqlStateXOpen : {
|
||||
return ExtractedDatabaseMetaData.SQLStateType.XOpen;
|
||||
}
|
||||
default : {
|
||||
return ExtractedDatabaseMetaData.SQLStateType.UNKOWN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class ExtractedDatabaseMetaDataImpl implements ExtractedDatabaseMetaData {
|
||||
private final boolean supportsScrollableResults;
|
||||
private final boolean supportsGetGeneratedKeys;
|
||||
private final boolean supportsBatchUpdates;
|
||||
private final boolean supportsDataDefinitionInTransaction;
|
||||
private final boolean doesDataDefinitionCauseTransactionCommit;
|
||||
private final Set<String> extraKeywords;
|
||||
private final SQLStateType sqlStateType;
|
||||
private final boolean lobLocatorUpdateCopy;
|
||||
private final String connectionSchemaName;
|
||||
private final String connectionCatalogName;
|
||||
private final LinkedHashSet<TypeInfo> typeInfoSet;
|
||||
|
||||
private ExtractedDatabaseMetaDataImpl(
|
||||
boolean supportsScrollableResults,
|
||||
boolean supportsGetGeneratedKeys,
|
||||
boolean supportsBatchUpdates,
|
||||
boolean supportsDataDefinitionInTransaction,
|
||||
boolean doesDataDefinitionCauseTransactionCommit,
|
||||
Set<String> extraKeywords,
|
||||
SQLStateType sqlStateType,
|
||||
boolean lobLocatorUpdateCopy,
|
||||
String connectionSchemaName,
|
||||
String connectionCatalogName,
|
||||
LinkedHashSet<TypeInfo> typeInfoSet) {
|
||||
this.supportsScrollableResults = supportsScrollableResults;
|
||||
this.supportsGetGeneratedKeys = supportsGetGeneratedKeys;
|
||||
this.supportsBatchUpdates = supportsBatchUpdates;
|
||||
this.supportsDataDefinitionInTransaction = supportsDataDefinitionInTransaction;
|
||||
this.doesDataDefinitionCauseTransactionCommit = doesDataDefinitionCauseTransactionCommit;
|
||||
this.extraKeywords = extraKeywords;
|
||||
this.sqlStateType = sqlStateType;
|
||||
this.lobLocatorUpdateCopy = lobLocatorUpdateCopy;
|
||||
this.connectionSchemaName = connectionSchemaName;
|
||||
this.connectionCatalogName = connectionCatalogName;
|
||||
this.typeInfoSet = typeInfoSet;
|
||||
}
|
||||
|
||||
public boolean supportsScrollableResults() {
|
||||
return supportsScrollableResults;
|
||||
}
|
||||
|
||||
public boolean supportsGetGeneratedKeys() {
|
||||
return supportsGetGeneratedKeys;
|
||||
}
|
||||
|
||||
public boolean supportsBatchUpdates() {
|
||||
return supportsBatchUpdates;
|
||||
}
|
||||
|
||||
public boolean supportsDataDefinitionInTransaction() {
|
||||
return supportsDataDefinitionInTransaction;
|
||||
}
|
||||
|
||||
public boolean doesDataDefinitionCauseTransactionCommit() {
|
||||
return doesDataDefinitionCauseTransactionCommit;
|
||||
}
|
||||
|
||||
public Set<String> getExtraKeywords() {
|
||||
return extraKeywords;
|
||||
}
|
||||
|
||||
public SQLStateType getSqlStateType() {
|
||||
return sqlStateType;
|
||||
}
|
||||
|
||||
public boolean doesLobLocatorUpdateCopy() {
|
||||
return lobLocatorUpdateCopy;
|
||||
}
|
||||
|
||||
public String getConnectionSchemaName() {
|
||||
return connectionSchemaName;
|
||||
}
|
||||
|
||||
public String getConnectionCatalogName() {
|
||||
return connectionCatalogName;
|
||||
}
|
||||
|
||||
public LinkedHashSet<TypeInfo> getTypeInfoSet() {
|
||||
return typeInfoSet;
|
||||
}
|
||||
}
|
||||
|
||||
public ConnectionProvider getConnectionProvider() {
|
||||
return connectionProvider;
|
||||
}
|
||||
|
||||
public SQLStatementLogger getSqlStatementLogger() {
|
||||
return sqlStatementLogger;
|
||||
}
|
||||
|
||||
public SQLExceptionHelper getSqlExceptionHelper() {
|
||||
return sqlExceptionHelper;
|
||||
}
|
||||
|
||||
public Dialect getDialect() {
|
||||
return dialect;
|
||||
}
|
||||
|
||||
public ExtractedDatabaseMetaData getExtractedMetaDataSupport() {
|
||||
return extractedMetaDataSupport;
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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.service.jdbc.internal;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.service.jdbc.spi.JdbcServices;
|
||||
import org.hibernate.service.spi.ServicesRegistry;
|
||||
import org.hibernate.service.spi.ServiceInitiator;
|
||||
|
||||
/**
|
||||
* Standard initiator for the standard {@link JdbcServices} service
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class JdbcServicesInitiator implements ServiceInitiator<JdbcServices> {
|
||||
public static final JdbcServicesInitiator INSTANCE = new JdbcServicesInitiator();
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Class<JdbcServices> getServiceInitiated() {
|
||||
return JdbcServices.class;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public JdbcServices initiateService(Map configValues, ServicesRegistry registry) {
|
||||
return new JdbcServicesImpl();
|
||||
}
|
||||
}
|
@ -0,0 +1,250 @@
|
||||
/*
|
||||
* 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.service.jdbc.internal;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.hibernate.ConnectionReleaseMode;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.JDBCException;
|
||||
import org.hibernate.service.jdbc.spi.JdbcResourceRegistry;
|
||||
import org.hibernate.service.jdbc.spi.JdbcServices;
|
||||
import org.hibernate.service.jdbc.spi.ConnectionObserver;
|
||||
import org.hibernate.service.jdbc.spi.LogicalConnectionImplementor;
|
||||
|
||||
/**
|
||||
* LogicalConnectionImpl implementation
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class LogicalConnectionImpl implements LogicalConnectionImplementor {
|
||||
private static final Logger log = LoggerFactory.getLogger( LogicalConnectionImpl.class );
|
||||
|
||||
private transient Connection physicalConnection;
|
||||
private final ConnectionReleaseMode connectionReleaseMode;
|
||||
private final JdbcServices jdbcServices;
|
||||
private final JdbcResourceRegistry jdbcResourceRegistry;
|
||||
private final List<ConnectionObserver> observers = new ArrayList<ConnectionObserver>();
|
||||
private boolean releasesEnabled = true;
|
||||
|
||||
private final boolean isUserSuppliedConnection;
|
||||
private boolean isClosed;
|
||||
|
||||
public LogicalConnectionImpl(
|
||||
Connection userSuppliedConnection,
|
||||
ConnectionReleaseMode connectionReleaseMode,
|
||||
JdbcServices jdbcServices) {
|
||||
if ( connectionReleaseMode == ConnectionReleaseMode.AFTER_STATEMENT &&
|
||||
! jdbcServices.getConnectionProvider().supportsAggressiveRelease() ) {
|
||||
log.debug( "connection provider reports to not support aggressive release; overriding" );
|
||||
connectionReleaseMode = ConnectionReleaseMode.AFTER_TRANSACTION;
|
||||
}
|
||||
this.physicalConnection = userSuppliedConnection;
|
||||
this.connectionReleaseMode = connectionReleaseMode;
|
||||
this.jdbcServices = jdbcServices;
|
||||
this.jdbcResourceRegistry = new JdbcResourceRegistryImpl( jdbcServices.getSqlExceptionHelper() );
|
||||
|
||||
this.isUserSuppliedConnection = ( userSuppliedConnection != null );
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public JdbcServices getJdbcServices() {
|
||||
return jdbcServices;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public JdbcResourceRegistry getResourceRegistry() {
|
||||
return jdbcResourceRegistry;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void addObserver(ConnectionObserver observer) {
|
||||
observers.add( observer );
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public boolean isOpen() {
|
||||
return !isClosed;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public boolean isPhysicallyConnected() {
|
||||
return physicalConnection != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Connection close() {
|
||||
log.trace( "closing logical connection" );
|
||||
Connection c = physicalConnection;
|
||||
if ( !isUserSuppliedConnection && physicalConnection != null ) {
|
||||
jdbcResourceRegistry.close();
|
||||
releaseConnection();
|
||||
}
|
||||
// not matter what
|
||||
physicalConnection = null;
|
||||
isClosed = true;
|
||||
for ( ConnectionObserver observer : observers ) {
|
||||
observer.logicalConnectionClosed();
|
||||
}
|
||||
log.trace( "logical connection closed" );
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public ConnectionReleaseMode getConnectionReleaseMode() {
|
||||
return connectionReleaseMode;
|
||||
}
|
||||
|
||||
public void afterStatementExecution() {
|
||||
log.trace( "starting after statement execution processing [{}]", connectionReleaseMode );
|
||||
if ( connectionReleaseMode == ConnectionReleaseMode.AFTER_STATEMENT ) {
|
||||
if ( ! releasesEnabled ) {
|
||||
log.debug( "skipping aggressive release due to manual disabling" );
|
||||
return;
|
||||
}
|
||||
if ( jdbcResourceRegistry.hasRegisteredResources() ) {
|
||||
log.debug( "skipping aggressive release due to registered resources" );
|
||||
return;
|
||||
}
|
||||
releaseConnection();
|
||||
}
|
||||
}
|
||||
|
||||
public void afterTransaction() {
|
||||
if ( connectionReleaseMode == ConnectionReleaseMode.AFTER_STATEMENT ||
|
||||
connectionReleaseMode == ConnectionReleaseMode.AFTER_TRANSACTION ) {
|
||||
if ( jdbcResourceRegistry.hasRegisteredResources() ) {
|
||||
log.info( "forcing container resource cleanup on transaction completion" );
|
||||
jdbcResourceRegistry.releaseResources();
|
||||
}
|
||||
aggressiveRelease();
|
||||
}
|
||||
}
|
||||
|
||||
public void disableReleases() {
|
||||
log.trace( "disabling releases" );
|
||||
releasesEnabled = false;
|
||||
}
|
||||
|
||||
public void enableReleases() {
|
||||
log.trace( "(re)enabling releases" );
|
||||
releasesEnabled = true;
|
||||
afterStatementExecution();
|
||||
}
|
||||
|
||||
/**
|
||||
* Force aggresive release of the underlying connection.
|
||||
*/
|
||||
public void aggressiveRelease() {
|
||||
if ( isUserSuppliedConnection ) {
|
||||
log.debug( "cannot aggressively release user-supplied connection; skipping" );
|
||||
}
|
||||
else {
|
||||
log.debug( "aggressively releasing JDBC connection" );
|
||||
if ( physicalConnection != null ) {
|
||||
releaseConnection();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Pysically opens a JDBC Connection.
|
||||
*
|
||||
* @throws org.hibernate.JDBCException Indicates problem opening a connection
|
||||
*/
|
||||
private void obtainConnection() throws JDBCException {
|
||||
log.debug( "obtaining JDBC connection" );
|
||||
try {
|
||||
physicalConnection = getJdbcServices().getConnectionProvider().getConnection();
|
||||
for ( ConnectionObserver observer : observers ) {
|
||||
observer.physicalConnectionObtained( physicalConnection );
|
||||
}
|
||||
log.debug( "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.debug( "releasing JDBC connection" );
|
||||
try {
|
||||
if ( !physicalConnection.isClosed() ) {
|
||||
getJdbcServices().getSqlExceptionHelper().logAndClearWarnings( physicalConnection );
|
||||
}
|
||||
for ( ConnectionObserver observer : observers ) {
|
||||
observer.physicalConnectionReleased();
|
||||
}
|
||||
getJdbcServices().getConnectionProvider().closeConnection( physicalConnection );
|
||||
physicalConnection = null;
|
||||
log.debug( "released JDBC connection" );
|
||||
}
|
||||
catch (SQLException sqle) {
|
||||
throw getJdbcServices().getSqlExceptionHelper().convert( sqle, "Could not close connection" );
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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.service.jdbc.spi;
|
||||
|
||||
import java.sql.Connection;
|
||||
|
||||
/**
|
||||
* An observer of logical connection events.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface ConnectionObserver {
|
||||
/**
|
||||
* A physical connection was obtained.
|
||||
*
|
||||
* @param connection The physical connection just obtained.
|
||||
*/
|
||||
public void physicalConnectionObtained(Connection connection);
|
||||
|
||||
/**
|
||||
* A physical connection was released.
|
||||
*/
|
||||
public void physicalConnectionReleased();
|
||||
|
||||
/**
|
||||
* The logical connection was closed.
|
||||
*/
|
||||
public void logicalConnectionClosed();
|
||||
}
|
@ -0,0 +1,133 @@
|
||||
/*
|
||||
* 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.service.jdbc.spi;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.internal.util.jdbc.TypeInfo;
|
||||
|
||||
/**
|
||||
* Information extracted from {@link java.sql.DatabaseMetaData} regarding what the JDBC driver reports as
|
||||
* being supported or not. Obviously {@link java.sql.DatabaseMetaData} reports many things, these are a few in
|
||||
* which we have particular interest.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface ExtractedDatabaseMetaData {
|
||||
|
||||
public enum SQLStateType {
|
||||
XOpen,
|
||||
SQL99,
|
||||
UNKOWN
|
||||
}
|
||||
|
||||
/**
|
||||
* Did the driver report to supporting scrollable result sets?
|
||||
*
|
||||
* @return True if the driver reported to support {@link java.sql.ResultSet#TYPE_SCROLL_INSENSITIVE}.
|
||||
* @see java.sql.DatabaseMetaData#supportsResultSetType
|
||||
*/
|
||||
public boolean supportsScrollableResults();
|
||||
|
||||
/**
|
||||
* Did the driver report to supporting retrieval of generated keys?
|
||||
*
|
||||
* @return True if the if the driver reported to support calls to {@link java.sql.Statement#getGeneratedKeys}
|
||||
* @see java.sql.DatabaseMetaData#supportsGetGeneratedKeys
|
||||
*/
|
||||
public boolean supportsGetGeneratedKeys();
|
||||
|
||||
/**
|
||||
* Did the driver report to supporting batched updates?
|
||||
*
|
||||
* @return True if the driver supports batched updates
|
||||
* @see java.sql.DatabaseMetaData#supportsBatchUpdates
|
||||
*/
|
||||
public boolean supportsBatchUpdates();
|
||||
|
||||
/**
|
||||
* Did the driver report to support performing DDL within transactions?
|
||||
*
|
||||
* @return True if the drivers supports DDL statements within transactions.
|
||||
* @see java.sql.DatabaseMetaData#dataDefinitionIgnoredInTransactions
|
||||
*/
|
||||
public boolean supportsDataDefinitionInTransaction();
|
||||
|
||||
/**
|
||||
* Did the driver report to DDL statements performed within a transaction performing an implicit commit of the
|
||||
* transaction.
|
||||
*
|
||||
* @return True if the driver/database performs an implicit commit of transaction when DDL statement is
|
||||
* performed
|
||||
* @see java.sql.DatabaseMetaData#dataDefinitionCausesTransactionCommit()
|
||||
*/
|
||||
public boolean doesDataDefinitionCauseTransactionCommit();
|
||||
|
||||
/**
|
||||
* Get the list of extra keywords (beyond standard SQL92 keywords) reported by the driver.
|
||||
*
|
||||
* @return The extra keywords used by this database.
|
||||
* @see java.sql.DatabaseMetaData#getSQLKeywords()
|
||||
*/
|
||||
public Set<String> getExtraKeywords();
|
||||
|
||||
/**
|
||||
* Retrieve the type of codes the driver says it uses for {@code SQLState}. They might follow either
|
||||
* the X/Open standard or the SQL92 standard.
|
||||
*
|
||||
* @return The SQLState strategy reportedly used by this driver/database.
|
||||
* @see java.sql.DatabaseMetaData#getSQLStateType()
|
||||
*/
|
||||
public SQLStateType getSqlStateType();
|
||||
|
||||
/**
|
||||
* Did the driver report that updates to a LOB locator affect a copy of the LOB?
|
||||
*
|
||||
* @return True if updates to the state of a LOB locator update only a copy.
|
||||
* @see java.sql.DatabaseMetaData#locatorsUpdateCopy()
|
||||
*/
|
||||
public boolean doesLobLocatorUpdateCopy();
|
||||
|
||||
/**
|
||||
* Retrieve the name of the schema in effect when we connected to the database.
|
||||
*
|
||||
* @return The schema name
|
||||
*/
|
||||
public String getConnectionSchemaName();
|
||||
|
||||
/**
|
||||
* Retrieve the name of the catalog in effect when we connected to the database.
|
||||
*
|
||||
* @return The catalog name
|
||||
*/
|
||||
public String getConnectionCatalogName();
|
||||
|
||||
/**
|
||||
* Set of type info reported by the driver.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public LinkedHashSet<TypeInfo> getTypeInfoSet();
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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.service.jdbc.spi;
|
||||
|
||||
/**
|
||||
* Specialized {@link JdbcWrapper} contract for wrapped objects that can additioanlly be invalidated
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface InvalidatableWrapper<T> extends JdbcWrapper<T> {
|
||||
/**
|
||||
* Make the wrapper invalid for further usage.
|
||||
*/
|
||||
public void invalidate();
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* 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.service.jdbc.spi;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.Statement;
|
||||
|
||||
/**
|
||||
* Defines a registry of JDBC resources related to a particular unit of work.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface JdbcResourceRegistry {
|
||||
/**
|
||||
* Register a JDBC statement.
|
||||
*
|
||||
* @param statement The statement to register.
|
||||
*/
|
||||
public void register(Statement statement);
|
||||
|
||||
/**
|
||||
* Release a previously registered statement.
|
||||
*
|
||||
* @param statement The statement to release.
|
||||
*/
|
||||
public void release(Statement statement);
|
||||
|
||||
/**
|
||||
* Register a JDBC result set.
|
||||
*
|
||||
* @param resultSet The result set to register.
|
||||
*/
|
||||
public void register(ResultSet resultSet);
|
||||
|
||||
/**
|
||||
* Release a previously registered result set.
|
||||
*
|
||||
* @param resultSet The result set to release.
|
||||
*/
|
||||
public void release(ResultSet resultSet);
|
||||
|
||||
/**
|
||||
* Does this registry currently have any registered resources?
|
||||
*
|
||||
* @return True if the registry does have registered resources; false otherwise.
|
||||
*/
|
||||
public boolean hasRegisteredResources();
|
||||
|
||||
/**
|
||||
* Release all registered resources.
|
||||
*/
|
||||
public void releaseResources();
|
||||
|
||||
/**
|
||||
* Close this registry. Also {@link #releaseResources releases} any registered resources.
|
||||
* <p/>
|
||||
* After execution, the registry is considered unusable.
|
||||
*/
|
||||
public void close();
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 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.service.jdbc.spi;
|
||||
|
||||
import java.sql.Connection;
|
||||
|
||||
import org.hibernate.ConnectionReleaseMode;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
|
||||
import org.hibernate.service.spi.Service;
|
||||
|
||||
/**
|
||||
* Contract for services around JDBC operations. These represent shared resources, aka not varied by session/use.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface JdbcServices extends Service {
|
||||
/**
|
||||
* Obtain service for providing JDBC connections.
|
||||
*
|
||||
* @return The connection provider.
|
||||
*/
|
||||
public ConnectionProvider getConnectionProvider();
|
||||
|
||||
/**
|
||||
* Obtain the dialect of the database to which {@link Connection connections} from
|
||||
* {@link #getConnectionProvider()} point.
|
||||
*
|
||||
* @return The database dialect.
|
||||
*/
|
||||
public Dialect getDialect();
|
||||
|
||||
/**
|
||||
* Obtain service for logging SQL statements.
|
||||
*
|
||||
* @return The SQL statement logger.
|
||||
*/
|
||||
public SQLStatementLogger getSqlStatementLogger();
|
||||
|
||||
/**
|
||||
* Obtain service for dealing with exceptions.
|
||||
*
|
||||
* @return The exception helper service.
|
||||
*/
|
||||
public SQLExceptionHelper getSqlExceptionHelper();
|
||||
|
||||
/**
|
||||
* Obtain infomration about supported behavior reported by the JDBC driver.
|
||||
* <p/>
|
||||
* Yuck, yuck, yuck! Much prefer this to be part of a "basic settings" type object. See discussion
|
||||
* on {@link org.hibernate.cfg.internal.JdbcServicesBuilder}
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public ExtractedDatabaseMetaData getExtractedMetaDataSupport();
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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.service.jdbc.spi;
|
||||
|
||||
/**
|
||||
* Generic contract for wrapped JDBC objects.
|
||||
*
|
||||
* @param <T> One of either {@link java.sql.Connection}, {@link java.sql.Statement} or {@link java.sql.ResultSet}
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface JdbcWrapper<T> {
|
||||
/**
|
||||
* Retrieve the wrapped JDBC object.
|
||||
*
|
||||
* @return The wrapped object
|
||||
*/
|
||||
public T getWrappedObject();
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* 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.service.jdbc.spi;
|
||||
|
||||
import java.sql.Connection;
|
||||
|
||||
/**
|
||||
* LogicalConnection contract
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface LogicalConnection {
|
||||
/**
|
||||
* Is this logical connection open? Another phraseology sometimes used is: "are we
|
||||
* logically connected"?
|
||||
*
|
||||
* @return True if logically connected; false otherwise.
|
||||
*/
|
||||
public boolean isOpen();
|
||||
|
||||
/**
|
||||
* Is this logical connection instance "physically" connected. Meaning
|
||||
* do we currently internally have a cached connection.
|
||||
*
|
||||
* @return True if physically connected; false otherwise.
|
||||
*/
|
||||
public boolean isPhysicallyConnected();
|
||||
|
||||
/**
|
||||
* Retrieves the connection currently "logically" managed by this LogicalConnectionImpl.
|
||||
* <p/>
|
||||
* Note, that we may need to obtain a connection to return here if a
|
||||
* connection has either not yet been obtained (non-UserSuppliedConnectionProvider)
|
||||
* or has previously been aggressively released.
|
||||
*
|
||||
* @return The current Connection.
|
||||
*/
|
||||
public Connection getConnection();
|
||||
|
||||
/**
|
||||
* Release the underlying connection and clean up any other resources associated
|
||||
* with this logical connection.
|
||||
* <p/>
|
||||
* This leaves the logical connection in a "no longer useable" state.
|
||||
*
|
||||
* @return The physical connection which was being used.
|
||||
*/
|
||||
public Connection close();
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* 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.service.jdbc.spi;
|
||||
|
||||
import org.hibernate.ConnectionReleaseMode;
|
||||
|
||||
/**
|
||||
* The "internal" contract for LogicalConnection
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface LogicalConnectionImplementor extends LogicalConnection {
|
||||
/**
|
||||
* Obtains the JDBC services associated with this logical connection.
|
||||
*
|
||||
* @return JDBC services
|
||||
*/
|
||||
public JdbcServices getJdbcServices();
|
||||
|
||||
/**
|
||||
* Obtains the JDBC resource registry associated with this logical connection.
|
||||
*
|
||||
* @return The JDBC resource registry.
|
||||
*/
|
||||
public JdbcResourceRegistry getResourceRegistry();
|
||||
|
||||
/**
|
||||
* Add an observer interested in notification of connection events.
|
||||
*
|
||||
* @param observer The observer.
|
||||
*/
|
||||
public void addObserver(ConnectionObserver observer);
|
||||
|
||||
/**
|
||||
* The release mode under which this logical connection is operating.
|
||||
*
|
||||
* @return the release mode.
|
||||
*/
|
||||
public ConnectionReleaseMode getConnectionReleaseMode();
|
||||
|
||||
/**
|
||||
* Used to signify that a statement has completed execution which may
|
||||
* indicate that this logical connection need to perform an
|
||||
* aggressive release of its physical connection.
|
||||
*/
|
||||
public void afterStatementExecution();
|
||||
|
||||
/**
|
||||
* Used to signify that a transaction has completed which may indicate
|
||||
* that this logical connection need to perform an aggressive release
|
||||
* of its physical connection.
|
||||
*/
|
||||
public void afterTransaction();
|
||||
|
||||
/**
|
||||
* Manually (and temporarily) circumvent aggressive release processing.
|
||||
*/
|
||||
public void disableReleases();
|
||||
|
||||
/**
|
||||
* Re-enable aggressive release processing (after a prior {@link #disableReleases()} call.
|
||||
*/
|
||||
public void enableReleases();
|
||||
}
|
@ -0,0 +1,212 @@
|
||||
/*
|
||||
* 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.service.jdbc.spi;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.SQLWarning;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.hibernate.JDBCException;
|
||||
import org.hibernate.exception.SQLExceptionConverter;
|
||||
import org.hibernate.exception.SQLStateConverter;
|
||||
import org.hibernate.exception.ViolatedConstraintNameExtracter;
|
||||
import org.hibernate.util.StringHelper;
|
||||
|
||||
/**
|
||||
* Helper for handling SQLExceptions in various manners.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SQLExceptionHelper {
|
||||
private static final Logger log = LoggerFactory.getLogger( SQLExceptionHelper.class );
|
||||
|
||||
public static final String DEFAULT_EXCEPTION_MSG = "SQL Exception";
|
||||
public static final String DEFAULT_WARNING_MSG = "SQL Warning";
|
||||
|
||||
public static final SQLExceptionConverter DEFAULT_CONVERTER = new SQLStateConverter(
|
||||
new ViolatedConstraintNameExtracter() {
|
||||
public String extractConstraintName(SQLException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
private SQLExceptionConverter sqlExceptionConverter;
|
||||
|
||||
/**
|
||||
* Create an exception helper with a default exception converter.
|
||||
*/
|
||||
public SQLExceptionHelper() {
|
||||
sqlExceptionConverter = DEFAULT_CONVERTER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an exception helper with a specific exception converter.
|
||||
*
|
||||
* @param sqlExceptionConverter The exception converter to use.
|
||||
*/
|
||||
public SQLExceptionHelper(SQLExceptionConverter sqlExceptionConverter) {
|
||||
this.sqlExceptionConverter = sqlExceptionConverter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Access the current exception converter being used internally.
|
||||
*
|
||||
* @return The current exception converter.
|
||||
*/
|
||||
public SQLExceptionConverter getSqlExceptionConverter() {
|
||||
return sqlExceptionConverter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inject the exception converter to use.
|
||||
* <p/>
|
||||
* NOTE : <tt>null</tt> is allowed and signifies to use the default.
|
||||
*
|
||||
* @param sqlExceptionConverter The converter to use.
|
||||
*/
|
||||
public void setSqlExceptionConverter(SQLExceptionConverter sqlExceptionConverter) {
|
||||
this.sqlExceptionConverter = ( sqlExceptionConverter == null ? DEFAULT_CONVERTER : sqlExceptionConverter );
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an SQLException using the current converter, doing some logging first.
|
||||
*
|
||||
* @param sqle The exception to convert
|
||||
* @param message An error message.
|
||||
* @return The converted exception
|
||||
*/
|
||||
public JDBCException convert(SQLException sqle, String message) {
|
||||
return convert( sqle, message, "n/a" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an SQLException using the current converter, doing some logging first.
|
||||
*
|
||||
* @param sqle The exception to convert
|
||||
* @param message An error message.
|
||||
* @param sql The SQL being executed when the exception occurred
|
||||
* @return The converted exception
|
||||
*/
|
||||
public JDBCException convert(SQLException sqle, String message, String sql) {
|
||||
logExceptions( sqle, message + " [" + sql + "]" );
|
||||
return sqlExceptionConverter.convert( sqle, message, sql );
|
||||
}
|
||||
|
||||
/**
|
||||
* Log any {@link java.sql.SQLWarning}s registered with the connection.
|
||||
*
|
||||
* @param connection The connection to check for warnings.
|
||||
*/
|
||||
public void logAndClearWarnings(Connection connection) {
|
||||
if ( log.isWarnEnabled() ) {
|
||||
try {
|
||||
logWarnings( connection.getWarnings() );
|
||||
}
|
||||
catch ( SQLException sqle ) {
|
||||
//workaround for WebLogic
|
||||
log.debug( "could not log warnings", sqle );
|
||||
}
|
||||
}
|
||||
try {
|
||||
//Sybase fail if we don't do that, sigh...
|
||||
connection.clearWarnings();
|
||||
}
|
||||
catch ( SQLException sqle ) {
|
||||
log.debug( "could not clear warnings", sqle );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the given (and any nested) warning.
|
||||
*
|
||||
* @param warning The warning
|
||||
*/
|
||||
public void logWarnings(SQLWarning warning) {
|
||||
logWarnings( warning, null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the given (and any nested) warning.
|
||||
*
|
||||
* @param warning The warning
|
||||
* @param message The message text to use as a preamble.
|
||||
*/
|
||||
public void logWarnings(SQLWarning warning, String message) {
|
||||
if ( log.isWarnEnabled() ) {
|
||||
if ( log.isDebugEnabled() && warning != null ) {
|
||||
message = StringHelper.isNotEmpty( message ) ? message : DEFAULT_WARNING_MSG;
|
||||
log.debug( message, warning );
|
||||
}
|
||||
while ( warning != null ) {
|
||||
StringBuffer buf = new StringBuffer( 30 )
|
||||
.append( "SQL Warning: " )
|
||||
.append( warning.getErrorCode() )
|
||||
.append( ", SQLState: " )
|
||||
.append( warning.getSQLState() );
|
||||
log.warn( buf.toString() );
|
||||
log.warn( warning.getMessage() );
|
||||
warning = warning.getNextWarning();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the given (and any nested) exception.
|
||||
*
|
||||
* @param sqlException The exception to log
|
||||
*/
|
||||
public void logExceptions(SQLException sqlException) {
|
||||
logExceptions( sqlException, null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the given (and any nested) exception.
|
||||
*
|
||||
* @param sqlException The exception to log
|
||||
* @param message The message text to use as a preamble.
|
||||
*/
|
||||
public void logExceptions(SQLException sqlException, String message) {
|
||||
if ( log.isErrorEnabled() ) {
|
||||
if ( log.isDebugEnabled() ) {
|
||||
message = StringHelper.isNotEmpty( message ) ? message : DEFAULT_EXCEPTION_MSG;
|
||||
log.debug( message, sqlException );
|
||||
}
|
||||
while ( sqlException != null ) {
|
||||
StringBuffer buf = new StringBuffer( 30 )
|
||||
.append( "SQL Error: " )
|
||||
.append( sqlException.getErrorCode() )
|
||||
.append( ", SQLState: " )
|
||||
.append( sqlException.getSQLState() );
|
||||
log.warn( buf.toString() );
|
||||
log.error( sqlException.getMessage() );
|
||||
sqlException = sqlException.getNextException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* 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.service.jdbc.spi;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.hibernate.jdbc.util.FormatStyle;
|
||||
|
||||
/**
|
||||
* Centralize logging for SQL statements.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SQLStatementLogger {
|
||||
private static final Logger log = LoggerFactory.getLogger( SQLStatementLogger.class );
|
||||
|
||||
private boolean logToStdout;
|
||||
private boolean format;
|
||||
|
||||
/**
|
||||
* Constructs a new SQLStatementLogger instance.
|
||||
*/
|
||||
public SQLStatementLogger() {
|
||||
this( false, false );
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new SQLStatementLogger instance.
|
||||
*
|
||||
* @param logToStdout Should we log to STDOUT in addition to our internal logger.
|
||||
* @param format Should we format the statements prior to logging
|
||||
*/
|
||||
public SQLStatementLogger(boolean logToStdout, boolean format) {
|
||||
this.logToStdout = logToStdout;
|
||||
this.format = format;
|
||||
}
|
||||
|
||||
/**
|
||||
* Are we currently logging to stdout?
|
||||
*
|
||||
* @return True if we are currently logging to stdout; false otherwise.
|
||||
*/
|
||||
public boolean isLogToStdout() {
|
||||
return logToStdout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable (true) or disable (false) logging to stdout.
|
||||
*
|
||||
* @param logToStdout True to enable logging to stdout; false to disable.
|
||||
*/
|
||||
public void setLogToStdout(boolean logToStdout) {
|
||||
this.logToStdout = logToStdout;
|
||||
}
|
||||
|
||||
public boolean isFormat() {
|
||||
return format;
|
||||
}
|
||||
|
||||
public void setFormat(boolean format) {
|
||||
this.format = format;
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a SQL statement string.
|
||||
*
|
||||
* @param statement The SQL statement.
|
||||
*/
|
||||
public void logStatement(String statement) {
|
||||
// for now just assume a DML log for formatting
|
||||
if ( format ) {
|
||||
if ( logToStdout || log.isDebugEnabled() ) {
|
||||
statement = FormatStyle.BASIC.getFormatter().format( statement );
|
||||
}
|
||||
}
|
||||
log.debug( statement );
|
||||
if ( logToStdout ) {
|
||||
System.out.println( "Hibernate: " + statement );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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.service.jdbc.spi;
|
||||
|
||||
import java.sql.Connection;
|
||||
|
||||
/**
|
||||
* Contract for resolving the schema of a {@link Connection}.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface SchemaNameResolver {
|
||||
/**
|
||||
* Given a JDBC {@link Connection}, resolve the name of the schema (if one) to which it connects.
|
||||
*
|
||||
* @param connection The JDBC connection
|
||||
*
|
||||
* @return The name of the schema (may be null).
|
||||
*/
|
||||
public String resolveSchemaName(Connection connection);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user