com.farmafene.commons.hibernate.generators.WorkInOther.java Source code

Java tutorial

Introduction

Here is the source code for com.farmafene.commons.hibernate.generators.WorkInOther.java

Source

/*
 * Copyright (c) 2009-2014 farmafene.com
 * All rights reserved.
 * 
 * Permission is hereby granted, free  of charge, to any person obtaining
 * a  copy  of this  software  and  associated  documentation files  (the
 * "Software"), to  deal in  the Software without  restriction, including
 * without limitation  the rights to  use, copy, modify,  merge, publish,
 * distribute,  sublicense, and/or sell  copies of  the Software,  and to
 * permit persons to whom the Software  is furnished to do so, subject to
 * the following conditions:
 * 
 * The  above  copyright  notice  and  this permission  notice  shall  be
 * included in all copies or substantial portions of the Software.
 * 
 * THE  SOFTWARE IS  PROVIDED  "AS  IS", WITHOUT  WARRANTY  OF ANY  KIND,
 * EXPRESS OR  IMPLIED, INCLUDING  BUT NOT LIMITED  TO THE  WARRANTIES OF
 * MERCHANTABILITY,    FITNESS    FOR    A   PARTICULAR    PURPOSE    AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE,  ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
package com.farmafene.commons.hibernate.generators;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import javax.persistence.Column;

import org.hibernate.LockMode;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.TransactionHelper;
import org.hibernate.id.IdentifierGenerationException;
import org.slf4j.Logger;

import com.farmafene.commons.hibernate.generators.SubSequenceTableGenerator.DataBaseName;

/**
 * {@inheritDoc}
 * 
 * @since 1.0.0
 */
class WorkInOther extends TransactionHelper {
    /**
     * 
     */
    private final SubSequenceTableGenerator WorkInOther;

    private Object[] theKey;

    private Logger logger;

    private Dialect dialectoBBDD;

    private DataBaseName db;

    private FieldsGenerador campos;

    public WorkInOther(SubSequenceTableGenerator subSequenceTableGeneratorV2, Object[] theKey, Logger logger,
            Dialect dialectoBBDD, DataBaseName db, FieldsGenerador campos) {
        WorkInOther = subSequenceTableGeneratorV2;
        this.theKey = theKey;
        this.logger = logger;
        this.dialectoBBDD = dialectoBBDD;
        this.db = db;
        this.campos = campos;
    }

    /**
     * {@inheritDoc}
     * 
     * @since 1.0.0
     */
    @Override
    protected Serializable doWorkInCurrentTransaction(Connection conn, String sqlNOUSADO) throws SQLException {
        try {
            Serializable salida = null;
            try {
                salida = getNextValue(conn, theKey);
            } catch (SQLException e) {
                logger.error("getNextValue SQLException: ", e);
                throw new UnsupportedOperationException(e);
            }
            updateNextValue(conn, salida, theKey);
            logger.debug(String.format("NextValue (%1$s): %2$s", salida.getClass().getName(), salida.toString()));
            return salida;

        } catch (IdentifierGenerationException e) {
            throw e;
        } finally {
            // DO NOTHING
        }
    }

    /**
     * {@inheritDoc}
     * 
     * @since 1.0.0
     */
    private void updateNextValue(Connection conn, Serializable id, Object[] theKey) throws SQLException {
        String sql = null;
        PreparedStatement qps = null;
        try {
            sql = getQueryUpdate();
            logger.debug(sql);
            qps = conn.prepareStatement(sql);
            qps.setString(1, id.toString());
            cargaValores(qps, 2, theKey);
            qps.executeUpdate();
        } catch (SQLException e) {
            logger.error("Error al recuperar el identificador", e);
            throw e;
        } finally {
            if (qps != null) {
                try {
                    qps.close();
                } catch (Throwable e) {

                }
            }
        }
    }

