All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.skife.jdbi.v2.BasicHandle Maven / Gradle / Ivy

Go to download

jDBI is designed to provide convenient tabular data access in Java(tm). It uses the Java collections framework for query results, provides a convenient means of externalizing sql statements, and provides named parameter support for any database being used.

There is a newer version: 2.78
Show newest version
/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.skife.jdbi.v2;

import org.skife.jdbi.v2.exceptions.UnableToCloseResourceException;
import org.skife.jdbi.v2.exceptions.UnableToManipulateTransactionIsolationLevelException;
import org.skife.jdbi.v2.sqlobject.SqlObjectBuilder;
import org.skife.jdbi.v2.tweak.ArgumentFactory;
import org.skife.jdbi.v2.tweak.ContainerFactory;
import org.skife.jdbi.v2.tweak.ResultColumnMapper;
import org.skife.jdbi.v2.tweak.ResultSetMapper;
import org.skife.jdbi.v2.tweak.SQLLog;
import org.skife.jdbi.v2.tweak.StatementBuilder;
import org.skife.jdbi.v2.tweak.StatementCustomizer;
import org.skife.jdbi.v2.tweak.StatementLocator;
import org.skife.jdbi.v2.tweak.StatementRewriter;
import org.skife.jdbi.v2.tweak.TransactionHandler;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

class BasicHandle implements Handle
{

    private StatementRewriter statementRewriter;
    private StatementLocator  statementLocator;
    private SQLLog            log;
    private TimingCollector   timingCollector;
    private StatementBuilder  statementBuilder;

    private boolean closed = false;

    private final Map      globalStatementAttributes;
    private final MappingRegistry          mappingRegistry;
    private final ContainerFactoryRegistry containerFactoryRegistry;
    private final Foreman                  foreman;
    private final TransactionHandler       transactions;
    private final Connection               connection;


    BasicHandle(TransactionHandler transactions,
                StatementLocator statementLocator,
                StatementBuilder preparedStatementCache,
                StatementRewriter statementRewriter,
                Connection connection,
                Map globalStatementAttributes,
                SQLLog log,
                TimingCollector timingCollector,
                MappingRegistry mappingRegistry,
                Foreman foreman,
                ContainerFactoryRegistry containerFactoryRegistry)
    {
        this.statementBuilder = preparedStatementCache;
        this.statementRewriter = statementRewriter;
        this.transactions = transactions;
        this.connection = connection;
        this.statementLocator = statementLocator;
        this.log = log;
        this.timingCollector = timingCollector;
        this.mappingRegistry = mappingRegistry;
        this.foreman = foreman;
        this.globalStatementAttributes = new HashMap();
        this.globalStatementAttributes.putAll(globalStatementAttributes);
        this.containerFactoryRegistry = containerFactoryRegistry.createChild();
    }

    @Override
    public Query> createQuery(String sql)
    {
        MappingRegistry queryRegistry = new MappingRegistry(this.mappingRegistry);
        return new Query>(new Binding(),
                                              new DefaultMapper(),
                                              statementLocator,
                                              statementRewriter,
                                              this,
                                              statementBuilder,
                                              sql,
                                              new ConcreteStatementContext(globalStatementAttributes, queryRegistry),
                                              log,
                                              timingCollector,
                                              Collections.emptyList(),
                                              queryRegistry,
                                              foreman.createChild(),
                                              containerFactoryRegistry.createChild());
    }

    /**
     * Get the JDBC Connection this Handle uses
     *
     * @return the JDBC Connection this Handle uses
     */
    @Override
    public Connection getConnection()
    {
        return this.connection;
    }

    @Override
    public void close()
    {
        if (!closed) {
            try {
                statementBuilder.close(getConnection());
            } finally {
                try {
                    connection.close();
                }
                catch (SQLException e) {
                    throw new UnableToCloseResourceException("Unable to close Connection", e);
                }
                finally {
                    log.logReleaseHandle(this);
                    closed = true;
                }
            }
        }
    }

    boolean isClosed()
    {
        return closed;
    }

