oracle 如何在 Hibernate 中将字符串映射到数据库序列
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12517421/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to map a string to DB sequence in Hibernate
提问by Andy
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.
使用 Oracle 11g,FOO_ID
列是 a VARCHAR2
,但序列SQ_FOO_ID
产生 a NUMBER
。数据库显然对此很满意,但应用程序需要能够支持可能已在应用程序外部插入到此列中的非数字 ID。
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?
考虑到上面的代码,我得到了一个org.hibernate.id.IdentifierGenerationException: Unknown integral data type for ids : java.lang.String
. 有没有办法做这个映射?
Using Hibernate 3.6.
使用休眠 3.6。
采纳答案by chris
Implement a custom IdentifierGenerator class; from a blog post:
实现自定义的 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;
}
}
Annotate the entity PK like this:
像这样注释实体 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;
}
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:
由于 Eclipse 中的一个错误,可能会引发一个错误,即生成器 ( seq_id
) 未在持久性单元中定义。将其设置为警告,如下所示:
- Select Window ? Preferences
- Expand Java Persistence ? JPA ? Errors/Warnings
- Click Queries and generators
- Set Generator is not defined in the persistence unitto:
Warning
- Click OKto apply changes and close the dialog
- 选择窗口?喜好
- 展开Java 持久性?JPA ? 错误/警告
- 单击查询和生成器
- Set Generator 未在持久性单元中定义为:
Warning
- 单击确定应用更改并关闭对话框
回答by Norbert Madarász
This is another approach:
这是另一种方法:
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();
}
}
The sequence parameter has to be specified on the id property like in the following example:
必须在 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;
}