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]
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?
It is helped me a lot. Thanks a lot….
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.
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.
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());
}
}
It helps me a lot!! Thank you! We use Firebird 1.5 and hibernates implemented generators doesn’t work with this dialect.
thanks for the post, it was helpful
What if I want to increment the sequence by 2
Like mentioned in your examaple : M001,M003,M005
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
..
}
}
When generate method will call ? I have done same but generate method is not calling
Good post, keep
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