将 Hibernate 配置为使用 Oracle 的 SYS_GUID() 作为主键
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/846786/
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
Configure Hibernate to use Oracle's SYS_GUID() for Primary Key
提问by Ryan Cook
I am looking for a way to get hibernate to use oracle's SYS_GUID()
function when inserting new rows. Currently my DB tables have SYS_GUID()
as the default so if hibernate simply generated SQL that omited the value it should work.
我正在寻找一种SYS_GUID()
在插入新行时让休眠使用 oracle函数的方法。目前我的数据库表SYS_GUID()
是默认的,所以如果休眠只是生成忽略它应该工作的值的 SQL。
I have everything working, but it is currently generating the UUID/GUID in code using the system-uuid generator:
我一切正常,但它目前正在使用 system-uuid 生成器在代码中生成 UUID/GUID:
@Id
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name = "system-uuid", strategy = "uuid")
@Column(name = "PRODUCT_ID", unique = true, nullable = false)
public String getId() {
return this.productId;
}
This is fine, but I would prefer that the guids were generated by the database so they will be sequential and potentially have better performance. Plus I would just like to know how to configure this.
这很好,但我更希望 guid 由数据库生成,因此它们将是顺序的并且可能具有更好的性能。另外,我只想知道如何配置它。
I am using annotations for configuration, but xml configuration examples are awesome as well.
我正在使用注释进行配置,但 xml 配置示例也很棒。
Here is a sample table definition (in case it matters):
这是一个示例表定义(以防万一):
CREATE TABLE SCHEMA_NAME.PRODUCT
(
PRODUCT_ID RAW(16) DEFAULT SYS_GUID() NOT NULL,
PRODUCT_CODE VARCHAR2(10 CHAR) NOT NULL,
PRODUCT_NAME VARCHAR2(30 CHAR) NOT NULL,
PRODUCT_DESC VARCHAR2(512 CHAR)
)
UPDATE:
更新:
Mat's sollution of using "guid" worked, here is the sql generated:
Mat 使用“guid”的解决方案起作用了,这是生成的 sql:
Hibernate:
select rawtohex(sys_guid())
from dual
Hibernate:
insert into PRODUCT
(PRODUCT_CODE, PRODUCT_DESC, LOB_ID, PRODUCT_NAME, PROVIDER_ID, PRODUCT_ID)
values (?, ?, ?, ?, ?, ?)
It seems that using the columns default value in an insert is not possible, so the choice is between an application generated guid and a database round trip.
似乎在插入中使用列默认值是不可能的,因此在应用程序生成的 guid 和数据库往返之间进行选择。
采纳答案by Matt Solnit
You might be able to use the "guid" generator. See this postfrom the Hibernate forum. It looks like they added support for Oracle using SYS_GUID()
a while back, but the documentationstill says they only support SQL Server and MySQL.
您也许可以使用“guid”生成器。请参阅Hibernate 论坛上的这篇文章。看起来他们在不久前增加了对 Oracle 的支持SYS_GUID()
,但文档仍然说他们只支持 SQL Server 和 MySQL。
I haven't worked with JPA annotations yet, but here is an example using XML configuration:
我还没有使用过 JPA 注释,但这里有一个使用 XML 配置的示例:
<id name="PRODUCT_ID">
<generator class="guid" />
</id>
EDIT:In regards to your second question, I think you are asking why Hibernate can't do something like this:
编辑:关于你的第二个问题,我想你是在问为什么 Hibernate 不能做这样的事情:
INSERT INTO PRODUCT (PRODUCT_ID, /* etc */)
SELECT SYSGUID(), /* etc */
The reason is that Hibernate must know what the object's ID is. For example, consider the following scenario:
原因是 Hibernate 必须知道对象的 ID 是什么。例如,请考虑以下场景:
- You create a new Product object and save it. Oracle assigns the ID.
- You detach the Product from the Hibernate session.
- You later re-attach it and make some changes.
- You now want to persist those changes.
- 您创建一个新的 Product 对象并保存它。Oracle 分配 ID。
- 您从 Hibernate 会话中分离产品。
- 您稍后重新附加它并进行一些更改。
- 您现在想要保留这些更改。
Without knowing the ID, Hibernate can't do this. It needs the ID in order to issue the UPDATE statement. So the implementation of org.hibernate.id.GUIDGenerator
has to generate the ID beforehand, and then later on re-use it in the INSERT statement.
在不知道 ID 的情况下,Hibernate 无法执行此操作。它需要 ID 才能发出 UPDATE 语句。所以执行org.hibernate.id.GUIDGenerator
必须事先生成 ID,然后在 INSERT 语句中重新使用它。
This is the same reason why Hibernate cannot do any batchingif you use a database-generated ID (including auto-increment on databases that support it). Using one of the hilo generators, or some other Hibernate-generated ID mechanism, is the only way to get good performance when inserting lots of objects at once.
如果您使用数据库生成的 ID(包括支持它的数据库的自动增量),这与 Hibernate 无法进行任何批处理的原因相同。使用 hilo 生成器之一或其他一些 Hibernate 生成的 ID 机制是一次插入大量对象时获得良好性能的唯一方法。
回答by gavenkoa
I have same task that topic starter. With thanks to @Matt Solnitsuggestion I use such annotations:
我有与主题启动器相同的任务。感谢@Matt Solnit 的建议,我使用了这样的注释:
@Id
@NotNull
@Column(name = "UUID")
@GenericGenerator(name = "db-uuid", strategy = "guid")
@GeneratedValue(generator = "db-uuid")
private String uuid;
public String getUuid() { return uuid; }
public void setUuid(String uuid) { this.uuid = uuid; }
strategy = "guid"
and String
type are essential parts of solution.
strategy = "guid"
和String
类型是解决方案的重要组成部分。
Before persisting new entities Hibernate issue SQL query:
在持久化新实体之前,Hibernate 发出 SQL 查询:
select rawtohex(sys_guid()) from dual
My setup: Oracle 11, Hibernate 4.3.4.Final, Spring 3.2.x. And field is raw(16)
in table for efficient storage and lesser index size then if you use char(32)
.
我的设置:Oracle 11、Hibernate 4.3.4.Final、Spring 3.2.x。而场是raw(16)
在表中存储效率和较小的索引的大小,然后,如果你使用char(32)
。
When I try to use java.util.UUID
as ID field type I get error from Hibernate on persisting new entity (it try to set String
type to java.util.UUID
field).
当我尝试java.util.UUID
用作 ID 字段类型时,我在持久化新实体时从 Hibernate 收到错误(它尝试将String
类型设置为java.util.UUID
字段)。
Also I use javax.xml.bind.DatatypeConverter
for non-Hibernate queries (Spring JDBC helpers), for passing convert to byte[]
:
我还javax.xml.bind.DatatypeConverter
用于非 Hibernate 查询(Spring JDBC 助手),用于将 convert 传递给byte[]
:
String query = "insert into TBL (UUID, COMPANY) values (:UUID, :COMPANY)";
MapSqlParameterSource parameters = new MapSqlParameterSource()
.addValue("COMPANY", repo.getCompany())
.addValue("UUID", DatatypeConverter.parseHexBinary(signal.getUuid()));
namedJdbcTemplate.update(query, parameters);
for extracting:
提取:
ResultSet rs;
sig.id = DatatypeConverter.printHexBinary(rs.getBytes("UUID"));
All web controllers get codes like:
所有网络控制器都获得如下代码:
025131763FB19522E050010A106D11E9
without {
, -
, }
chars (usual representation of UUID is {a-b-c-d-x-y}
if you remember). This representation already URL encoding clean and safe. You don't need to implement PropertyEditor
or Convertor
for String
type:
没有{
, -
,}
字符(UUID 的通常表示是,{a-b-c-d-x-y}
如果你还记得的话)。这种表示已经 URL 编码干净和安全。你并不需要实现PropertyEditor
或Convertor
进行String
类型:
@RequestMapping(value = {"/signal/edit/{id}.htm"}, method = RequestMethod.POST)
public String handleEditRequest(
@PathVariable("id") String id,
Compare with failed attempt to use jaa.util.UUID
, where I need to write:
与失败的使用尝试进行比较jaa.util.UUID
,我需要在其中编写:
@Component
public static class UUIDPropertyEditor extends PropertyEditorSupport {
@Override
public void setAsText(final String str) {
if (str == null || str.isEmpty()) {
setValue(null);
return;
}
setValue(UUID.fromString(str));
}
}
private @Autowired UUIDPropertyEditor juuidPE;
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(UUIDPropertyEditor.class, juuidPE);
}
in order to use:
为了使用:
@PathVariable("id") UUID id,
回答by cdmckay
I think you can do it by setting the generator to native. I'm not really sure how to do it in Hibernate but in NHibernate you'd do something like this in the XML:
我认为您可以通过将生成器设置为本机来实现。我不太确定如何在 Hibernate 中执行此操作,但在 NHibernate 中,您可以在 XML 中执行以下操作:
<id column="PRODUCT_ID">
<generator class="native"/>
</id>