7

我正在寻找一种SYS_GUID()在插入新行时让休眠以使用 oracle 功能的方法。目前我的数据库表具有SYS_GUID()默认值,因此如果休眠只是生成省略了该值的 SQL,它应该可以工作。

我一切正常,但它目前正在使用 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;
}

这很好,但我更希望 guid 由数据库生成,因此它们将是连续的并且可能具有更好的性能。另外,我只想知道如何配置它。

我使用注释进行配置,但 xml 配置示例也很棒。

这是一个示例表定义(以防万一):

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)
)

更新:

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 (?, ?, ?, ?, ?, ?)

似乎不可能在插入中使用列默认值,因此选择是在应用程序生成的 guid 和数据库往返之间进行选择。

4

3 回答 3

5

您也许可以使用“guid”生成器。请参阅Hibernate 论坛上的这篇文章。看起来他们不久前增加了对 OracleSYS_GUID()的支持,但文档仍然说他们只支持 SQL Server 和 MySQL。

我还没有使用过 JPA 注释,但这里有一个使用 XML 配置的示例:

<id name="PRODUCT_ID">
  <generator class="guid" />
</id>

编辑:关于你的第二个问题,我想你是在问为什么 Hibernate 不能做这样的事情:

INSERT INTO PRODUCT (PRODUCT_ID, /* etc */)
SELECT SYSGUID(), /* etc */

原因是 Hibernate 必须知道对象的 ID 是什么。例如,考虑以下场景:

  1. 您创建一个新的 Product 对象并保存它。Oracle 分配 ID。
  2. 您将产品从 Hibernate 会话中分离出来。
  3. 您稍后重新附加它并进行一些更改。
  4. 您现在想要保留这些更改。

在不知道 ID 的情况下,Hibernate 无法做到这一点。它需要 ID 才能发出 UPDATE 语句。因此,实现org.hibernate.id.GUIDGenerator必须事先生成 ID,然后在 INSERT 语句中重新使用它。

这与如果您使用数据库生成的 ID(包括支持它的数据库上的自动增量),Hibernate 无法进行任何批处理的原因相同。在一次插入大量对象时,使用其中一个 hilo 生成器或其他一些 Hibernate 生成的 ID 机制是获得良好性能的唯一方法。

于 2009-05-11T05:49:31.797 回答
2

我有与主题启动器相同的任务。感谢@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"String类型是解决方案的重要组成部分。

在持久化新实体之前,Hibernate 发出 SQL 查询:

select rawtohex(sys_guid()) from dual

我的设置:Oracle 11、Hibernate 4.3.4.Final、Spring 3.2.x。如果raw(16)您使用char(32).

当我尝试java.util.UUID用作 ID 字段类型时,我从 Hibernate 收到关于持久化新实体的错误(它尝试将String类型设置为java.util.UUID字段)。

我还javax.xml.bind.DatatypeConverter用于非 Hibernate 查询(Spring JDBC 帮助程序),用于将转换传递给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);

用于提取:

ResultSet rs;
sig.id = DatatypeConverter.printHexBinary(rs.getBytes("UUID"));

所有 Web 控制器都获得如下代码:

025131763FB19522E050010A106D11E9

没有{, -,字符(如果你记得的话},UUID 的通常表示是)。{a-b-c-d-x-y}这种表示已经 URL 编码干净和安全。您不需要实现或PropertyEditor类型:ConvertorString

@RequestMapping(value = {"/signal/edit/{id}.htm"}, method = RequestMethod.POST)
public String handleEditRequest(
        @PathVariable("id") String id,

与失败的使用尝试相比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);
}

为了使用:

@PathVariable("id") UUID id,
于 2014-09-11T14:50:01.983 回答
0

我认为你可以通过将生成器设置为原生来做到这一点。我不确定如何在 Hibernate 中执行此操作,但在 NHibernate 中,您会在 XML 中执行以下操作:

<id column="PRODUCT_ID">
  <generator class="native"/>
</id>
于 2009-05-11T05:29:21.503 回答