Спящий режим с Oracle 11g не работает с выбранным генератором

Я использую Hibernate 3.2.5 и Hibernate Annotations 3.3.1.GA в качестве поставщика JPA в приложении для загрузки данных. Я настроил Hibernate на использование C3P0 для пула соединений.

Моя база данных: Oracle Database 11g Enterprise Edition Release 11.1.0.7.0 — 64-битная версия

Поскольку для 11g нет встроенного диалекта гибернации, я настроил его для использования

org.hibernate.dialect.Oracle10gDialect

Драйвер JDBC: драйвер Oracle JDBC, версия: 11.2.0.1.0

Приложение загружает некоторые журналы производительности транзакций из мейнфрейма в базу данных Oracle для последующего анализа и составления отчетов. По сути, это пакетное задание, которое отслеживает папку и ждет новый файл, затем считывает его и вставляет в базу данных (в среднем около 4,5 миллионов строк вставляется в день), поэтому я выбрал Hibernate из-за его способности использовать пакетные вставки JDBC, которые после некоторого сравнительного тестирования не так хорошо работает в EclipseLink. Файлы имеют проприетарный двоичный формат, поэтому я не могу использовать более простые инструменты, такие как импорт CSV и т. д.

Первоначально я разработал приложение для использования с MySQL на своей рабочей станции, так как изначально оно предназначалось для однократной задачи анализа, но теперь я хочу перенести его на корпоративную платформу Oracle RAC, поскольку оказалось полезным продолжать импортировать данные и сохранять их. на пару месяцев для использования мной и несколькими другими аналитиками. Я попросил администратора базы данных настроить таблицы и скорректировать классы Entity, чтобы отразить некоторые незначительные изменения в именах полей и типах данных, а также изменить драйвер, сведения о соединении и т. д., но я столкнулся с некоторыми проблемами с генерацией первичного ключа.

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

Администратор базы данных настроил последовательности так, чтобы созданные ими пользователи не могли просматривать их.

Использование типов сгенерированных значений JPA (javax.annotations) не будет работать в любом случае.

eg:

@GeneratedValue(strategy = GenerationType.AUTO)

Это дает SQL:

select hibernate_sequence.nextval from dual

Какие драйверы Oracle выдают исключение с ошибкой:

25/11/2009 11:57:23 AM org.hibernate.util.JDBCExceptionReporter logExceptions
WARNING: SQL Error: 2289, SQLState: 42000
25/11/2009 11:57:23 AM org.hibernate.util.JDBCExceptionReporter logExceptions
SEVERE: ORA-02289: sequence does not exist

Узнав, что я провел некоторое исследование и нашел варианты использования расширений аннотаций Hibernate JPA «GenericGenerator» со стратегией «выбора» (http://docs.jboss.org/hibernate/stable/core/reference/en/html/mapping.html#mapping-declaration-id-generator)

eg

@GeneratedValue(generator="id_anEntity")
@GenericGenerator(name = "id_anEntity",
strategy = "select")

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

25/11/2009 1:40:50 PM org.hibernate.impl.SessionFactoryImpl <init>
INFO: building session factory

и не возвращается.

Я обнаружил, что то же самое произошло, когда я не указал диалект в файле persistence.xml.

Он отлично работает, если я использую стратегию «приращения», хотя это означает, что последовательности затем разбиваются, поскольку значение было увеличено без увеличения последовательности, что далеко от идеала.

«Собственная» стратегия дает тот же результат, что и использование GenerationType.AUTO (ORA-02289: последовательность не существует).

Я не уверен, связано ли это с тем, что я использую неправильную стратегию генерации ключей, или с ошибкой в ​​моей конфигурации, или с ошибкой.

Мы очень ценим любую помощь в том, чтобы заставить работать стратегию «выбрать» или лучшую альтернативу. Я потенциально мог бы вернуться к использованию чистого JDBC с подготовленными операторами и т. д., но это имеет тенденцию становиться немного запутанным, и я предпочитаю подход JPA.

Еще немного информации:

Свойства Persistence.xml:

        <property name="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider"/>
        <property name="hibernate.show_sql" value="true"/>
        <property name="hibernate.c3p0.min_size" value="5"/>
        <property name="hibernate.c3p0.max_size" value="20"/>
        <property name="hibernate.c3p0.timeout" value="1800"/>
        <property name="hibernate.c3p0.max_statements" value="100000"/>
        <property name="hibernate.jdbc.use_get_generated_keys" value="true"/>
        <property name="hibernate.cache.use_query_cache" value="false"/>
        <property name="hibernate.cache.use_second_level_cache" value="false"/>
        <property name="hibernate.order_inserts" value="true"/>
        <property name="hibernate.order_updates" value="true"/>
        <property name="hibernate.connection.username" value="myusername"/>
        <property name="hibernate.connection.driver_class" value="oracle.jdbc.OracleDriver"/>
        <property name="hibernate.connection.password" value="mypassword"/>
        <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect"/>
        <property name="hibernate.connection.url" value="jdbc:oracle:thin:@(DESCRIPTION =
    (ADDRESS      = (PROTOCOL = TCP) (HOST = myoracleserver) (PORT = 1521))
    (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = myservicename))
  )"/>
        <property name="hibernate.jdbc.batch_size" value = "100000" />

