/**
 * Copyright 2008-2009. Chongqing Communications Industry Services Co.,Ltd Information Technology Branch. All rights reserved. <a>http://www.crunii.com</a>
 */
package com.crunii.micro.domain.common.hibernate;

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

import org.hibernate.HibernateException;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.id.enhanced.SequenceStructure;
import org.hibernate.id.enhanced.SequenceStyleGenerator;
import org.hibernate.type.IntegerType;
import org.hibernate.type.LongType;
import org.hibernate.type.StringType;
import org.hibernate.type.Type;

/**
 * @author 田平 create 2015年12月30日上午10:24:12
 */
public class MySqlSeqGenerator extends SequenceStyleGenerator {

	@Override
	public Serializable generate(SharedSessionContractImplementor session, Object object) throws HibernateException {
		
		Type type = session.getFactory().getIdentifierType(object.getClass().getName());
		SequenceStructure structure = (SequenceStructure) getDatabaseStructure();
		Dialect dialect = session.getFactory().getServiceRegistry().getService(JdbcServices.class).getDialect();
		String sql = dialect.getSequenceNextValString(structure.getName());
		Long nextId = null;
		try {
			final PreparedStatement st = session.getJdbcCoordinator().getStatementPreparer().prepareStatement(sql);
			try {
				final ResultSet rs = session.getJdbcCoordinator().getResultSetReturn().extract(st);
				try {
					rs.next();
					nextId = rs.getLong(1);
				} finally {
					try {
						session.getJdbcCoordinator().getLogicalConnection().getResourceRegistry().release(rs, st);
					} catch (Throwable ignore) {
						// intentionally empty
					}
				}
			} finally {
				session.getJdbcCoordinator().getLogicalConnection().getResourceRegistry().release(st);
				session.getJdbcCoordinator().afterStatementExecution();
			}

		} catch (SQLException sqle) {
			JdbcServices jdbcServices = session.getFactory().getServiceRegistry().getService(JdbcServices.class);
			throw jdbcServices.getSqlExceptionHelper().convert(sqle, "could not get next sequence value", sql);
		}

		if (type instanceof StringType) {
			return nextId.toString();
		} else if (type instanceof LongType) {
			return nextId;
		} else if (type instanceof IntegerType) {
			return nextId.intValue();
		} else {
			throw new RuntimeException("MySqlSeqGenerator not support type:" + type);
		}
	}
}
