-->
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.  [ 13 posts ] 
Author Message
 Post subject: Custom types and ID generators
PostPosted: Fri Mar 26, 2004 12:26 am 
Regular
Regular

Joined: Fri Dec 12, 2003 2:09 pm
Posts: 84
Location: San Francisco, USA
We strongly type the IDs of our persistent objects so that when we reference objects by ID, we know which kind of object we're dealing with. This makes things more readable, improves type safety, etc.

We want to use a Hibernate ID sequence generator that maps database NUMBERs to custom types, in particular subclasses of our PersistentEntityId class, rather than to Long, Integer, or Short. We couldn't figure out a way to do this out-of-the box (please correct me if I'm wrong), so we copied-and-modified Hibernate's SequenceGenerator to come up with our own IdSequenceGenerator.

I posted the results below too see if are interested in this pattern. I suspect that Hibernate's built-in ID generators could easily be extended to map to custom types, so I'll file an enhancement request if there's sufficient interest.

Sample mapping:
Code:
<!-- primary key -->
<id name="id"
    column="NODE_ID"
    type="com.purisma.node.NodeId">
    <generator class="com.purisma.db.util.IdSequenceGenerator">
        <param name="sequence">NODE_SEQ</param>
    </generator>
</id>


IdSequenceGenerator class:
Code:
public class IdSequenceGenerator implements IdentifierGenerator, Configurable
{
    public static final String HIBERNATE_SEQUENCE = "hibernate_sequence";
    public static final String SCHEMA = "schema";
    public static final String SEQUENCE = "sequence";

    private Class _idClass = null;
    private String _sequenceName = null;
    private Type _type = null;
    private String _nextValSql = null;
   
    public void configure(Type type, Properties params, Dialect dialect)
        throws MappingException {

        // get the name of the sequence
        _sequenceName = PropertiesHelper.getString(SEQUENCE, params, HIBERNATE_SEQUENCE);
        String schemaName = params.getProperty(SCHEMA);
        if ( schemaName!=null && _sequenceName.indexOf(StringHelper.DOT)<0 )
            _sequenceName = schemaName + '.' + _sequenceName;
        _nextValSql = dialect.getSequenceNextValString(_sequenceName);

        // verify the validity of the ID type
        _type = type;
        _idClass = type.getReturnedClass();       
        if (! PersistentEntityId.class.isAssignableFrom(_idClass)) {
            throw new MappingException("ID class does not extend PersistentEntityId: " + _idClass);           
        }
    }
   
    public Serializable generate(SessionImplementor session, Object obj)
        throws SQLException, HibernateException
    {
        PreparedStatement st = session.getBatcher().prepareStatement(_nextValSql);
        try {
            ResultSet rs = st.executeQuery();
            final long result;
            try {
                rs.next();
                result = rs.getLong(1);
            } finally {
                rs.close();
            }
            return PersistentEntityId.createIdObject(_idClass, result);
        } catch (SQLException sqle) {
            JDBCExceptionReporter.logExceptions(sqle);
            throw sqle;
        } finally {
            session.getBatcher().closeStatement(st);
        }       
    }
   
}


p.s. We have developed a good deal of Hibernate "how to" documentation to help our engineers understand and use Hibernate. I'd like to offer this back to the community as well -- should I post it to the Community wiki?


Top
 Profile  
 
 Post subject: Re: Custom types and ID generators
PostPosted: Fri Mar 26, 2004 4:29 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
hypernate wrote:
p.s. We have developed a good deal of Hibernate "how to" documentation to help our engineers understand and use Hibernate. I'd like to offer this back to the community as well -- should I post it to the Community wiki?

Sure, it is very welcome.

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jun 16, 2005 12:04 pm 
Newbie

Joined: Wed Jun 15, 2005 8:00 am
Posts: 16
Location: Munich, Germany
Thanks, you saved my day! (http://forum.hibernate.org/viewtopic.php?t=943812)


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jun 16, 2005 12:49 pm 
Regular
Regular

Joined: Fri Dec 12, 2003 2:09 pm
Posts: 84
Location: San Francisco, USA
You're welcome!


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jun 16, 2005 11:20 pm 
Beginner
Beginner

Joined: Mon Jun 13, 2005 5:52 pm
Posts: 43
I've done something very similar in my app, and I wouldn't ever switch back to primitive types for primary keys.

You might consider using an interface that the abstract key class must implement. Rather than having your generator refer directly to the abstract class, you can use an interface like:

Code:
public interface IntegerIdentifierKey {

  public Integer getIdentifier();
 
  public void setIdentifier(Integer identifier);
 
}


You can then just create a new instance of the class name provided in the parameter, which will be castable to the IntegerIdentifierKey class. This will help others be able to reuse this pattern more easily.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jun 17, 2005 3:15 am 
Regular
Regular

Joined: Fri Dec 12, 2003 2:09 pm
Posts: 84
Location: San Francisco, USA
Agreed -- that would allow the base implementation to be completely independent of the concrete classes. At the same time, I have as of late been opting towards minimizing use of interfaces, having seen interface proliferation drive development teams crazy on several projects.

Internal projects vs. public patterns have different needs, no doubt.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jun 17, 2005 4:13 am 
Newbie

Joined: Wed Jun 15, 2005 8:00 am
Posts: 16
Location: Munich, Germany
I derived an abstract class from Number which is base for all strong typed (immutable) numbers and ids.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jun 20, 2005 9:43 am 
Newbie

Joined: Wed Jun 15, 2005 8:00 am
Posts: 16
Location: Munich, Germany
Were you able to create the mapping xml for such via XDoclet? I keep getting errors and don't know what I'm doing wrong.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jun 20, 2005 12:38 pm 
Regular
Regular

Joined: Fri Dec 12, 2003 2:09 pm
Posts: 84
Location: San Francisco, USA
We don't use Xdoclet.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 22, 2005 9:48 am 
Newbie

Joined: Wed Jun 15, 2005 8:00 am
Posts: 16
Location: Munich, Germany
Can't you or just don't you want to?


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 22, 2005 12:17 pm 
Regular
Regular

Joined: Fri Dec 12, 2003 2:09 pm
Posts: 84
Location: San Francisco, USA
mrohrmoser wrote:
Can't you or just don't you want to?


We began development before Xdoclet was stable, and we haven't had a reason to upgrade to it. We haven't even had the conversation over whether HBM generation from annotations is appropriate for us.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jan 03, 2006 5:47 am 
Newbie

Joined: Tue Sep 13, 2005 9:09 am
Posts: 17
Hello,

I want to make the schema of the sequence as parameter so i have used your code above. I thought, i have to add "schema" property to hibernate properties ("params") and it will be used in configure method but it keeps the "schemaName" to null.

I want to know where i have to specify the "schema" property that will be affected to "schemaName" variable in the configure method.


Thank you for your help.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jan 03, 2006 6:40 am 
Newbie

Joined: Wed Jun 15, 2005 8:00 am
Posts: 16
Location: Munich, Germany
I added to the hibernate.cfg:

<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<property name="connection.url">jdbc:oracle:thin:@MyServer:MyPort:MyCatalog</property>
<property name="connection.username">MyUid</property>
<property name="connection.password">MyPwd</property>
<property name="hibernate.default_schema">MySchema</property>

Greetings,
M


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 13 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.