org.hibernate.id.IncrementGenerator.java Source code

Java tutorial

Introduction

Here is the source code for org.hibernate.id.IncrementGenerator.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.id;

import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;

import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.boot.model.naming.ObjectNameNormalizer;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.mapping.Table;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.type.Type;

/**
 * <b>increment</b><br>
 * <br>
 * An <tt>IdentifierGenerator</tt> that returns a <tt>long</tt>, constructed by
 * counting from the maximum primary key value at startup. Not safe for use in a
 * cluster!<br>
 * <br>
 * Mapping parameters supported, but not usually needed: tables, column.
 * (The tables parameter specified a comma-separated list of table names.)
 *
 * @author Gavin King
 * @author Steve Ebersole
 * @author Brett Meyer
 */
public class IncrementGenerator implements IdentifierGenerator, Configurable {
    private static final CoreMessageLogger LOG = CoreLogging.messageLogger(IncrementGenerator.class);

    private Class returnClass;
    private String sql;

    private IntegralDataTypeHolder previousValueHolder;

    @Override
    public synchronized Serializable generate(SharedSessionContractImplementor session, Object object)
            throws HibernateException {
        if (sql != null) {
            initializePreviousValueHolder(session);
        }
        return previousValueHolder.makeValueThenIncrement();
    }

    @Override
    public void configure(Type type, Properties params, ServiceRegistry serviceRegistry) throws MappingException {
        returnClass = type.getReturnedClass();

        final JdbcEnvironment jdbcEnvironment = serviceRegistry.getService(JdbcEnvironment.class);
        final ObjectNameNormalizer normalizer = (ObjectNameNormalizer) params
                .get(PersistentIdentifierGenerator.IDENTIFIER_NORMALIZER);

        String column = params.getProperty("column");
        if (column == null) {
            column = params.getProperty(PersistentIdentifierGenerator.PK);
        }
        column = normalizer.normalizeIdentifierQuoting(column).render(jdbcEnvironment.getDialect());

        String tableList = params.getProperty("tables");
        if (tableList == null) {
            tableList = params.getProperty(PersistentIdentifierGenerator.TABLES);
        }
        String[] tables = StringHelper.split(", ", tableList);

        final String schema = normalizer
                .toDatabaseIdentifierText(params.getProperty(PersistentIdentifierGenerator.SCHEMA));
        final String catalog = normalizer
                .toDatabaseIdentifierText(params.getProperty(PersistentIdentifierGenerator.CATALOG));

        StringBuilder buf = new StringBuilder();
        for (int i = 0; i < tables.length; i++) {
            final String tableName = normalizer.toDatabaseIdentifierText(tables[i]);
            if (tables.length > 1) {
                buf.append("select max(").append(column).append(") as mx from ");
            }
            buf.append(Table.qualify(catalog, schema, tableName));
            if (i < tables.length - 1) {
                buf.append(" union ");
            }
        }
        if (tables.length > 1) {
            buf.insert(0, "( ").append(" ) ids_");
            column = "ids_.mx";
        }

        sql = "select max(" + column + ") from " + buf.toString();
    }

    private void initializePreviousValueHolder(SharedSessionContractImplementor session) {
        previousValueHolder = IdentifierGeneratorHelper.getIntegralDataTypeHolder(returnClass);

        if (LOG.isDebugEnabled()) {
            LOG.debugf("Fetching initial value: %s", sql);
        }
        try {
            PreparedStatement st = session.getJdbcCoordinator().getStatementPreparer().prepareStatement(sql);
            try {
                ResultSet rs = session.getJdbcCoordinator().getResultSetReturn().extract(st);
                try {
                    if (rs.next()) {
                        previousValueHolder.initialize(rs, 0L).increment();
                    } else {
                        previousValueHolder.initialize(1L);
                    }
                    sql = null;
                    if (LOG.isDebugEnabled()) {
                        LOG.debugf("First free id: %s", previousValueHolder.makeValue());
                    }
                } finally {
                    session.getJdbcCoordinator().getLogicalConnection().getResourceRegistry().release(rs, st);
                }
            } finally {
                session.getJdbcCoordinator().getLogicalConnection().getResourceRegistry().release(st);
                session.getJdbcCoordinator().afterStatementExecution();
            }
        } catch (SQLException sqle) {
            throw session.getJdbcServices().getSqlExceptionHelper().convert(sqle,
                    "could not fetch initial value for increment generator", sql);
        }
    }
}