Настройте Hibernate для использования sys GUID() Oracle для первичного ключа

Я ищу способ заставить hibernate использовать oracle при вставке новых строк. В настоящее время мои таблицы БД имеют SYS_GUID() по умолчанию, поэтому, если hibernate просто сгенерировал SQL, который опустил значение, оно должно работать.

у меня все работает, но в настоящее время он генерирует UUID/GUID в коде, используя генератор system-uuid:

@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's sollution использования "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, сгенерированным приложением и базой данных туда и обратно.

3 ответов


возможно, вы сможете использовать генератор "guid". См.этот пост С форума Hibernate. Похоже, они добавили поддержку Oracle с помощью SYS_GUID() некоторое время назад, но документация по-прежнему говорит, что они поддерживают только SQL Server и MySQL.

Я еще не работал с аннотациями JPA, но вот пример использования конфигурации XML:

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

EDIT: что касается вашего второго вопроса, я думаю, вы спрашиваете почему Hibernate не может сделать что-то подобное:

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

причина в том, что Hibernate должен знать, что такое идентификатор объекта. Например, рассмотрим следующий сценарий:

  1. вы создаете новый объект продукта и сохраняете его. Oracle присваивает идентификатор.
  2. вы отсоединяете продукт от сеанса гибернации.
  3. вы позже повторно прикрепите его и внесете некоторые изменения.
  4. теперь вы хотите сохранить эти изменения.

не зная ID, Hibernate не может этого сделать. Ему нужен ID для выпуска инструкции UPDATE. Итак, реализация org.hibernate.id.GUIDGenerator должен сгенерировать идентификатор заранее, а затем повторно использовать его в инструкции INSERT.

это та же самая причина, почему Hibernate не может пакетной если вы используете ID, созданный базой данных (включая автоматическое приращение для баз данных, которые его поддерживают). Используя один из генераторов hilo, или некоторые другой механизм Hibernate-generated ID-это единственный способ получить хорошую производительность при вставке сразу нескольких объектов.


у меня такая же задача, что и тема starter. С благодарностью @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 тип необходимые части решения.

перед сохранением новых сущностей спящий режим выдает SQL-запрос:

select rawtohex(sys_guid()) from dual

моя настройка: Oracle 11, Hibernate 4.3.4.Финал, Весна 3.2.х. И поле raw(16) в таблице для эффективного хранения и меньшего размера индекса, если вы используете char(32).

когда я пытаюсь использовать java.util.UUID как тип поля ID я получаю ошибку из спящего режима при сохранении нового объекта (он пытается установить String тип


Я думаю, вы можете сделать это, установив генератор в native. Я не совсем уверен, как это сделать в спящем режиме, но в NHibernate вы бы сделали что-то подобное в XML:

<id column="PRODUCT_ID">
  <generator class="native"/>
</id>