I already figure out how to set up your own custom IdentityGenerator for BigINT. Here are the steps:
1. Create your own IdentityGenerator, e.g. ExtendedIdentityGenerator. In my case, I want to use statement.RETURN_GENERATED_KEYS. Therefore, I set the following property in hibernate.cfg.xml. <property name="hibernate.jdbc.use_get_generated_keys">true</property>
This is the logic in ExtendedIdentityGenerator. You can have different logic. I just copy most logic from existing IdentityGenerator and then override some logic there:
public class ExtendedIdentityGenerator extends AbstractPostInsertGenerator{
public InsertGeneratedIdentifierDelegate getInsertGeneratedIdentifierDelegate(
PostInsertIdentityPersister persister,
Dialect dialect,
boolean isGetGeneratedKeysEnabled) throws HibernateException {
return new GetGeneratedKeysDelegate( persister, dialect );
}
public static class GetGeneratedKeysDelegate
extends AbstractReturningDelegate
implements InsertGeneratedIdentifierDelegate {
private final PostInsertIdentityPersister persister;
private final Dialect dialect;
public GetGeneratedKeysDelegate(PostInsertIdentityPersister persister, Dialect dialect) {
super( persister );
this.persister = persister;
this.dialect = dialect;
}
public IdentifierGeneratingInsert prepareIdentifierGeneratingInsert() {
IdentifierGeneratingInsert insert = new IdentifierGeneratingInsert( dialect );
insert.addIdentityColumn( persister.getRootTableKeyColumnNames()[0] );
return insert;
}
protected PreparedStatement prepare(String insertSQL, SessionImplementor session) throws SQLException {
return session.getBatcher().prepareStatement( insertSQL, true );
}
public Serializable executeAndExtract(PreparedStatement insert) throws SQLException {
insert.executeUpdate();
ResultSet rs = null;
try {
rs = insert.getGeneratedKeys();
Type type = persister.getIdentifierType();
if (!rs.next()) {
throw new HibernateException("The database returned no generated identity value");
}
Class clazz = type.getReturnedClass();
if (clazz == java.math.BigInteger.class) {
logger.debug("retuned type: " + rs.getObject(1).getClass().getName());
return (java.math.BigInteger)rs.getObject(1);
} else {
throw new IdentifierGenerationException("this id generator generates BigInteger but get " + clazz.getName());
}
finally {
if ( rs != null ) {
rs.close();
}
}
}
}
}
2. Specify the class in the mapping corresponding to the table which has the BIGINT ID:
<hibernate-mapping>
<class catalog="campaign_mgr" name="com.mycorp.middleware.PlacementEvent" table="placement_event">
<id name="id" type="java.math.BigInteger">
<column name="ID" />
<generator class="com.mycorp.util.ExtendedIdentityGenerator"/> <---- Class name with full package path
</id>
This works except there is bug in MYSQL JDBC driver, since I get the same problem with pure jdbc code. What happen is that the returned result from insertion statement will be java.lang.Long. Then when you cast it to java.math.BigInteger, you will get ClassCastException. Unless MYSQL fixes that, this BIGINT identityGenerator won't work.
BTW, the ID column of the table is UNSIGNED BIGINT, according MYSQL jdbc documentation, java.math.BIGINTEGER is the java type for the column. That just does not work with insertion.
See
http://bugs.mysql.com/bug.php?id=50968