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]
Tags: annotations, hibernate, java
September 20th, 2010 at 3:23 pm
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
March 16th, 2011 at 10:26 am
Thanks for this post.
Just to ask, did you configure hibernate to auto create the seq_stock_code sequence?
February 1st, 2012 at 11:44 am
It is helped me a lot. Thanks a lot….
May 26th, 2012 at 7:03 am
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.
November 21st, 2012 at 4:04 pm
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.
November 29th, 2012 at 12:15 pm
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());
}
}