HibernateMapping

D

dcasdererwe

Gast
Hallo,
ich habe folgende Datenbankstruktur. Für jedes Gerät gibt es eine Tabelle in der die zugehörigen Messwerte geloggt werden:

Tabelle "GeräteID1"
---> Messwert 1, Datum 1, .....
---> Messwert 2, Datum2, ......


Tabelle "GeräteID2"
---> Messwert 1, Datum 1, .....
---> Messwert 2, Datum2, ......


Ich habe mir jetzt über reverse engineering das mappingfile und das POJO von der Tabelle "GeräteID1" erzeugt und kann nun Messwerte für Gerät 1 lesen und schreiben.
Wie kann ich das mappingfile / pojo verändern, um mit folgendem Aufruf Messwerte zu speichern?
Java:
 session.save(new Messwert ("GeräteID", "Messwert1234", new Date(), ........));
 tx.commit();
Hibernate soll die Werte automatisch in die richtige Tabelle schreiben, falls Tabelle nicht vorhanden, soll sie nach dem Muster von "GeräteID1" erzeugt werden.



Einen zweiten Fehler habe ich noch bei der Anbindung an Postgres 9.1. Hibernate vergisst die Anführungszeichen um die Spaltennamen.
Meine hibernate.cfg.xml für Postgres:
Java:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <property name="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</property>
        <property name="hibernate.connection.driver_class">org.postgresql.Driver</property>
        <property name="hibernate.connection.url">jdbc:postgresql://localhost:5432/tabellenname</property>
        <property name="hibernate.connection.username">xxxxxxx</property>
        <property name="hibernate.connection.password">xxxxxxx</property>
         <!-- Enable Hibernate's automatic session context management -->
        <property name="current_session_context_class">thread</property>
        <property name="hibernate.query.factory_class">org.hibernate.hql.classic.ClassicQueryTranslatorFactory</property>
        <property name="show_sql">true</property>
        <mapping resource="javaapplication1/Log.hbm.xml"/>
    </session-factory>
</hibernate-configuration>

Das erzeugte SQL-Statement:
Java:
insert into public.log (Messwert, Datum, ........)  values (?,?,.......)

Durch die fehlenden "" kommt es zur Fehlerausgabe:
Java:
Schwerwiegend: FEHLER: Spalte »messwert« von Relation »log« existiert nicht


VIELEN DANK FÜR EURE HILFE :)
 
N

nillehammer

Gast
So wie Du es Dir vorstellst, anhand der übergebenen Geräte-ID quasi dynamisch die richtige Tabelle zu finden, wird von Hibernate nicht unterstützt. Aus dem Dilemma siehe ich drei mögliche Auswege:
  • Du schreibst Dir eine DAO-Methode, die das entsprechend flexibel handhabt
  • Du schreibst eine abstrakte Klasse Geraet (MappedSuberclass) und leitest von dieser Klasse Geraet1, Geraet2 etc ab. Die abgeleiteten Klassen (Entity) kannst du dann 1 zu 1 auf die DB-Tabelle mappen.
  • Du machst Dir Gedanken über Dein Datenmodell. Es scheint mir keine gute Idee, für jedes Gerät eine extra Tabelle zu nehmen. Ich würde eher eine Tabelle Geraet sehen, die die Daten aller Geräte aufnimmt. Und dann eine Tabelle Messwert. Diese nimmt alle Messwerte auf und hat einen Fremdschlüssel zu Geraet. Dann kannst Du über OneToMany/ManyToOne so mappen, wie es dich gehört.
 
Zuletzt bearbeitet von einem Moderator:
D

dcasdererwe

Gast
  • Es scheint mir keine gute Idee, für jedes Gerät eine extra Tabelle zu nehmen. Ich würde eher eine Tabelle Geraet sehen, die die Daten aller Geräte aufnimmt. Und dann eine Tabelle Messwert. Diese nimmt alle Messwerte auf und hat einen Fremdschlüssel zu Geraet. Dann kannst Du über OneToMany/ManyToOne so mappen, wie es dich gehört.

Vielen Dank für die schnelle Antwort. Die Struktur ist "historisch gewachsen". Ich persönlich würde auch nur eine Tabelle "Gerät" machen, aber wird nicht gewünscht ;)
 
