2009-11-25 4 views
4

J'utilise Hibernate 3.2.5 et Hibernate Annotations 3.3.1.GA comme fournisseur JPA dans une application de chargement de données. J'ai configuré Hibernate pour utiliser C3P0 pour le regroupement de connexions.Hibernation avec Oracle 11g ne fonctionne pas avec le générateur "select"

Ma base de données est: Oracle Database 11g Enterprise Edition de presse 11.1.0.7.0 - 64bit production

Comme il n'y a pas construit en dialecte veille prolongée pour 11g, donc je l'ai configuré pour utiliser

org.hibernate.dialect.Oracle10gDialect 

Pilote JDBC: pilote JDBC Oracle, version: 11.2.0.1.0

L'application charge certains journaux de performances de transaction d'un système mainframe dans une base de données Oracle pour analyse et création de rapports ultérieurs. Il s'agit essentiellement d'un travail batch qui surveille un dossier et attend un nouveau fichier puis le lit et l'insère dans la base de données (en moyenne 4,5 millions de lignes insérées par jour), j'ai donc choisi Hibernate pour sa capacité à utiliser des insertions batch JDBC semble ne pas fonctionner si bien dans EclipseLink après quelques tests de comparaison. Les fichiers sont dans un format binaire propriétaire donc je ne peux pas utiliser des outils plus simples tels que les importations CSV.

A l'origine, j'ai développé l'application pour MySQL sur mon poste de travail comme c'était initialement le cas pour une tâche d'analyse. pour le déplacer vers une plate-forme Oracle RAC d'entreprise, car il s'est avéré utile de continuer à importer des données et de les conserver pendant quelques mois pour une utilisation par moi-même et quelques autres analystes. J'ai eu un DBA configurer les tables et avoir ajusté mes classes Entity pour refléter quelques changements mineurs dans les noms de champs et les types de données et changé les détails du pilote et de la connexion etc, mais j'ai rencontré quelques problèmes avec la génération de clé primaire.

Il y a quelques tables (tableau de données principal avec quelques tables stockant différents types de support, par exemple le type de transaction, les usercodes, etc.). Chacun a une colonne d'identifiant unique (primaire) qui est générée automatiquement en utilisant une séquence et un déclencheur de mise à jour avant.

L'administrateur de base de données a configuré les séquences pour qu'elles ne soient pas visibles par les utilisateurs qu'elles ont créés. L'utilisation des types de valeur générés par JPA (javax.annotations) ne fonctionnerait pas dans tous les cas.

par exemple:

@GeneratedValue(strategy = GenerationType.AUTO) 

Cela donne le SQL:

select hibernate_sequence.nextval from dual 

que les pilotes Oracle renvoie une exception pour l'erreur:

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 

Après avoir constaté que je l'ai fait quelques-uns recherche et trouvé les options pour utiliser les extensions d'annotation Hibernate JPA "GenericGenerator" avec un "select" str atégie (http://docs.jboss.org/hibernate/stable/core/reference/en/html/mapping.html#mapping-declaration-id-generator)

par exemple

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

Cependant quand j'utilise ce que je trouve Hibernate se bloque lors de la création EntityManagerFactory. Il semble avoir passé la construction des propriétés, la construction des requêtes nommées, la connexion au serveur, puis se bloque à:

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

et ne revient pas.

J'ai trouvé la même chose lorsque je n'ai pas spécifié le dialecte dans le fichier persistence.xml.

Cela fonctionne très bien si j'utilise la stratégie "increment", bien que cela signifie que les séquences sont ensuite rompues lorsque la valeur a été incrémentée sans que la séquence ait été incrémentée, ce qui est moins qu'idéal.

La stratégie "native" donne le même résultat que l'utilisation de GenerationType.AUTO (ORA-02289: la séquence n'existe pas). Je ne suis pas sûr si cela est dû à moi en utilisant la mauvaise stratégie de génération de clé, ou une erreur dans ma configuration, ou un bug.

Toute aide pour faire fonctionner la stratégie "select", ou une meilleure alternative est très appréciée. Je pourrais potentiellement revenir à l'utilisation pure JDBC avec des déclarations préparées et autres, mais cela a tendance à être un peu brouillon et je préfère l'approche JPA.

Quelques infos:

propriétés 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" /> 

Un échantillon de la déclaration du champ d'identification dans l'une des classes d'entités utilisant des annotations:

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

Répondre

2

I Je ne sais pas très bien ce que vous entendez par "Le DBA a configuré les séquences pour qu'elles ne soient pas visibles par les utilisateurs qu'elles ont créés". - Est-ce que cela signifie que la séquence ne vous est pas visible? Pourquoi pas?

Pour générateur à base de séquence utiliser où le nom de séquence n'est pas « hibernate_sequence » (ce qui ne l'est jamais dans la vraie vie, c'est juste la valeur par défaut), vous devez specify the appropriate generator:

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

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

générateur «sélectionnez » stratégie signifie que Hibernate va essayer de sélectionner la ligne que vous venez d'insérer en utilisant une clé unique (autre que PK, évidemment). Avez-vous défini cela? Je voudrais fortement vous suggérons d'aller avec la séquence à la place.

+0

oui l'équipe DB a rendu les séquences cachées des codes utilisateur qu'elles m'ont donnés, donc ne peut pas les spécifier en hibernation. Je pense que je vais devoir revenir vers eux pour leur demander de les rendre visibles, mais en même temps je suis tombé sur les problèmes d'accrochage pendant la construction de l'EntityManagerFactory, je me suis donc demandé s'il y avait quelque chose , à part ça, je pourrais choisir une meilleure option. – mushion22

+0

Ah je vois bien. Je pensais que Hibernate avait peut-être un truc pour utiliser getGeneratedKeys via JDBC vu que j'ai activé. – mushion22

+0

getGeneratedKeys fonctionne pour le générateur de "séquence-identité" pour le dialecte Oracle10g; cependant, cela signifie que vous devez avoir votre séquence accessible. – ChssPly76

Questions connexes