org.hibernate.type.DbTimestampType.java Source code

Java tutorial

Introduction

Here is the source code for org.hibernate.type.DbTimestampType.java

Source

/*
 * Hibernate, Relational Persistence for Idiomatic Java
 *
 * License: GNU Lesser General Public License (LGPL), version 2.1 or later.
 * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
 */
package org.hibernate.type;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.Date;

import org.hibernate.dialect.Dialect;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.internal.CoreMessageLogger;

import org.jboss.logging.Logger;

/**
 * <tt>dbtimestamp</tt>: An extension of {@link TimestampType} which
 * maps to the database's current timestamp, rather than the jvm's
 * current timestamp.
 * <p/>
 * Note: May/may-not cause issues on dialects which do not properly support
 * a true notion of timestamp (Oracle < 8, for example, where only its DATE
 * datatype is supported).  Depends on the frequency of DML operations...
 *
 * @author Steve Ebersole
 */
public class DbTimestampType extends TimestampType {
    public static final DbTimestampType INSTANCE = new DbTimestampType();

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

    @Override
    public String getName() {
        return "dbtimestamp";
    }

    @Override
    public String[] getRegistrationKeys() {
        return new String[] { getName() };
    }

    @Override
    public Date seed(SharedSessionContractImplementor session) {
        if (session == null) {
            LOG.trace("Incoming session was null; using current jvm time");
            return super.seed(null);
        } else if (!session.getJdbcServices().getJdbcEnvironment().getDialect()
                .supportsCurrentTimestampSelection()) {
            LOG.debug(
                    "Falling back to vm-based timestamp, as dialect does not support current timestamp selection");
            return super.seed(session);
        } else {
            return getCurrentTimestamp(session);
        }
    }

    private Date getCurrentTimestamp(SharedSessionContractImplementor session) {
        Dialect dialect = session.getJdbcServices().getJdbcEnvironment().getDialect();
        String timestampSelectString = dialect.getCurrentTimestampSelectString();
        if (dialect.isCurrentTimestampSelectStringCallable()) {
            return useCallableStatement(timestampSelectString, session);
        }
        return usePreparedStatement(timestampSelectString, session);
    }

    private Timestamp usePreparedStatement(String timestampSelectString, SharedSessionContractImplementor session) {
        PreparedStatement ps = null;
        try {
            ps = session.getJdbcCoordinator().getStatementPreparer().prepareStatement(timestampSelectString, false);
            ResultSet rs = session.getJdbcCoordinator().getResultSetReturn().extract(ps);
            rs.next();
            Timestamp ts = rs.getTimestamp(1);
            if (LOG.isTraceEnabled()) {
                LOG.tracev("Current timestamp retrieved from db : {0} (nanos={1}, time={2})", ts, ts.getNanos(),
                        ts.getTime());
            }
            return ts;
        } catch (SQLException e) {
            throw session.getJdbcServices().getSqlExceptionHelper().convert(e,
                    "could not select current db timestamp", timestampSelectString);
        } finally {
            if (ps != null) {
                session.getJdbcCoordinator().getLogicalConnection().getResourceRegistry().release(ps);
                session.getJdbcCoordinator().afterStatementExecution();
            }
        }
    }

    private Timestamp useCallableStatement(String callString, SharedSessionContractImplementor session) {
        CallableStatement cs = null;
        try {
            cs = (CallableStatement) session.getJdbcCoordinator().getStatementPreparer()
                    .prepareStatement(callString, true);
            cs.registerOutParameter(1, java.sql.Types.TIMESTAMP);
            session.getJdbcCoordinator().getResultSetReturn().execute(cs);
            Timestamp ts = cs.getTimestamp(1);
            if (LOG.isTraceEnabled()) {
                LOG.tracev("Current timestamp retrieved from db : {0} (nanos={1}, time={2})", ts, ts.getNanos(),
                        ts.getTime());
            }
            return ts;
        } catch (SQLException e) {
            throw session.getJdbcServices().getSqlExceptionHelper().convert(e,
                    "could not call current db timestamp function", callString);
        } finally {
            if (cs != null) {
                session.getJdbcCoordinator().getLogicalConnection().getResourceRegistry().release(cs);
                session.getJdbcCoordinator().afterStatementExecution();
            }
        }
    }
}