    @Override
    public void define(String key, Object value)
    {
        this.globalStatementAttributes.put(key, value);
    }

    /**
     * Start a transaction
     */
    @Override
    public Handle begin()
    {
        transactions.begin(this);
        log.logBeginTransaction(this);
        return this;
    }

    /**
     * Commit a transaction
     */
    @Override
    public Handle commit()
    {
        final long start = System.nanoTime();
        transactions.commit(this);
        log.logCommitTransaction((System.nanoTime() - start) / 1000000L, this);
        return this;
    }

    /**
     * Rollback a transaction
     */
    @Override
    public Handle rollback()
    {
        final long start = System.nanoTime();
        transactions.rollback(this);
        log.logRollbackTransaction((System.nanoTime() - start) / 1000000L, this);
        return this;
    }

    /**
     * Create a transaction checkpoint (savepoint in JDBC terminology) with the name provided.
     *
     * @param name The name of the checkpoint
     *
     * @return The same handle
     */
    @Override
    public Handle checkpoint(String name)
    {
        transactions.checkpoint(this, name);
        log.logCheckpointTransaction(this, name);
        return this;
    }

    /**
     * Release the named checkpoint, making rollback to it not possible.
     *
     * @return The same handle
     */
    @Override
    public Handle release(String checkpointName)
    {
        transactions.release(this, checkpointName);
        log.logReleaseCheckpointTransaction(this, checkpointName);
        return this;
    }

    @Override
    public void setStatementBuilder(StatementBuilder builder)
    {
        this.statementBuilder = builder;
    }

    @Override
    public void setSQLLog(SQLLog log)
    {
        this.log = log;
    }

    @Override
    public void setTimingCollector(final TimingCollector timingCollector)
    {
        if (timingCollector == null) {
            this.timingCollector = TimingCollector.NOP_TIMING_COLLECTOR;
        }
        else {
            this.timingCollector = timingCollector;
        }
    }


    /**
     * Rollback a transaction to a named checkpoint
     *
     * @param checkpointName the name of the checkpoint, previously declared with {@see Handle#checkpoint}
     */
    @Override
    public Handle rollback(String checkpointName)
    {
        final long start = System.nanoTime();
        transactions.rollback(this, checkpointName);
        log.logRollbackToCheckpoint((System.nanoTime() - start) / 1000000L, this, checkpointName);
        return this;
    }

    @Override
    public boolean isInTransaction()
    {
        return transactions.isInTransaction(this);
    }

    @Override
    public Update createStatement(String sql)
    {
        return new Update(this,
                          statementLocator,
                          statementRewriter,
                          statementBuilder,
                          sql,
                          new ConcreteStatementContext(globalStatementAttributes, new MappingRegistry(mappingRegistry)),
                          log,
                          timingCollector,
                          foreman,
                          containerFactoryRegistry);
    }

    @Override
    public Call createCall(String sql)
    {
        return new Call(this,
                        statementLocator,
                        statementRewriter,
                        statementBuilder,
                        sql,
                        new ConcreteStatementContext(globalStatementAttributes, new MappingRegistry(mappingRegistry)),
                        log,
                        timingCollector,
                        Collections.emptyList(),
                        foreman,
                        containerFactoryRegistry);
    }

    @Override
    public int insert(String sql, Object... args)
    {
        return update(sql, args);
    }

    @Override
    public int update(String sql, Object... args)
    {
        Update stmt = createStatement(sql);
        int position = 0;
        for (Object arg : args) {
            stmt.bind(position++, arg);
        }
        return stmt.execute();
    }

    @Override
    public PreparedBatch prepareBatch(String sql)
    {
        return new PreparedBatch(statementLocator,
                                 statementRewriter,
                                 this,
                                 statementBuilder,
                                 sql,
                                 new ConcreteStatementContext(globalStatementAttributes, new MappingRegistry(mappingRegistry)),
                                 log,
                                 timingCollector,
                                 Collections.emptyList(),
                                 foreman,
                                 containerFactoryRegistry);
    }

