# [Hibernate] Intelligenter Hibernate Join



## ilumin (11. Sep 2007)

Hallo,

mein erster Post und gleich eine Frage.. 

ich migriere derzeit eine altgediente Anwendung von einer Client Applikation
hin zu einer Webanwendung mit Spring MVC und Hibernate. Dazu existiert
eine Oracle Datenbank welche in ihrer Struktur nicht angepasst (wenn nur minimal)
werden soll. 

Wir haben verschiedene Benutzer deren Benutzer id in jeder Tabelle
bei jedem Datensatz mit geschrieben wird (feld user_Id). Wir haben eine Tabelle 
bezeichnungen und eine Tabelle bezeichnungstexte welche einen dreiteiligen
primärschlüssel hat: bezeichnungs_id, sprache, user_id

Es existiert ein default user (id 1) welchem alle bezeichnungstexte zugeordnet sind.
Dieser default userhält die default bezeichnungstexte. wenn ein user einen eigenen
bezeichnungstext für eine Position erstellt dann soll automatisch dieser verwendet werden
und nicht der default bezeichnungstext.

in hibernate habe ich beispielsweise folgende selects:


```
select
  p.wert,
  p.prozent,
  b.text
from
  Position p
  join p.bezeichnung.bezeichnungstext b (<-- knackpunkt)
where
  p.user.id = 213
```

(nur schematisch / exemplarisch dargestellt)

jetzt möchte ich durch Hibernate Mechanismen, AOP oder sonst
irgendwie den join zum Bezeichnungstext so haben dass er mir 
den default bezeichnungstext (user_id = 1) liefert wenn
kein bezeichnungstext mit einer user_id = 213 vorliegt.

überlegungen wären bisher ob wir keine joins mehr nehmen sondern 
nur die bezeichnungs-id's und später die resultsets durch eine 
methode jagen welche die entsprechenden bezeichnungen aus der
Datenbank holt (wär mir persönlich unrecht, fühlt sich nicht "straight forward" an).

Gibts sowas wie intelligentes Mapping (schwer zu beschreiben) bzw.
konditionales Mapping? Intelligente Stellvertreter Objekte über die ich joine
anstatt die automatisch von Hibernate generierten (eclipse hibernate tools)
und mir diese Bedingung prüfen / abfangen / erfüllen (wenn ja wie)?

schwer zu erklären ich hoffe es wird klar und jemand hat mir hier den
entscheidenden Tip...

bitte um hilfe, alle alternativen gern gesehen!

Grüße,

Pascal


----------



## ms (11. Sep 2007)

Wie würdest du es denn mit plain SQL machen?
Mir fällt auf die schnelle nur eine CASE-Anweisung ein.

ms


----------



## ilumin (11. Sep 2007)

z.b. ein subselect für die bezeichnungstexte. naja ich hatte einfach gehofft dass mir hibernate hier "elegantere" möglichkeiten bietet. 
bzw. ich wäre schon glücklich wenn ich es mit hibernate überhaupt (!) irgendwie hinbekommen würde. gern auch mit nem interceptor also über aop oder sonstwie.


----------



## ms (11. Sep 2007)

Sofern ich das richtig verstanden habe scheint mir diese Aufgabenstellung einfach zu trivial mit normalen Mitteln lösbar zu sein, als mit AOP, Interceptoren, usw...
Was spricht denn gegen ein Subselect oder eine Case-Anweisung?

ms


----------



## ilumin (11. Sep 2007)

dass ich jeden der x-hundert querys durchgehen und anpassen müsste. ich möchte ungern sql (oder fast sql) schreiben wenn ich schon etwas wie hibernate einsetze. natrülich komme ich irgendwie an die richtigen bezeichnungstexte, allerdings eben überall von hand mit nem subselect. 

Wünschenswert wäre es einfach wenn ich mir hibernate so schlau machen könnte dass es mir automatisch bei einem join auf die bezeichnungstexte die richtigen bezeichnungstexte liefert ohne dass ich in jeden query case oder subselects reinbringe.


----------



## ms (11. Sep 2007)

Wie willst du auf Hibernate umstellen, wenn du die vorhandenen SQL-Queries nicht angreifst?

Wenn es nicht zuviel ist dann poste doch mal bitte deine gemappten Klassen (also nur die für diesen Teil relevanten), die Mappingfiles sowie ein oder zwei vorhandene Select-Statements wo das bisher schon funktioniert.

