如何在Hibernate中将字符串映射到DB序列

几乎在标题中说出来。 我有一个看起来像这样的类:

@Entity @Table(name="FOO") public class Foo { private String theId; @Id @Column(name = "FOO_ID") @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "fooIdSeq") @SequenceGenerator(name = "fooIdSeq", sequenceName = "SQ_FOO_ID", allocationSize = 10) public String getTheId() { return theId; } public String setTheId(String theId) { this.theId = theId; } } 

使用Oracle 11g, FOO_ID列是VARCHAR2 ,但序列SQ_FOO_ID产生NUMBER 。 数据库显然对此感到满意,但应用程序需要能够支持可能已在应用程序外部插入此列的非数字ID。

考虑到上面的代码,我得到一个org.hibernate.id.IdentifierGenerationException: Unknown integral data type for ids : java.lang.String 。 有没有办法做这个映射?

使用Hibernate 3.6。

实现自定义IdentifierGenerator类; 来自博客文章 :

 import java.io.Serializable; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import org.hibernate.HibernateException; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.id.IdentifierGenerator; public class StringKeyGenerator implements IdentifierGenerator { @Override public Serializable generate(SessionImplementor session, Object collection) throws HibernateException { Connection connection = session.connection(); PreparedStatement ps = null; String result = ""; try { // Oracle-specific code to query a sequence ps = connection.prepareStatement("SELECT TABLE_SEQ.nextval AS TABLE_PK FROM dual"); ResultSet rs = ps.executeQuery(); if (rs.next()) { int pk = rs.getInt("TABLE_PK"); // Convert to a String result = Integer.toString(pk); } } catch (SQLException e) { throw new HibernateException("Unable to generate Primary Key"); } finally { if (ps != null) { try { ps.close(); } catch (SQLException e) { throw new HibernateException("Unable to close prepared statement."); } } } return result; } } 

像这样注释实体PK:

 @Id @GenericGenerator(name="seq_id", strategy="my.package.StringKeyGenerator") @GeneratedValue(generator="seq_id") @Column(name = "TABLE_PK", unique = true, nullable = false, length = 20) public String getId() { return this.id; } 

由于Eclipse中的错误,可能会引发错误,即生成器( seq_id )未在持久性单元中定义。 将此设置为警告,如下所示:

  1. 选择Window»Preferences
  2. 展开Java持久性»JPA»错误/警告
  3. 单击查询和生成器
  4. 设置生成器未在持久性单元中定义为: Warning
  5. 单击“ 确定”以应用更改并关闭对话框

这是另一种方法:

 import java.io.Serializable; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.id.IdentifierGeneratorHelper.BigDecimalHolder; import org.hibernate.id.IntegralDataTypeHolder; import org.hibernate.id.SequenceGenerator; public class StringSequenceGenerator extends SequenceGenerator { @Override public Serializable generate(SessionImplementor session, Object obj) { return super.generate( session, obj ).toString(); } protected IntegralDataTypeHolder buildHolder() { return new BigDecimalHolder(); } } 

必须在id属性上指定sequence参数,如下例所示:

 @Id @GenericGenerator(name = "STRING_SEQUENCE_GENERATOR", strategy = "mypackage.StringSequenceGenerator", parameters = { @Parameter(name = "sequence", value = "MY_SEQUENCE_NAME") }) @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "STRING_SEQUENCE_GENERATOR") @Column(name = "MY_ID") public String getMyId() { return this.myId; }