Custom Hibernate Sequence Generator for Id field

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]

13 thoughts on “Custom Hibernate Sequence Generator for Id field

  1. 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

  2. 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.

  3. 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.

  4. 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());
    }
    }

  5. Hi,

    Thanks for your tutorial. It really helped to set my own ID / PK generator
    I custimized with somme parameter passed to my PK Generator class.
    @Entity @Table(name=”UTILISATEUR”)
    public class UtilisateurEntity implements Serializable {
    private static final long serialVersionUID = -3416450676331189345L;

    @Id @GenericGenerator(name=”entityIGenerator”, strategy=”com.prima.solutions.primaclaims.core.dao.impl.PkGenerator”,
    parameters={@Parameter(name=PkGenerator.TABLE, value=”SEQUENCE”),
    @Parameter(name=PkGenerator.PK_COLUMN_VALUE, value=”UTILISATEUR”),
    @Parameter(name=PkGenerator.VALUE_COLUMN_NAME, value=”NUMERO”)
    })
    @GeneratedValue(generator=”entityIGenerator”)
    private Integer pk;

    ….
    }

    public class PkGenerator implements IdentifierGenerator, Configurable {

    @Override
    public Serializable generate(SessionImplementor session, Object obj) throws HibernateException {

    // Perform select, insert, update on the table storing Entities ID

    }

    @Override
    public void configure(Type type, Properties params, Dialect dialect) throws MappingException {

    // Retreive parameters passed from the Entity and init class values
    ..
    }

    }

  6. Thanks for the example, It helps to set custom Id.
    I am facing an issue when I try to create new schema from the POJO.
    Is it possible with this configuration like can I create table or schema from this configuration?
    When I apply to create custom id and try to execute project I am facing an issue with “Unknown Column :custom_id”
    Thank you

Leave a Reply to Peter Cancel reply

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