如何在Hibernate中将字符串映射到DB序列 [英] How to map a string to DB sequence in Hibernate

查看:118
本文介绍了如何在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: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 {
$ b $ @Override
public Serializable generate(SessionImplementor session,Object collection)throws HibernateException {
Connection connection = session。连接();
PreparedStatement ps = null;
String result =;

try {
//特定于Oracle的代码来查询序列
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);

//转换为字符串
result = Integer.toString(pk);
}
} catch(SQLException e){
抛出新的HibernateException(Unable to generate Primary Key);
} finally {
if(ps!= null){
try {
ps.close();
} catch(SQLException e){
抛出新的HibernateException(Unable to close prepared statements。);
}
}
}

返回结果;






$ b

注释实体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;



$ b $ p
$ b

由于Eclipse中存在一个错误,可能会引发一个错误, seq_id )未在持久性单元中定义。将此设置为如下警告:


  1. 选择窗口»首选项 li>展开 Java持久性»JPA»错误/警告

  2. 单击查询和生成器 >设置生成器未在持久性单元中定义为:警告

  3. 单击 / strong>应用更改并关闭对话框


Pretty much says it in the title. I have a class that looks something like this:

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

Using Oracle 11g, the FOO_ID column is a VARCHAR2, but the sequence SQ_FOO_ID yields a NUMBER. The database is apparently happy with this, but the application needs to be able to support non-numeric IDs that may have been inserted into this column outside of the application.

Considering the code above, I get a org.hibernate.id.IdentifierGenerationException: Unknown integral data type for ids : java.lang.String. Is there any way to do this mapping?

Using Hibernate 3.6.

解决方案

Implement a custom IdentifierGenerator class; from a 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;
    }
}

Annotate the entity PK like this:

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

Due to a bug in Eclipse, an error might be raised that the generator (seq_id) is not defined in the persistence unit. Set this to a warning as follows:

  1. Select Window » Preferences
  2. Expand Java Persistence » JPA » Errors/Warnings
  3. Click Queries and generators
  4. Set Generator is not defined in the persistence unit to: Warning
  5. Click OK to apply changes and close the dialog

这篇关于如何在Hibernate中将字符串映射到DB序列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