Custom Hibernate Sequence Generator for Id field

January 27th, 2009 | Posted by anorakgirl in Code

I have a table with a primary key in the format M001, M002 etc (lets not think about what happens after M999 for now). I’m using Hibernate Annotations, and I found a great way of generating the Primary Key value for new Records:

First I created a database sequence to use. Then I implemented org.hibernate.id.IdentifierGenerator;

public class StockCodeGenerator implements IdentifierGenerator {

    private static Logger log = Logger.getLogger(StockCodeGenerator.class);

    public Serializable generate(SessionImplementor session, Object object)
            throws HibernateException {

        String prefix = "M";
        Connection connection = session.connection();
        try {

            PreparedStatement ps = connection
                    .prepareStatement("SELECT nextval ('seq_stock_code') as nextval");

            ResultSet rs = ps.executeQuery();
            if (rs.next()) {
                int id = rs.getInt("nextval");
                String code = prefix + StringUtils.leftPad("" + id,3, '0');
                log.debug("Generated Stock Code: " + code);
                return code;
            }

        } catch (SQLException e) {
            log.error(e);
            throw new HibernateException(
                    "Unable to generate Stock Code Sequence");
        }
        return null;
    }
}

Then, in my entity class, I simply annotate the id field like this:

@Id
@GenericGenerator(name="seq_id", strategy="my.package.StockCodeGenerator")
@GeneratedValue(generator="seq_id")
@Column(name = "stock_code", unique = true, nullable = false, length = 20)
public String getStockCode() {
    return this.stockCode;
}

It works really well!

[Thanks to Jejomar Dimayuga for this post http://blog.dagitab.com/htsrv/trackback.php?tb_id=30 which I have modified slightly to use a sequence rather than a table]

  

You can follow any responses to this entry through the RSS 2.0 You can leave a response, or trackback.

6 Responses

  • David says:

    Hi your article helps me a lot . Thank you.

    I still have some questions as shown below:

    1. What if I wire hibernate database connection in spring, do I have to still write things like Connection connection = session.connection(); PreparedStatement ps = connection ??
    2. If rs.next() does not return anything, how this situation needs to be processed?

    Thanks

  • Thanks for this post.

    Just to ask, did you configure hibernate to auto create the seq_stock_code sequence?

  • Praveen reddy says:

    It is helped me a lot. Thanks a lot….

  • madhawa chaminda says:

    your post was valuable much for me,but i am not using annotations,only the hibenate mapping files.will you explain me how to incorporate your example with hibernate mapping file,
    Thank you very much.

  • Mark R says:

    The code lacks closing statements on the result set and prepared statement.
    We got “too many open cursors” in Oracle using it, so close() calles need to be added.

  • Peter says:

    Thanks for the code, just what I was looking for.

    I have a slightly different implementation

    Connection connection = session.connection();
    PreparedStatement ps = null;
    try {
    ps = connection
    .prepareStatement(“SELECT nextval (‘hibernate_sequence’) as nextval”);

    ResultSet rs = ps.executeQuery();
    rs.next();
    Long id = rs.getLong(“nextval”);
    if (log.isDebugEnabled())
    log.debug(“Generating new id:” + id);
    return id;

    } catch (SQLException e) {
    throw new UncheckedException(“Failed to generate new sequence for:”
    + object, e);
    } finally {
    if (ps != null)
    try {
    ps.close();
    } catch (Throwable e) {
    log.warn(“Failed to close statement:” + e.getMessage());
    }
    }



Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>