Hi, I've write a custom Pk generator,
Simply following and customizing the source of Hibernate
Code:
org.hibernate.id.MultipleHiLoPerTableGenerator
I've just done it because I need a composite primary key generator.
below the code I've customized.
Code:
public class MyHiLoIdGenerator
extends TransactionHelper
implements PersistentIdentifierGenerator, Configurable {
private static final Logger log = LoggerFactory.getLogger(SigeproHiLoIdGenerator.class);
public static final String ID_TABLE = "table";
public static final String PK_COLUMN_NAME = "primary_key_column";
public static final String PK2_COLUMN = "primary_key_column2";
public static final String PK_VALUE_NAME = "primary_key_value";
public static final String VALUE_COLUMN_NAME = "value_column";
public static final String PK_LENGTH_NAME = "primary_key_length";
private static final int DEFAULT_PK_LENGTH = 255;
public static final String DEFAULT_TABLE = "hibernate_sequences";
private static final String DEFAULT_PK_COLUMN = "sequence_name";
private static final String DEFAULT_PK2_COLUMN = "business_key_2";
private static final String DEFAULT_VALUE_COLUMN = "sequence_next_hi_value";
private String tableName;
private String pkColumnName;
private String business_key_2;
private String valueColumnName;
private String query;
private String insert;
private String update;
//hilo params
public static final String MAX_LO = "max_lo";
private long hi;
private int lo;
private int maxLo;
private Class returnClass;
private int keySize;
public String[] sqlCreateStrings(Dialect dialect) throws HibernateException {
return new String[] {
new StringBuffer( dialect.getCreateTableString() )
.append( ' ' )
.append( tableName )
.append( " ( " )
.append( pkColumnName )
.append( ' ' )
.append( dialect.getTypeName( Types.VARCHAR, keySize, 0, 0 ) )
.append( ", " )
.append( business_key_2 )
.append( ' ' )
.append( dialect.getTypeName( Types.VARCHAR, keySize, 0, 0 ) )
.append( ", " )
.append( valueColumnName )
.append( ' ' )
.append( dialect.getTypeName( Types.INTEGER ) )
.append( " ) " )
.toString()
};
}
public String[] sqlDropStrings(Dialect dialect) throws HibernateException {
StringBuffer sqlDropString = new StringBuffer( "drop table " );
if ( dialect.supportsIfExistsBeforeTableName() ) {
sqlDropString.append( "if exists " );
}
sqlDropString.append( tableName ).append( dialect.getCascadeConstraintsString() );
if ( dialect.supportsIfExistsAfterTableName() ) {
sqlDropString.append( " if exists" );
}
return new String[] { sqlDropString.toString() };
}
public Object generatorKey() {
return tableName;
}
public Serializable doWorkInCurrentTransaction(Connection conn, String sql) throws SQLException {
int result;
int rows;
do {
// The loop ensures atomicity of the
// select + update even for no transaction
// or read committed isolation level
//sql = query;
//SQL_STATEMENT_LOGGER.logStatement( sql, FormatStyle.BASIC );
PreparedStatement qps = conn.prepareStatement(query);
PreparedStatement ips = null;
try {
//qps.setString(1, ORMHelper.getProperties().getProperty("business_key_2"));
qps.setString(1, ORMHelper.getBusiness_key_2());
ResultSet rs = qps.executeQuery();
boolean isInitialized = rs.next();
if ( !isInitialized ) {
result = 0;
ips = conn.prepareStatement(insert);
//ips.setString(1, key);
ips.setInt(1, result);
//ips.setString(2, ORMHelper.getProperties().getProperty("business_key_2"));
ips.setString(2, ORMHelper.getBusiness_key_2());
ips.execute();
}
else {
result = rs.getInt(1);
}
rs.close();
}
catch (SQLException sqle) {
log.error("could not read or init a hi value", sqle);
throw sqle;
}
finally {
if (ips != null) {
ips.close();
}
qps.close();
}
//sql = update;
PreparedStatement ups = conn.prepareStatement(update);
try {
ups.setInt( 1, result + 1 );
ups.setInt( 2, result );
ups.setString( 3, ORMHelper.getBusiness_key_2() );
rows = ups.executeUpdate();
}
catch (SQLException sqle) {
log.error("could not update hi value in: " + tableName, sqle);
throw sqle;
}
finally {
ups.close();
}
}
while (rows==0);
return new Integer(result);
}
public synchronized Serializable generate(SessionImplementor session, Object obj)
throws HibernateException {
PkId genericId = new PkId();
if (maxLo < 1) {
//keep the behavior consistent even for boundary usages
int val = ( (Integer) doWorkInNewTransaction(session) ).intValue();
if (val == 0) val = ( (Integer) doWorkInNewTransaction(session) ).intValue();
genericId.setCodice((Integer)IdentifierGeneratorFactory.createNumber( hi + lo++, Integer.class ));
genericId.setIdcomune(ORMHelper.getBusiness_key_2());
return genericId;
}
if (lo>maxLo) {
int hival = ( (Integer) doWorkInNewTransaction(session) ).intValue();
lo = (hival == 0) ? 1 : 0;
hi = hival * (maxLo+1);
log.debug("new hi value: " + hival);
}
genericId.setCodice((Integer)IdentifierGeneratorFactory.createNumber( hi + lo++, Integer.class ));
//genericId.setIdcomune(ORMHelper.getProperties().getProperty("business_key_2"));
genericId.setIdcomune(ORMHelper.getBusiness_key_2());
return genericId;
}
public void configure(Type type, Properties params, Dialect dialect) throws MappingException {
tableName = PropertiesHelper.getString(ID_TABLE, params, DEFAULT_TABLE);
pkColumnName = PropertiesHelper.getString(PK_COLUMN_NAME, params, DEFAULT_PK_COLUMN);
business_key_2 = PropertiesHelper.getString(PK2_COLUMN, params, DEFAULT_PK2_COLUMN);
valueColumnName = PropertiesHelper.getString(VALUE_COLUMN_NAME, params, DEFAULT_VALUE_COLUMN);
String schemaName = params.getProperty(SCHEMA);
String catalogName = params.getProperty(CATALOG);
keySize = PropertiesHelper.getInt(PK_LENGTH_NAME, params, DEFAULT_PK_LENGTH);
String keyValue = PropertiesHelper.getString(PK_VALUE_NAME, params, params.getProperty(TABLE) );
System.out.println(sqlCreateStrings(dialect)[0]);
if ( tableName.indexOf( '.' )<0 ) {
tableName = Table.qualify( catalogName, schemaName, tableName );
}
query = "select " +
valueColumnName +
" from " +
dialect.appendLockHint(LockMode.UPGRADE, tableName) +
" where " + pkColumnName + " = '" + keyValue + "'" +
" and " + business_key_2 + " = ? " +
dialect.getForUpdateString();
update = "update " +
tableName +
" set " +
valueColumnName +
" = ? where " +
valueColumnName +
" = ? and " +
pkColumnName +
" = '" +
keyValue
+ "'" +
" and " + business_key_2 + " = ? ";
insert = "insert into " + tableName +
"(" + pkColumnName + ", " + valueColumnName + " , "+business_key_2 +") " +
"values('"+ keyValue +"', ?, ? )";
//hilo config
maxLo = PropertiesHelper.getInt(MAX_LO, params, Short.MAX_VALUE);
lo = maxLo + 1; // so we "clock over" on the first invocation
returnClass = type.getReturnedClass();
}
}
As a result I'have a table (hibernate_sequences)so defined
Code:
SEQUENCE_NAME VARCHAR2(255 CHAR)
PRIMARY_KEY_COLUMN2 VARCHAR2(255 CHAR)
SEQUENCE_NEXT_HI_VALUE NUMBER(10)
I think, that starting from the source of the IdGenerator in the package
org.hibernate.id.* you'll be able to create one of your own, instead of using the defaults.
hope this help.