Пример объявления поля ID в одном из классов сущностей с использованием аннотаций:

@Entity
@Table(name = "myentity",
catalog = "",
schema = "mydb")
public class myEntity implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @Basic(optional = false)
    @GeneratedValue(generator="id_anEntity")
    @GenericGenerator(name = "id_anEntity",
    strategy = "select")
    @Column(name = "MYENTITYID",
    nullable = false)
    private Integer myEntityID;

   //... other column mappings

    public Integer getMyEntityID() {
        return myEntityID;
    }

    public void setMyEntityID(Integer myEntityID) {
        this. myEntityID = myEntityID;
    }

   //... other getters & setters
}

person mushion22    schedule 25.11.2009    source источник


Ответы (1)


Мне немного непонятно, что вы подразумеваете под «Администратор базы данных настроил последовательности так, чтобы они не были доступны для просмотра пользователями, которых они создали». - значит ли это, что последовательность вам не видна? Почему нет?

Чтобы использовать генератор на основе последовательности, где имя последовательности не является «hibernate_sequence» (которого в реальной жизни никогда не бывает; это просто значение по умолчанию), вам необходимо укажите соответствующий генератор:

@SequenceGenerator(name="myentity_seq", sequenceName="my_sequence")
public class MyEntity {
 ...

 @Id
 @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="myentity_seq")
 private Integer myEntityID;
 ...
}

Стратегия генератора «выбрать» означает, что Hibernate попытается выбрать строку, которую вы только что вставили, используя уникальный ключ (очевидно, кроме PK). У вас есть это определение? Я бы настоятельно предложил вам использовать последовательность.

person ChssPly76    schedule 25.11.2009
comment
да, команда БД скрыла последовательности от пользовательских кодов, которые они мне дали, поэтому не может указать их в спящем режиме. Я полагаю, что мне придется вернуться к ним, чтобы попросить их сделать их видимыми, но в то же время я столкнулся с проблемами зависания при создании EntityManagerFactory, поэтому мне было интересно, есть ли что-то, что я делаю неправильно, в стороне из этого я мог бы выбрать лучший вариант. - person mushion22; 26.11.2009
comment
А, я вижу, хорошо. Я подумал, может быть, у Hibernate есть хитрость, позволяющая использовать getGeneratedKeys через JDBC, поскольку у меня это включено. - person mushion22; 26.11.2009
comment
getGeneratedKeys работает для генератора идентификаторов последовательностей для диалекта Oracle10g; однако это по-прежнему означает, что ваша последовательность должна быть доступна - person ChssPly76; 26.11.2009
comment
Администратор баз данных сказал, что они предпочитают не делать последовательности видимыми для случая, когда кто-то выбирает их помимо вставки, поэтому без необходимости увеличивают последовательность. В итоге я использовал класс, который парень написал здесь forum.hibernate.org/viewtopic. php?f=1&t=973262, который работает хорошо. Я надеялся, что такое поведение Hibernate будет встроено при использовании getGeneratedKeys. - person mushion22; 27.11.2009
comment
Вы все рассмотрели запрос на улучшение Hibernate для поддержки этого? На самом деле это небольшая вариация идентичности последовательности, и на самом деле ее довольно просто поддерживать. Тем не менее, он поставляется с обычными предупреждениями против использования стратегий идентификаторов, сгенерированных вставками. - person Steve Ebersole; 25.05.2012
comment
Этот ответ сделал это для меня. Однако мне не нужно было иметь SequenceGenerator на уровне класса. Хотя у меня была та же проблема, что и у mushion22, у меня также была задействована схема (оракул), поэтому я использовал: @SequenceGenerator(name = the_seq, sequenceName = ACMDB.INSP_HDR_SEQ) - person markthegrea; 28.08.2012