-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 
Author Message
 Post subject: mysql BIGINT column mapping in hibernate
PostPosted: Fri Feb 05, 2010 11:12 pm 
Newbie

Joined: Sat May 30, 2009 2:47 am
Posts: 12
Hi,

I am using MYSQL 5.1.36. The primary key of a table is BIGINT. The ID generation is using MYSQL auto_increment.

This is the hibernate mapping configuration:

<hibernate-mapping>
<class catalog="campaign_mgr" name="PlacementEvent" table="placement_event">
<id name="id" >
<column name="ID"/>
<generator class="identity"/>
</id>

Since I want to stick with what MYSQL jdbc driver recommend, using java.math.BigInteger for bigint column. Also that column is an unsigned column. java Long is not enough for this.

I get the following error when inserting a placementEvent row into DB. I am looking to implement my own generator class. However, I don't know which one I shall extend from and override. It is not that obvious to me by looking at the source of IdentityGenerator and IdentityGeneratorFactory classes. Can someone help on that? Thanks.

org.hibernate.id.IdentifierGenerationException: this id generator generates long, integer, short or string
at org.hibernate.id.IdentifierGeneratorFactory.get(IdentifierGeneratorFactory.java:116)
at org.hibernate.id.IdentifierGeneratorFactory.getGeneratedIdentity(IdentifierGeneratorFactory.java:92)
at org.hibernate.id.IdentityGenerator$GetGeneratedKeysDelegate.executeAndExtract(IdentityGenerator.java:98)
at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:57)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2176)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2656)
at org.hibernate.action.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:71)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:279)
at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:321)
at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:204)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:130)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:210)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:195)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:117)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:535)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:527)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:523)


Top
 Profile  
 
 Post subject: Re: mysql BIGINT column mapping in hibernate
PostPosted: Sat Feb 06, 2010 7:51 pm 
Newbie

Joined: Sat May 30, 2009 2:47 am
Posts: 12
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


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.