Проблема с генератором последовательности гибернации Oracle

Я разрабатываю приложение, используя oracle 11g, Java (struts2) и Hibernate.

У меня есть таблица с именем mytemp со столбцом mytemp_id типа NUMBER (22,0).

В моем файле mytemp.hbm.xml идентификатор файла указан ниже.

<id name="mytempId" type="big_decimal">
        <column name="MYTEMP_ID" precision="22" scale="0" />
        <generator class="sequence">
            <param name="sequence">MYTEMP_TEMP_ID_SEQ</param>
        </generator>
    </id>

В моей базе данных Oracle последовательность с именем «MYTEMP_TEMP_ID_SEQ» создана и отлично работает в Oracle.

Теперь, когда я пытаюсь вставить запись, используя спящий режим, я получаю следующую ошибку

org.hibernate.id.IdentifierGenerationException: этот генератор идентификаторов генерирует длинные, целые, короткие или строковые

Кажется, что, поскольку моя последовательность возвращает число, спящий режим рассматривает его как BigDecimal, в то время как класс генератора последовательности спящего режима рассматривает значения, которые являются длинными, целочисленными, короткими и только строковыми.

У Hibernate не должно быть проблем с BigDecimal. Но я думаю, что они не реализовали BigDecimal для генератора последовательности

Может ли кто-нибудь помочь мне решить проблему?

Спасибо.


person amar4kintu    schedule 14.08.2009    source источник


Ответы (3)


Честно говоря, я не могу себе представить, почему вы настаиваете на том, чтобы ваш идентификатор был BigDecimal, а не длинным. Максимальное длинное значение – 9,223,372,036,854,775,807, что, хотя, по общему признанию, составляет примерно одну тысячную от максимального значения NUMBER(22), на самом деле должно быть достаточно. Если бы вам нужно было генерировать один миллион идентификаторов каждую секунду, вам пришлось бы делать это в течение 300 000 лет, чтобы исчерпать свою последовательность.

Тем не менее, чтобы сгенерировать ваш идентификатор как BigDecimal, вам нужно будет написать свой собственный генератор. Вы можете сделать это, расширив встроенный в Hibernate SequenceGenerator и переопределив его метод generate(). Вместо вызова IdentifierGeneratorFactory.get(), который поддерживает только long/int/short/String, вы получите значение своей последовательности из набора результатов как BigDecimal.

Затем вам нужно будет объявить свой генератор, указав его полное имя класса:

<generator class="com.mypackage.BigDecimalGenerator">
  <param name="sequence">MYTEMP_TEMP_ID_SEQ</param>
</generator>
person ChssPly76    schedule 15.08.2009
comment
Привет ChssPly76, Спасибо за ваш ответ. Я преобразовал свой спящий режим, чтобы использовать long везде, где есть BigDecimal, чтобы использовать последовательность в спящем режиме. Это решает мою проблему. Я разместил его здесь, чтобы узнать, как я могу расширить класс генератора идентификаторов спящего режима, чтобы использовать bigDecimal для генератора последовательности. Я не понимаю это точно. Но преобразование BigDecimal в long точно решает проблему. Спасибо. - person amar4kintu; 25.08.2009
comment
Я объяснил, как расширить SequenceGenerator в своем ответе выше. Взгляните на его метод generate() — вы в основном скопируете все это и замените IdentifierGeneratorFactory.get() на resultSet.get(), чтобы получить значение BigDecimal. - person ChssPly76; 25.08.2009
comment
Я установил, что все мои поля big_decimal считаются длинными в моем файле генерации гибернации.. так что теперь он работает нормально.. спасибо.. за вашу поддержку.. - person amar4kintu; 29.12.2009

Вы установили правильный диалект? Этого должно быть достаточно, чтобы Hibernate понял результат последовательности.

[EDIT] Проблема в том, что тип вашей последовательности не соответствует типу вашего столбца. Последовательность (согласно сообщению об ошибке Hibernate) может быть преобразована в длинную, целочисленную, короткую или строку, в то время как ваша последовательность возвращает BigDecimal.

Я предлагаю указать тип столбца идентификатора как «длинный», даже если Oracle не знает этот тип. Внутренне Hibernate должен иметь возможность корректно отбрасывать все для всех.

person Aaron Digulla    schedule 14.08.2009
comment
да .. ниже мой диалект ‹property name=hibernate.dialect›org.hibernate.dialect.Oracle10gDialect‹/property› - person amar4kintu; 14.08.2009
comment
В этом случае проблема заключается в типе вашего столбца ID. Смотрите мои правки. - person Aaron Digulla; 14.08.2009

Определенно. Длинного идентификатора должно быть достаточно, учитывая количество уникальных записей, которые он может сгенерировать. Конкретный генератор просто для того, чтобы иметь специальные значения, может иметь тип, отличный от integer, или иметь контроль над значениями типа integer по какой-то причине (может быть, в зависимости от проекта).

Кроме того, генератор зависит от базы данных, как последовательность для оракула, поэтому определение диалекта также имеет значение.

person Yuvaraj V    schedule 04.10.2009