ms


----------



## ilumin (11. Sep 2007)

wir haben bereits auf hibernate umgestellt. Die applikation ist lauffähig und nahezu produktiv. es geht hier um weitere features die wir in die anwendung nachträglich einfügen wollen, wie z.b. die möglichkeit bezeichnungstexte zu customisen. meine Fragestellung hier bezieht sich nicht auf die migration der anwendung (das warn nur hintergrund infos) sondern um das anpassen der migrierten version, dem webclient welcher bereits vollständig in spring und hibernate implementiert ist.

die sql statements der alten applikation sind irrelevant da wir die neue applikation nur auf der alten Datenbasis, nicht aber der Codebasis aufgebaut haben also from scratch. In der alten Applikation existiert keine mehrbenutzerfähigkeit ergo auch keine user_id's. Im Moment holen wir über einen join einfach die entsprechenden bezeichnungstexte wollen hier allerdings nun die möglichkeit bieten eigene bezeichnungstexte anzulegen und das möglichst ohne jeden einzelnen query erneut anfassen zu müssen (hql query, nicht sql query).

evtl drücke ich mich einfach nicht klar genug aus


----------



## ms (11. Sep 2007)

Sind die Model-Klassen schon für die Texte refactored worden?

ms


----------



## ilumin (11. Sep 2007)

ja, durch die eclipse hibernate tools ging das nahezu automatisch. ist allerdings schon ne ecke her da wir das ganz zu Beginn der Entwicklung gemacht haben. Das sind hier einfache, "dumme" Pojo's mit Atributen und entsprechenden Gettern und Settern dazu. mehr nicht.


----------



## ms (11. Sep 2007)

Mehr brauchts ja auch nicht sein.
Kannst du mal so ein Pojo posten?
Möchte gerne die Relationen zu den Texten sehen.

ms


----------



## ilumin (11. Sep 2007)

Hilft das so?


```
// Faelligkeit.java:
   private Bezeichnung	pefBezeichnungen;

// Bezeichnung.java:
   private Set		pefBeztextes				= new HashSet( 0 );

// Beztext.java:
   private BeztextId	id;
   private String		bezeichnung;

// BeztextId.java:
   private Bezeichnung	pefBezeichnungen;
   private String		sprache;
   private User gvaUser;

// User.java
  private Long id;
```


Faelligkeit -> Bezeichnung -> Beztext -> BeztextId -> User


----------



## ms (11. Sep 2007)

```
// Bezeichnung.java:
   private Set		pefBeztextes				= new HashSet( 0 );
```
Ist das ein Set von BeztextId's?

ms


----------



## ilumin (11. Sep 2007)

nein von Beztext's (schreckliche Namensgebung ich weiß  )


----------



## KSG9|sebastian (11. Sep 2007)

Warum lagerst du die Logik um den richtigen Satz zu ermitteln nicht in eine StoredProcedure aus?
Ansonsten bleibt wohl nur 
a) Subselect
b) Case
c) per AOP in die Ausführung des Querys eingreifen und den Query manipulieren.

Wobei ich mir nicht vorstellen kann wie man das sinnvoll mit AOP lösen könnte, da die Querys ja immer unterschiedlich sind.
Das du machen könntest wäre mit AOP einzugreifen und wenn kein Ergebniss kommt (weil nichts für user_id xyz hinerlegt ist) denselben Query mit einer anderes user_id nochmal aufrufen.


----------



## ms (12. Sep 2007)

Gibt es den DefaultUser nur um die Default-Texte zuzuordnen?
Wenn dem so ist, dann halte ich schon das Modell für nicht ganz praktisch.
Den Standardtext hätte ich unabhängig von einem User definiert, also z.B. eine Klasse Standardtext.
Und einen Benutzerabhängigen Text hätte ich von dieser Klasse abgeleitet, z.B. Benutzertext. Diese Klasse hätte zusätzlich noch ein Userobjekt verknüpft.
Damit stellt sich dann nicht das Problem bei der Abfrage nach dem richtigen Text.
Es müsste nur sichergestellt werden, dass beim Erzeugen einer Faelligkeit die Standardtexte zugeordnet sind.

ms


----------



## ilumine (12. Sep 2007)

ms dein Ansatz klingt plausibel. ich werde das mal so umsetzen und schaun ob uns das weiter bringt. danke fürs erste!


----------