    @Override
    public Batch createBatch()
    {
        return new Batch(this.statementRewriter,
                         this.connection,
                         new ConcreteStatementContext(globalStatementAttributes, new MappingRegistry(mappingRegistry)),
                         log,
                         timingCollector,
                         foreman.createChild());
    }

    @Override
    public  ReturnType inTransaction(TransactionCallback callback)
    {
        return transactions.inTransaction(this, callback);
    }

    @Override
    public void useTransaction(final TransactionConsumer callback)
    {
        transactions.inTransaction(this, new VoidTransactionCallback() {
            @Override
            protected void execute(Handle handle, TransactionStatus status) throws Exception {
                callback.useTransaction(handle, status);
            }
        });
    }

    @Override
    public  ReturnType inTransaction(TransactionIsolationLevel level,
                                                 TransactionCallback callback)
    {
        final TransactionIsolationLevel initial = getTransactionIsolationLevel();
        boolean failed = true;
        try {
            setTransactionIsolation(level);

            ReturnType result = transactions.inTransaction(this, level, callback);
            failed = false;

            return result;
        }
        finally {
            try {
                setTransactionIsolation(initial);
            }
            catch (RuntimeException e) {
                if (! failed) {
                    throw e;
                }

                // Ignore, there was already an exceptional condition and we don't want to clobber it.
            }
        }
    }

    @Override
    public void useTransaction(TransactionIsolationLevel level, final TransactionConsumer callback)
    {
        inTransaction(level, new VoidTransactionCallback() {
            @Override
            protected void execute(Handle handle, TransactionStatus status) throws Exception {
                callback.useTransaction(handle, status);
            }
        });
    }

    @Override
    public List> select(String sql, Object... args)
    {
        Query> query = this.createQuery(sql);
        int position = 0;
        for (Object arg : args) {
            query.bind(position++, arg);
        }
        return query.list();
    }

    @Override
    public void setStatementLocator(StatementLocator locator)
    {
        this.statementLocator = locator;
    }

    @Override
    public void setStatementRewriter(StatementRewriter rewriter)
    {
        this.statementRewriter = rewriter;
    }

    @Override
    public Script createScript(String name)
    {
        return new Script(this, statementLocator, name, new ConcreteStatementContext(globalStatementAttributes, new MappingRegistry(mappingRegistry)));
    }

    @Override
    public void execute(String sql, Object... args)
    {
        this.update(sql, args);
    }

    @Override
    public void registerMapper(ResultSetMapper mapper)
    {
        mappingRegistry.addMapper(mapper);
    }

    @Override
    public void registerMapper(ResultSetMapperFactory factory)
    {
        mappingRegistry.addMapper(factory);
    }

    @Override
    public void registerColumnMapper(ResultColumnMapper mapper) {
        mappingRegistry.addColumnMapper(mapper);
    }

    @Override
    public void registerColumnMapper(ResultColumnMapperFactory factory) {
        mappingRegistry.addColumnMapper(factory);
    }

    @Override
    public  SqlObjectType attach(Class sqlObjectType)
    {
        return SqlObjectBuilder.attach(this, sqlObjectType);
    }

    @Override
    public void setTransactionIsolation(TransactionIsolationLevel level)
    {
        setTransactionIsolation(level.intValue());
    }

    @Override
    public void setTransactionIsolation(int level)
    {
        try {
            if (connection.getTransactionIsolation() == level) {
                // already set, noop
                return;
            }
            connection.setTransactionIsolation(level);
        }
        catch (SQLException e) {
            throw new UnableToManipulateTransactionIsolationLevelException(level, e);
        }
    }

    @Override
    public TransactionIsolationLevel getTransactionIsolationLevel()
    {
        try {
            return TransactionIsolationLevel.valueOf(connection.getTransactionIsolation());
        }
        catch (SQLException e) {
            throw new UnableToManipulateTransactionIsolationLevelException("unable to access current setting", e);
        }
    }

    @Override
    public void registerArgumentFactory(ArgumentFactory argumentFactory)
    {
        this.foreman.register(argumentFactory);
    }

    @Override
    public void registerContainerFactory(ContainerFactory factory)
    {
        this.containerFactoryRegistry.register(factory);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy