package net.bull.javamelody;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import org.hibernate.Interceptor;
import org.hibernate.ScrollMode;
import org.hibernate.cfg.Settings;
import org.hibernate.jdbc.Batcher;
import org.hibernate.jdbc.BatcherFactory;
import org.hibernate.jdbc.BatchingBatcher;
import org.hibernate.jdbc.ConnectionManager;
import org.hibernate.jdbc.NonBatchingBatcher;
/**
* Alternative pour monitorer les requêtes sql.
* Cette classe se configure avec la propriété hibernate "hibernate.jdbc.factory_class"
*
* Par exemple: hibernate.jdbc.factory_class=net.bull.javamelody.HibernateBatcherFactory
*
* @author Emeric Vernat
*/
public class HibernateBatcherFactory implements BatcherFactory {
private static class HibernateBatchingBatcher extends BatchingBatcher {
HibernateBatchingBatcher(ConnectionManager connectionManager, Interceptor interceptor) {
super(connectionManager, interceptor);
}
/** {@inheritDoc} */
@Override
public PreparedStatement prepareStatement(String sql) throws SQLException {
// super.prepareStatement utilisera prepareStatement(String, boolean)
// donc override a priori inutile mais on laisse createProxy vérifier
return createPreparedStatementProxy(sql, super.prepareStatement(sql));
}
/** {@inheritDoc} */
@Override
public PreparedStatement prepareBatchStatement(String sql) throws SQLException {
// prepareBatchStatement utilisera prepareStatement(String, boolean)
// donc override a priori inutile mais on laisse createProxy vérifier
return createPreparedStatementProxy(sql, super.prepareBatchStatement(sql));
}
/** {@inheritDoc} */
@Override
public PreparedStatement prepareStatement(String sql, boolean getGeneratedKeys)
throws SQLException {
return createPreparedStatementProxy(sql, super.prepareStatement(sql, getGeneratedKeys));
}
/** {@inheritDoc} */
@Override
public PreparedStatement prepareSelectStatement(String sql) throws SQLException {
return createPreparedStatementProxy(sql, super.prepareSelectStatement(sql));
}
/** {@inheritDoc} */
@Override
public PreparedStatement prepareStatement(String sql, String[] columnNames)
throws SQLException {
return createPreparedStatementProxy(sql, super.prepareStatement(sql, columnNames));
}
/** {@inheritDoc} */
@Override
public PreparedStatement prepareQueryStatement(String sql, boolean scrollable,
ScrollMode scrollMode) throws SQLException {
return createPreparedStatementProxy(sql,
super.prepareQueryStatement(sql, scrollable, scrollMode));
}
/** {@inheritDoc} */
@Override
public CallableStatement prepareCallableStatement(String sql) throws SQLException {
return createCallableStatementProxy(sql, super.prepareCallableStatement(sql));
}
/** {@inheritDoc} */
@Override
public CallableStatement prepareCallableQueryStatement(String sql, boolean scrollable,
ScrollMode scrollMode) throws SQLException {
return createCallableStatementProxy(sql,
super.prepareCallableQueryStatement(sql, scrollable, scrollMode));
}
/** {@inheritDoc} */
@Override
public CallableStatement prepareBatchCallableStatement(String sql) throws SQLException {
// prepareBatchCallableStatement utilisera prepareCallableStatement(String)
// donc override a priori inutile mais on laisse createProxy vérifier
return createCallableStatementProxy(sql, super.prepareBatchCallableStatement(sql));
}
}
private static class HibernateNonBatchingBatcher extends NonBatchingBatcher {
HibernateNonBatchingBatcher(ConnectionManager connectionManager, Interceptor interceptor) {
super(connectionManager, interceptor);
}
/** {@inheritDoc} */
@Override
public PreparedStatement prepareStatement(String sql) throws SQLException {
// super.prepareStatement utilisera prepareStatement(String, boolean)
// donc override a priori inutile mais on laisse createProxy vérifier
return createPreparedStatementProxy(sql, super.prepareStatement(sql));
}
/** {@inheritDoc} */
@Override
public PreparedStatement prepareBatchStatement(String sql) throws SQLException {
// prepareBatchStatement utilisera prepareStatement(String, boolean)
// donc override a priori inutile mais on laisse createProxy vérifier
return createPreparedStatementProxy(sql, super.prepareBatchStatement(sql));
}
/** {@inheritDoc} */
@Override
public PreparedStatement prepareSelectStatement(String sql) throws SQLException {
return createPreparedStatementProxy(sql, super.prepareSelectStatement(sql));
}
/** {@inheritDoc} */
@Override
public PreparedStatement prepareStatement(String sql, boolean getGeneratedKeys)
throws SQLException {
return createPreparedStatementProxy(sql, super.prepareStatement(sql, getGeneratedKeys));
}
/** {@inheritDoc} */
@Override
public PreparedStatement prepareStatement(String sql, String[] columnNames)
throws SQLException {
return createPreparedStatementProxy(sql, super.prepareStatement(sql, columnNames));
}
/** {@inheritDoc} */
@Override
public PreparedStatement prepareQueryStatement(String sql, boolean scrollable,
ScrollMode scrollMode) throws SQLException {
return createPreparedStatementProxy(sql,
super.prepareQueryStatement(sql, scrollable, scrollMode));
}
/** {@inheritDoc} */
@Override
public CallableStatement prepareBatchCallableStatement(String sql) throws SQLException {
// prepareBatchCallableStatement utilisera prepareCallableStatement(String)
// donc override a priori inutile mais on laisse createProxy vérifier
return createCallableStatementProxy(sql, super.prepareBatchCallableStatement(sql));
}
/** {@inheritDoc} */
@Override
public CallableStatement prepareCallableStatement(String sql) throws SQLException {
return createCallableStatementProxy(sql, super.prepareCallableStatement(sql));
}
/** {@inheritDoc} */
@Override
public CallableStatement prepareCallableQueryStatement(String sql, boolean scrollable,
ScrollMode scrollMode) throws SQLException {
return createCallableStatementProxy(sql,
super.prepareCallableQueryStatement(sql, scrollable, scrollMode));
}
}
static PreparedStatement createPreparedStatementProxy(String query, PreparedStatement statement) {
return (PreparedStatement) JdbcWrapper.SINGLETON.createStatementProxy(query, statement);
}
static CallableStatement createCallableStatementProxy(String query, CallableStatement statement) {
return (CallableStatement) JdbcWrapper.SINGLETON.createStatementProxy(query, statement);
}
/** {@inheritDoc} */
@Override
public Batcher createBatcher(ConnectionManager connectionManager, Interceptor interceptor) {
final boolean sqlMonitoringDisabled = JdbcWrapper.SINGLETON.isSqlMonitoringDisabled();
final Settings settings = connectionManager.getFactory().getSettings();
if (sqlMonitoringDisabled) {
if (settings.getJdbcBatchSize() == 0) {
return new NonBatchingBatcher(connectionManager, interceptor);
}
return new BatchingBatcher(connectionManager, interceptor);
}
final Batcher result;
if (settings.getJdbcBatchSize() == 0) {
result = new HibernateNonBatchingBatcher(connectionManager, interceptor);
} else {
result = new HibernateBatchingBatcher(connectionManager, interceptor);
}
LOG.debug("hibernate batcher factory initialized");
return result;
}
}