【问题标题】:How to map a string to DB sequence in Hibernate如何在 Hibernate 中将字符串映射到 DB 序列
【发布时间】:2012-09-13 02:27:35
【问题描述】:

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

@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。有没有办法做这个映射?

使用休眠 3.6。

【问题讨论】:

    标签: java oracle hibernate


    【解决方案1】:

    实现一个自定义的 IdentifierGenerator 类;来自blog post

    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. 选择窗口»首选项
    2. 展开 Java 持久性 » JPA » 错误/警告
    3. 点击查询和生成器
    4. Generator is not defined in the persistence unit设置为:Warning
    5. 点击确定应用更改并关闭对话框

    【讨论】:

      【解决方案2】:

      这是另一种方法:

      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 属性上指定序列参数,如下例所示:

      @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;
      }
      

      【讨论】:

        猜你喜欢
        • 2018-01-16
        • 2016-11-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多