package org.hibernate.id;
import java.io.Serializable;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Properties;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.cfg.ObjectNameNormalizer;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.internal.FormatStyle;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.jdbc.spi.SqlStatementLogger;
import org.hibernate.engine.spi.SessionEventListenerManager;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.id.enhanced.SequenceStyleGenerator;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.config.ConfigurationHelper;
import org.hibernate.jdbc.AbstractReturningWork;
import org.hibernate.mapping.Table;
import org.hibernate.type.Type;
import org.jboss.logging.Logger;
@Deprecated
public class TableGenerator implements PersistentIdentifierGenerator, Configurable {
public static final String COLUMN = "column";
public static final String DEFAULT_COLUMN_NAME = "next_hi";
public static final String TABLE = "table";
public static final String DEFAULT_TABLE_NAME = "hibernate_unique_key";
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, TableGenerator.class.getName());
private Type identifierType;
private String tableName;
private String columnName;
private String query;
private String update;
public void configure(Type type, Properties params, Dialect dialect) {
identifierType = type;
ObjectNameNormalizer normalizer = ( ObjectNameNormalizer ) params.get( IDENTIFIER_NORMALIZER );
tableName = ConfigurationHelper.getString( TABLE, params, DEFAULT_TABLE_NAME );
if ( tableName.indexOf( '.' ) < 0 ) {
final String schemaName = normalizer.normalizeIdentifierQuoting( params.getProperty( SCHEMA ) );
final String catalogName = normalizer.normalizeIdentifierQuoting( params.getProperty( CATALOG ) );
tableName = Table.qualify(
dialect.quote( catalogName ),
dialect.quote( schemaName ),
dialect.quote( tableName )
);
}
else {
}
columnName = dialect.quote(
normalizer.normalizeIdentifierQuoting(
ConfigurationHelper.getString( COLUMN, params, DEFAULT_COLUMN_NAME )
)
);
query = "select " +
columnName +
" from " +
dialect.appendLockHint(LockMode.PESSIMISTIC_WRITE, tableName) +
dialect.getForUpdateString();
update = "update " +
tableName +
" set " +
columnName +
" = ? where " +
columnName +
" = ?";
}
public synchronized Serializable generate(SessionImplementor session, Object object) {
return generateHolder( session ).makeValue();
}
protected IntegralDataTypeHolder generateHolder(final SessionImplementor session) {
final SqlStatementLogger statementLogger = session.getFactory().getServiceRegistry()
.getService( JdbcServices.class )
.getSqlStatementLogger();
final SessionEventListenerManager listeners = session.getEventListenerManager();
return session.getTransactionCoordinator().getTransaction().createIsolationDelegate().delegateWork(
new AbstractReturningWork<IntegralDataTypeHolder>() {
@Override
public IntegralDataTypeHolder execute(Connection connection) throws SQLException {
IntegralDataTypeHolder value = buildHolder();
int rows;
do {
final PreparedStatement qps = prepareStatement( connection, query, statementLogger, listeners );
try {
ResultSet rs = executeQuery( qps, listeners );
if ( !rs.next() ) {
String err = "could not read a hi value - you need to populate the table: " + tableName;
LOG.error(err);
throw new IdentifierGenerationException(err);
}
value.initialize( rs, 1 );
rs.close();
}
catch (SQLException e) {
LOG.error("Could not read a hi value", e);
throw e;
}
finally {
qps.close();
}
final PreparedStatement ups = prepareStatement( connection, update, statementLogger, listeners );
try {
value.copy().increment().bind( ups, 1 );
value.bind( ups, 2 );
rows = executeUpdate( ups, listeners );
}
catch (SQLException sqle) {
LOG.error(LOG.unableToUpdateHiValue(tableName), sqle);
throw sqle;
}
finally {
ups.close();
}
}
while (rows==0);
return value;
}
},
true
);
}
private PreparedStatement prepareStatement(
Connection connection,
String sql,
SqlStatementLogger statementLogger,
SessionEventListenerManager statsCollector) throws SQLException {
statementLogger.logStatement( sql, FormatStyle.BASIC.getFormatter() );
try {
statsCollector.jdbcPrepareStatementStart();
return connection.prepareStatement( sql );
}
finally {
statsCollector.jdbcPrepareStatementEnd();
}
}
private int executeUpdate(PreparedStatement ps, SessionEventListenerManager statsCollector) throws SQLException {
try {
statsCollector.jdbcExecuteStatementStart();
return ps.executeUpdate();
}
finally {
statsCollector.jdbcExecuteStatementEnd();
}
}
private ResultSet executeQuery(PreparedStatement ps, SessionEventListenerManager statsCollector) throws SQLException {
try {
statsCollector.jdbcExecuteStatementStart();
return ps.executeQuery();
}
finally {
statsCollector.jdbcExecuteStatementEnd();
}
}
public String[] sqlCreateStrings(Dialect dialect) throws HibernateException {
return new String[] {
dialect.getCreateTableString() + " " + tableName + " ( "
+ columnName + " " + dialect.getTypeName(Types.INTEGER) + " )" + dialect.getTableTypeString(),
"insert into " + tableName + " values ( 0 )"
};
}
public String[] sqlDropStrings(Dialect dialect) {
return new String[] { dialect.getDropTableString( tableName ) };
}
public Object generatorKey() {
return tableName;
}
protected IntegralDataTypeHolder buildHolder() {
return IdentifierGeneratorHelper.getIntegralDataTypeHolder( identifierType.getReturnedClass() );
}
}