D

dcasdererwe

Gast
Eventuell hat es auch den Grund, dass die Abfragen durch das Vorselektieren schneller laufen. In einer Gerätetabelle liegen nicht nur 3 Messwerte ;-)
 
N

nillehammer

Gast
dcasdererwe hat gesagt.:
Die Struktur ist "historisch gewachsen". Ich persönlich würde auch nur eine Tabelle "Gerät" machen, aber wird nicht gewünscht
Hab ich mir gedacht, deswegen hatte ich noch zwei andere Alternativen hingeschrieben. Ich würde dann an Deiner Stelle die zweite umsetzen.
 
N

nillehammer

Gast
Eventuell hat es auch den Grund, dass die Abfragen durch das Vorselektieren schneller laufen. In einer Gerätetabelle liegen nicht nur 3 Messwerte
Das bezweifle ich. Eine Abfrage mit einem einzigen INNER JOIN auf die GeräteId wird vom DBMS schnell genug abgearbeitet. Dies ist kein Grund für eine De-Normalisierung.
 
D

dcasdererwe

Gast
Das bezweifle ich. Eine Abfrage mit einem einzigen INNER JOIN auf die GeräteId wird vom DBMS schnell genug abgearbeitet. Dies ist kein Grund für eine De-Normalisierung.
Das werde ich morgen mal mit ein paar Abfragen testen, wie sich das auf die Laufzeit auswirkt. Wenn sie nicht signifikant ansteigt, werde ich alles in eine Tabelle schreiben.


Ich hänge immernoch an dem Postgres-Problem fest (mit den anderen DB-Typen funktioniert es).
Java:
select messwert from geraetID1
schlägt fehl mit
Java:
********** Fehler **********

FEHLER: Spalte »messwert« existiert nicht
SQL Status:42703
Zeichen:8

Es funktioniert nur über
Java:
select "Messwert" from geraetID1
aber Hibernate formatiert die Abfrage falsch. Hab mich jetzt durch diverse Foren gelesen, aber keine zielführende Antwort in bezug auf Hibernate gefunden.
 
N

nillehammer

Gast
select "Messwert" from geraetID1
Dass man bei Queries die Namen der anzuzeigenden Spalten in Hochkommas setzen muss, hab ich noch nie gehört. Ich glaube nicht, dass das nötig ist. Was aber sein kann ist, dass Postgres die Spaltennamen case-sensitive auswertet, sprich, dass Groß-/Klein-Schreibung zu beachten ist. Da hilft Dir ein @Column(name="Messwert") über dem getter oder der Instanzvariablen.
 
D

dcasdererwe

Gast
Vielen vielen Dank! case-sensitive war genau das Stichwort was mir gefehlt hat!
Keine Lust da mit Anotations rumzuwerkeln. Habe einfach ne neue DB angelegt, die hbm.xml um die Spalte "DeviceID" erweitert und Hibernate die Tabelle "Messwerte" erzeugen lassen.
Habe grad mal hochgerechnet, wird interessant mit der Laufzeit wenn man mal nen Select absetzt, da es ein paar mrd Datensätze werden.
 

Nogothrim

Aktives Mitglied
eigentlich schreibt postgres gerne alles klein und ist eher nicht case-sensitive bei Spalten und Tabellennamen, vielleicht irgendwas am db server komisch eingestellt? Habe allerdings keine Ahnung was diese ClassicQueryTranslatorFactory macht, vielleicht verbiegt die irgendwas. Ich kenne Hibernate nur über JPA.
 
D

dcasdererwe

Gast
Das bezweifle ich. Eine Abfrage mit einem einzigen INNER JOIN auf die GeräteId wird vom DBMS schnell genug abgearbeitet. Dies ist kein Grund für eine De-Normalisierung.
Bei mio. oder gar mrd. Datensätzen dauert das aber ne Weile.
Extremfall:
100 Geräte. 100mio Datensätze. Gerät 5 hat nur 100 Datensätze.
Ich möchte die Werte in Spalte xy von Gerät 5 aufsummieren.

Habe gerade "nur" mit ca 10mio Datensätzen getestet. Dauert 2-5 Sekunden.
 

Neue Themen


Oben