    /**
     * {@inheritDoc}
     * 
     * @since 1.0.0
     */
    private Serializable getNextValue(Connection conn, Object[] theKey) throws SQLException {
        PreparedStatement qps = null;
        PreparedStatement qps2 = null;
        ResultSet rs = null;
        ResultSet rs2 = null;
        String result = null;
        String sql = null;
        Serializable id = null;
        try {
            sql = getSelectQuery(dialectoBBDD);
            logger.debug(sql);
            qps = conn.prepareStatement(sql);
            cargaValores(qps, 1, theKey);
            rs = qps.executeQuery();
            if (!rs.next()) {
                logger.info("No se puede leer el siguiente valor - es necesario introducir valores en la tabla: "
                        + db.getNombreSecuencia());
                qps2 = conn.prepareStatement(getInsertQuery(dialectoBBDD));
                int index = cargaValores(qps2, 1, theKey);
                cargaValores(qps2, index, theKey);
                qps2.executeUpdate();
                rs2 = qps.executeQuery();
                if (rs2.next()) {
                    result = rs2.getString(1);
                } else {
                    throw new IdentifierGenerationException("No se ha podido generar el identificador");
                }
            } else {
                result = rs.getString(1);
            }
            if (result == null) {
                throw new IdentifierGenerationException("Identificador no encontrado");
            }
            try {
                id = (Serializable) campos.getTarget().getType().getConstructor(String.class).newInstance(result);
                if ("0".equals(id.toString())) {
                    throw new SQLException("Error en la generacin del identificador");
                }
            } catch (IllegalArgumentException e) {
                throw new IdentifierGenerationException(e.getMessage(), e);
            } catch (SecurityException e) {
                throw new IdentifierGenerationException(e.getMessage(), e);
            } catch (InstantiationException e) {
                throw new IdentifierGenerationException(e.getMessage(), e);
            } catch (IllegalAccessException e) {
                throw new IdentifierGenerationException(e.getMessage(), e);
            } catch (InvocationTargetException e) {
                throw new IdentifierGenerationException(e.getMessage(), e);
            } catch (NoSuchMethodException e) {
                throw new IdentifierGenerationException(e.getMessage(), e);
            }
            return id;
        } catch (SQLException e) {
            throw new SQLException("Identificador no encontrado", e);
        } finally {
            if (rs2 != null) {
                try {
                    rs2.close();
                } catch (Exception e) {
                }
            }
            if (rs != null) {
                try {
                    rs.close();
                } catch (Exception e) {
                }
            }
            if (qps2 != null) {
                try {
                    qps2.close();
                } catch (Exception e) {
                }
            }
            if (qps != null) {
                try {
                    qps.close();
                } catch (Exception e) {
                }
            }
        }
    }

    /**
     * {@inheritDoc}
     * 
     * @since 1.0.0
     */
    private String getSelectQuery(Dialect dialect) {
        StringBuilder sb = new StringBuilder("SELECT ")
                .append(campos.getTarget().getAnnotation(Column.class).name());
        sb.append(" FROM ");
        sb.append(dialect.appendLockHint(LockMode.UPGRADE, db.getNombreSecuencia()));
        writeWhereParameters(null, sb, campos.getLista());
        sb.append(dialect.getForUpdateString());
        return sb.toString();
    }

    private String getInsertQuery(Dialect dialect) {
        String initValue = "1";
        StringBuilder sb = new StringBuilder("INSERT INTO ");
        sb.append(db.getNombreSecuencia());
        sb.append(" (");
        for (Field f : campos.getLista()) {
            sb.append(f.getAnnotation(Column.class).name());
            sb.append(",");
        }
        sb.append(campos.getTarget().getAnnotation(Column.class).name());
        sb.append(") VALUES(");
        for (@SuppressWarnings("unused")
        Field f : campos.getLista()) {
            sb.append("?,");
        }
        sb.append("(SELECT CASE WHEN MAX(");
        sb.append(campos.getTarget().getAnnotation(Column.class).name());
        sb.append(") IS NULL THEN ");
        sb.append(initValue);
        sb.append(" ELSE MAX(");
        sb.append(campos.getTarget().getAnnotation(Column.class).name());
        sb.append(")+1 END FROM ");
        sb.append(WorkInOther.tableName);
        writeWhereParameters(null, sb, campos.getLista());
        sb.append(")");
        sb.append(")");
        String salida = sb.toString();
        if (logger.isDebugEnabled()) {
            logger.debug("getInsertQuery(): >" + salida + "<");
        }
        return salida;
    }

    /**
     * {@inheritDoc}
     * 
     * @since 1.0.0
     */
    void writeWhereParameters(String prefix, StringBuilder sb, Field[] listaCampos) {
        boolean where;
        where = true;
        for (Field f : listaCampos) {
            sb.append(where ? " WHERE " : " AND ");
            if (prefix != null) {
                sb.append(prefix).append(".");
            }
            sb.append(f.getAnnotation(Column.class).name());
            sb.append("=?");
            where = false;
        }
    }

    /**
     * {@inheritDoc}
     * 
     * @since 1.0.0
     */
    private int cargaValores(PreparedStatement qps, int indexInsert, Object[] theKey) throws SQLException {
        for (Object f : theKey) {
            logger.debug(String.format("parmetro[%1$d]: >%2$s<", indexInsert, f));
            qps.setObject(indexInsert++, f);
        }
        return indexInsert;
    }

    /**
     * {@inheritDoc}
     * 
     * @since 1.0.0
     */
    private String getQueryUpdate() {
        StringBuilder sb = new StringBuilder("UPDATE ").append(db.getNombreSecuencia());
        sb.append(" SET ").append(campos.getTarget().getAnnotation(Column.class).name()).append("=(?+1) ");
        writeWhereParameters(null, sb, campos.getLista());
        return sb.toString();
    }
}