Hibernate с Oracle 11g не работает с генератором "select" - PullRequest
4 голосов
/ 26 ноября 2009

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

Моя база данных: Oracle Database 11g Enterprise Edition, выпуск 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, поскольку оказалось полезным продолжать импортировать данные и сохранять их в течение нескольких месяцев для использования мной и несколькими другими аналитиками.У меня был администратор базы данных, который настраивал таблицы и настраивал свои классы сущностей, чтобы отразить некоторые незначительные изменения в именах полей и типах данных, а также изменил драйвер, детали подключения и т. Д., Но я столкнулся с некоторыми проблемами при генерации первичного ключа.

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

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

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

Например:

@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" с "select""стратегия (http://docs.jboss.org/hibernate/stable/core/reference/en/html/mapping.html#mapping-declaration-id-generator)

например

@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
}

1 Ответ

2 голосов
/ 26 ноября 2009

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

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...