# SQL Anfragen auslagern+Transaktionen



## Guest (4. Mrz 2008)

Hallo,

Erhoffe mir ein paar Tipps zu folgendem Problem:

Habe ein mittelgroßes Projekt (knapp 20k Zeilen Code) das ich aus verschiedenen Gründen derzeit gründlich überarbeite inklusive Refactoring. Gespeichert wird in einer MySQL-Datenbank (Zugriff über JDBC).
Es gibt nur 5 oder 6 Klassen deren Daten in die Datenbank gespeichert werden (je 1-4 Querys, die Klassen kümmern sich derzeit selbst um das speichern), aber aus performance (aber auch funktionalen) Gründen werden auch im restlichen Programm immer mehr SQL-Querys verwendet.
Derzeit werden noch keinen Transaktionen benutzt was zu kleineren Dateninkonsistenzen führen könnte.
Ich verwende eine selbst geschriebene Datenbank-Klasse welche SQL-Anfragen ausführt (sprich sich darum kümmert das eine Datenbankverbindung besteht, ggf. auch zusätzlich eine SSH-Verbindung zum Server, dann das Statement an die Datenbank absetzt) Das Vorgehen ist bsiher sehr beschränkt, man ruft im wesentlichen entweder "executeUpdate(String query)" oder "getPreparedStatement()" mit anschließendem "executePreparedStatement(PreparedStatement statement)" auf.

Was mir nicht gefällt:
a) SQL-Code überall im Projekt
b) Keine Transaktionen möglich da die Datenbank-Klasse nicht weiß welche Transaktionen zusammengehören
c) Die Datenbank-Klasse muss ich jeder Klasse per Konstruktor mitgeben oder als Parameter bei nur von extern aufgerufenen Methoden, aufgrund der Hierachie muss ich desshalb teilweise Daten die Datenbank-Klasse mitgeben die sie selbst gar nicht brauchen sondern nur weitergeben
d) Meine 5-6 Datenklassen sind zu mächtig, die sollen abgespeckt werden da sie mittlerweile weitaus mehr Code zum speichern und laden sowie sonstige Zwecke enthalten (z.B. getPrintedLabel() welches ein Label mit allen Druckdaten zurükliefert, recieveParcelStatus() welches die Paketdaten aus dem internet abruft usw.) als eigentliche Daten. Ich denke darüber nach diese zu reinen Datenklassen zu machen, aber wohin lagert man die bisherigen Methoden aus?
e) Zuverlässigkeit und Logging: Da die Abhängigkeit vom Programm immer größer wird und mehr und mehr kritische Bereiche hinzukommen bei denen Fehler ernste Konsequenzen haben muss die zuverlässigkeit möglichst hoch sein und ein Logging eingeführt werden damit Fehler schneller behoben werden können und die Daten eventuell korrigiert werden können. Logging könnte z.B. mit log4j erfolgen, aber da habe ich ja dasselbe Problem wie bei den SQL-Querys=> überall im ganzen Programm verteilt!
Bisher ist die Zuverlässigkeit deutlich zu kurz gekommen, das muss sich ändern

Bin noch Student (Diplom Informatik) und habe schon viel während der Programmierung dieses Projektes gelernt, aber immer nur Try&Error ist doof :wink: daher würde ich mich über ein paar Tipps freuen.

Über Hibernate hab ich schon einiges gelesen und mich informiert, was mir aber nicht ganz klar ist ob dies auch für die überall verteilten SQL-Abfragen (welche nichts mit laden oder speichern von daten zur Objektertsellung zu tun haben) einen sinnvollen Ansatz darstellen kann. Solch eine Abfrage enthält z.B. die Anweisung alle Rechnungsnummern zu liefern die Artikel x enthalten oder alle Rechnungen von einem Kunden mit dem Namen xy oder den zur Rechnung gehörigen Auftrag bzw. umgekehrt oder alle Paketnummern die zu einem Auftrag gedruckt wurden usw.


Wie gesagt, würde mich über ein paar Tipps freuen!


----------



## Gelöschtes Mitglied 5909 (4. Mrz 2008)

DB: Ibatis -> SQL ausgelagert
Logging: eventuell Log4j + aspectj


----------



## Guest (5. Mrz 2008)

Anonymous hat gesagt.:
			
		

> Hallo,
> 
> Ich verwende eine selbst geschriebene Datenbank-Klasse welche SQL-Anfragen ausführt (sprich sich darum kümmert das eine Datenbankverbindung besteht, ggf. auch zusätzlich eine SSH-Verbindung zum Server, dann das Statement an die Datenbank absetzt) Das Vorgehen ist bsiher sehr beschränkt, man ruft im wesentlichen entweder "executeUpdate(String query)" oder "getPreparedStatement()" mit anschließendem "executePreparedStatement(PreparedStatement statement)" auf.
> 
> c) Die Datenbank-Klasse muss ich jeder Klasse per Konstruktor mitgeben oder als Parameter bei nur von extern aufgerufenen Methoden, aufgrund der Hierachie muss ich desshalb teilweise Daten die Datenbank-Klasse mitgeben die sie selbst gar nicht brauchen sondern nur weitergeben



Wenn Threadsicherheit hier keine Rolle spielt, könnte man die Datenbank-Klasse als Singleton entwerfen, bzw. auf statische Methoden setzen. Dann würde schonmal c entfallen.


----------



## SnooP (5. Mrz 2008)

zu c) - korrekt. Aber die DB-Klasse sollte an sich schon thread-sicher sein, sprich zustandslos - dann gibt's auch keine Probleme mit Singletons.

zu dem SQL-Kram. Benutz einfach Hibernate und insb. schau dir das DAO-Pattern an. Sämtliche Anfragen/Queries an die DB sollten in den DAOs ausgelagert werden - dann hast du nicht mehr das Gefühl, das alles zerstreut ist. Denn selbst mit Hibernate hat man trotz hübschem Mapping sehr häufig zusätzlich die Anforderung bestimmte "spezielle" Abfragen an deine Tabellen machen zu müssen. Das kann man dort sehr hübsch via HQL oder Criteria-API machen. Letzteres halt eine programmatische Variante und insb. beim Filtern von Datenbeständen prima, weil man dadurch sehr viel schöner einzelne Filter-Parameter an und abschalten kann, als via SQL oder HQL-Strings (Stichwort StringBuffer.append...würg).
Das Behandeln von StoredProcedures ist mit Hibernate nicht ganz so prima... da soll z.B. das oben vorgeschlagene iBatis besser sein - falls du also SPs würd ich da weiter evaluieren.

Für Transaktionen würde ich mir Spring anschauen - das würde dem ganzen insg. rein architektonisch auch gut tun und die Einbindung von Hibernate via Spring ist sehr hübsch - man muss eindeutig weniger machen und genau das will man ja. Außerdem kann man dank AOP bzw. Interceptorn in Spring auch dein Logging-Problem ein wenig in den Griff bekommen... wenn du also ein durchgängiges Logging diverser Methoden benötigst, musst du nicht in jeder Methode ständig den Logger aufrufen... bei Spezial-Logging brauchst du das natürlich trotzdem - aber für das normale "Tracing" gehts auch generisch.


----------



## quippy (5. Mrz 2008)

Anonymous hat gesagt.:
			
		

> b) Keine Transaktionen möglich da die Datenbank-Klasse nicht weiß welche Transaktionen zusammengehören



Das könntest Du ihr beibringen, und zwar z.B. so, daß Du der DB-Klasse drei Methoden spendierst:

a) Methode "startTransaktion" zum Einleiten einer Transaktion, Ergebnis ist ein Handle (wie damals bei Dateien, irgendwas eindeutiges, so daß man weiß, was zu einer Transaktion gehört), dahinter verbirgt sich die JDBC-Connection, Ablage in z.B. einer HashMap - oder das Handle ist selbst der Container für die Connection, was eine Speicherung in der DB-Klasse dann unnötig macht. Der Connetcion dann noch ein "setAutocommit(false)" oder wie das hieß, und du kannst damit Transaktionen machen.

b) eine commitTransaktion(handle)-Methode zum positiven Abschluss

c) eine rollback(handle)-Methode bei Fehler

Dann mußt Du deiner Klasse allerdings auch immer schön das Handle mitgeben, wenn inserts, updates, deletes ausgeführt werden. Um abwärtskompatibel zu bleiben, könnten das Handle null sein, was heißt, man will keine Transaktion. Entsprechend dem Polymorphismus-Gedanken kannst Du die alten Methodensignaturen dann behalten, welche dann an die mit Transaktions-Handle delegieren.
Also so:

```
/**
 * Alte Methode delegiert
 */
public void updateFrom(Object o)
{
   updateFrom(null, o);
}
/**
 * Neue Methode mit Transaktions-Handle
 */
public void updateFrom(Handle h, Object o)
{
   // Voodoo
   Statement stmt = (h==null)?createConnection().createStatement():h.getConnection().createStatement(); // oder so...
}
```

Solltest Du nun allerdings ein Datenbankframework einsetzen, mußt Du diese Änderung nicht mehr durchführen - die sollten dafür techniken zur Verfügung stellen.


----------



## Guest (7. Mrz 2008)

Oh man oh man, hab den Eindruck in eine nie endende Spirale aus immer mehr Fachbegriffen, weiteren Frameworks, Patterns etc. zu geraten sobald ich mich im Enterprise-Bereich versuche zu orientieren  :### 
Je mehr man liest desto mehr Fragen hat man  ???:L 

Irgendwie wird mir auch immer klarer das ich die derzeitige Anwendung mehr oder weniger von Grund auf neu schreiben sollte, viele Bereiche wollte ich sowieso überarbeiten und bei Einführung von Hibernate und Logging bleibt wohl nicht mehr viel sinnvolles vom ursprünglichen Code übrig. Das gibt mir dann auch viele neue Freiheiten da ich dann komplett frei vom alten Design bin. Ist zwar schade um das bisherige Projekt da es mich das gesamte Studium über begleitet hat und ich wirklich sehr viel dabei gelernt habe :? Aber jetzt neigt sich das Studium dem Ende zu und es ist denke ich sinnvoll auch mal wieder über den Tellerand hinauszuschauen und Richtung Enterprise zu gehen, schließlich will ich später auch einen Job als Anwendungsprogrammierer.

Habe einige Fragen, aber zuerst ein paar Informationen zum Projekt:
-*Einsatzgebiet ist ein kleines Handelsunternehmen* (hauptsächlich E-Commerce)
-Ziel ist es letztendlich ein weitgehend komplettes *ERP-System* zu erschaffen, aber entsprechend des Einsatzgebietes beschränkt (wie gesagt *kleines* Handelsunternehmen)
Das heißt: Kundenverwaltung, Auftragsverwaltung, Rechnungen, Pakete (Packlisten, Versandetiketten drucken, Anbindung an Versanddienstleister wie DHL), Zahlungsverwaltung, Warenwirtschaft, Statsitktools (allgemein wie z.B. Umsatzentwicklung, spezieller auch sowas wie Rentabilität einzelner Artikel etc.), später eventuell auch Richtung Buchhaltung. weitere Stichwörter: Lagerverwaltung, permanente Inventur, Ausstattung der Waren mit Barcodes, Verwaltung der Daten des Online-Shops (Einpfegen neuer Artikeln,  teilweise auch automatischer Import aus Herstellerkatalogen in diversen Formaten etc.)
-Online-Shop ist *OSCommerce*, demnächst eventuell *XTCommerce*. Hier gibts Einschränkungen da das Shopsystem *nicht bei uns gehostet* ist, an der Datenbankstruktur kann auch nicht viel geändert werden da sonst das Shopsystem massiv modifiziert werden müsste. Verbindung zur Shopdatenbank erfolgt über eine *SSH-Verbindung*
-Budget für Hardware ist sehr gering (maximal ein "fetter" (Dualcore/Quadcore, 4GB RAM) Desktop-PC als Server denkbar inkl. RAID 1+Backup, kleinere Client-PCs nach Bedarf (Singlecore/kleine Dualcores, 1GB RAM)), Softwareentwicklung erfolgt nur durch mich alleine
-Bisher FAT-Client Konzept (Software bisher auf 2 PCs installiert, einer davon beherbergt zusätzlich die MySQL-Datenbank)
-*bis auf den Online-Shop wird die gesamte Software wird innerhalb eines Intrants eingesetzt*
-Später: 1 Server, bis zu 3 PCs im Büro/Buchhaltung/Reklamationsabteilung etc., bis zu 3 PCs im Lager (an Packstation(en), für manuelle Entnahmen von Material und Einbuchung von Materialeingang), also sagen wir mal *maximal 5-6 Personen arbeiten am System zur gleichen Zeit* (wenn auch teilweise in unterschiedlichen Bereichen), sprich Performance sollte daher eigentlich nicht so schnell zum Problem werden


Das ganze soll nach und nach entwickelt werden und so das laufende System Schritt für Schritt erweitert werden, das System muss also gut wartbar sein. Das bisherige Fat-Client Konzeot scheint mir dafür nicht ideal.


*Jetzt zu meinen Fragen:*
1) Spring+Hibernate ok für diesen Zweck? Oder muss es JavaEE/EJB sein?
2) Thin-Client/SmartClient? Weiß nicht so recht wo man da die Grenze ziehen soll zwischen Server und Client und wie man das implementieren kann. Die Clients sollten imho eine Swing-GUI haben und nicht im Browser laufen, aber kommt wirklich nur die GUI auf den Client und die gesamte Logik bei z.B. Button-Klicks liegt auf dem Server? Wie findet die Kommunikation zwischen Client und Server statt? RMI?


*gäähn* schon ziemlich spät und Posting ist auch lang genug den ich  :wink:
Freu mich auf eure Antworten!


----------



## maki (7. Mrz 2008)

Für ein Projekt dieser Größe würde ich zu iBatis greifen, ist besser für kleinere Projekte mit weniger Tabellen/Abfragen geeignet.

iBatis trennt SQL von Java (SQL befindet sich in XML Dateien), man braucht keine Zeile JDBC Code mehr zu schreiben und Transaktionen gibt's dazu.

Nachtrag: Du machst aber kein Refactoring ohne Unit Tests, gell?


----------



## ms (7. Mrz 2008)

maki hat gesagt.:
			
		

> Für ein Projekt dieser Größe würde ich zu iBatis greifen, ist besser für kleinere Projekte mit weniger Tabellen/Abfragen geeignet.


Findest du wirklich, dass dieses Projekt so "klein" ist?
Spring/Hibernate ist sicher ein guter Ansatz.
Allerdings bringen die besten Frameworks nichts, wenn man sich nicht gut damit auskennt.

Btw: Du planst, entwirfst, entwickelst, testest und dokumentierst das alles alleine?

ms


----------



## maki (7. Mrz 2008)

20000 Zeilen Code sind nicht wirklich groß imho, dann nur 5-6 Klassen die wirklich gespeichert werden.

Klar ist Spring/Hibernate (oder gar Spring/iBatis ) besser als alles selbst zu schreiben, allerdings muss er fast zwangsläufig mit einem Business/Domain Model aufwarten.
Wenn er das sowieso vorhat, dann ist Hibernate auf jedenfall eine gute Lösung.

Wenn er nur vorhat ein paar Dinge zu ändern (SQL auslagern, Transaktionen) wäre iBatis einfacher & schneller.
JDBC/SQL aus Java zu entfernen geht vorzüglich mit iBatis.
Wobei, wenn man Transaktionen einführen, muss man meist die Anwendung umstrukturieren, da kann es leicht sein das es gar nicht viel mehr Aufwand ist Hibernate einzuführen.


----------



## maki (7. Mrz 2008)

*doublepost*


----------



## Guest (7. Mrz 2008)

> Allerdings bringen die besten Frameworks nichts, wenn man sich nicht gut damit auskennt.
> 
> Btw: Du planst, entwirfst, entwickelst, testest und dokumentierst das alles alleine?


Leider kenne ich mich mit Spring und Hibernate noch gar nicht aus, hab mir aber gerade das Buch "Spring und Hibernate. Eine praxisbezogene Einführung" bestellt was ja hier im Forum auch öfters erwähnt wird. Auch wenn ich es nachher nicht mit Spring machen sollte kann es denke ich nicht schaden wenn ich mich da etwas einlese. Ehrlichgesagt kann ich mir immer noch nicht richtig vorstellen was Spring eigentlich ist bzw. tut egal wieviel ich darüber im Internet lese ???:L 
Ich hoffe das Buch wird mir da weiterhelfen.

Ja ich mache alles komplett selbst. Von Vorteil ist eindeutig das es ein Familienbetrieb ist, ich täglich in der Firma bin und kein Zeitdruck besteht. Auch wenn mal etwas anfangs nicht ganz zuverlässig funktioniert ist das kein Beinbruch da es immer noch tausendmal besser ist als alles von Hand zu machen wie bisher (trotzdem will ich in Zukunft mehr testen und eine höhere Qualität abliefern)
Es kommt halt vieles ziemlich kurz, Planung und Entwurf werden eher stiefmütterlich behandelt derzeit, Dokumentation sowieso, aber ich gelobe Besserung :wink: 
Es gibt auch keine festen Anforderung von Unternehmensseite her, ich schaue mir die Arbeitsabläufe an und entscheide selbst wo man mittels eigener Software effektiver arbeiten könnte.
Es ist für mich auch eine sehr gute Erfahrung da man an der Uni nicht wirklich programmieren lernt. Will wie gesagt auch im Berufsleben Richtung Anwendungsprogrammierung gehen und da brauche ich Projekte bei denen ich Erfahrung sammeln kann.

Zu den Transaktionen:
Das sollen keine mega-Transaktionen werden, nur einige Sachen sind halt in 2-4 SQL-Querys verteilt weil verschiedene Datenbanktabellen upgedatet werden müssen, so hat z.B. ein Auftrag eine Versandhistory, Zahlungshistory und Druckhistory die beim speichern des Auftrags mitgespeichert werden. Außerdem enthält ein Auftrag auch Positionen die gespeichert werden beim speichern des Auftrags.
Ansonsten ist das alles eher simpel gehalten, ich kann ja unmöglich alleine und noch dazu als unerfahrener Programmierer sowas wie SAP R/3 programmieren. Es wird halt nur das nötigste implementiert und dann an bestimmten Punkten die für unser Unternehmen speziell von Bedeutung sind mehr Zeit investiert. Ansonsten wird auch alles nach und nach implementiert, nicht das gesamte Projekt auf einmal. dementsprechend wird auch im wesentlichen nur Stück für Stück geplant und entworfen, auch weil immer mal neue Anforderungen auftauchen und andere wegfallen oder in den Hintergrund treten.


----------



## ms (7. Mrz 2008)

@Gast
Hätte ein paar Fragen zu deinem Projekt die aber nur indirekt mit deinem Thema hier zu tun haben.
Vielleicht registrierst du dich ja, dann kann ich dir einen PN schicken.

ms


----------



## Nova (8. Mrz 2008)

Hallo ms, ich bin der "Gast", wusste den Benutzernamen net mehr da der auf dem alten PC gespeichert war...


----------



## SnooP (11. Mrz 2008)

Also ich würde stark zu Spring und Hibernate raten... - da kannst du, denk ich nicht viel falsch machen. Du musst auch Hibernate und Spring nicht 100% verstanden haben, bevor du mit deinem Projekt anfängst - ich glaube da braucht es sowieso einige Jahre  ...ich mach jetzt seit etwas über nem Jahr mit Hibernate rumm und kann nicht sagen, dass ich alles verstanden hab, bzw. ich lerne jeden Tag noch etwas dazu *g* - aber das ist ja auch gewissermaßen der Reiz der Informatik... - und gerade was Transaktionen angeht, ist Spring insb. in Kombination mit Annoatations (Java5) echt mal lässig


----------



## Nova (11. Mrz 2008)

So hab ich mir das auch gedacht, wollte nach ein paar Tests gleich anfangen mit Spring&Hibernate zu programmieren.
Wie sagt man so schön: programmieren lernt man nur durch programmieren   

Bin mal gespannt ob heute das Buch kommt, gestern haben die Beamten bei der Post in unserer Region gestreikt :roll: (und ich dachte immer Beamte dürfen nicht streiken...)


----------



## quippy (11. Mrz 2008)

Nova hat gesagt.:
			
		

> gestern haben die Beamten bei der Post in unserer Region gestreikt :roll: (und ich dachte immer Beamte dürfen nicht streiken...)



Da haben auch nicht die Beamten der Post gestreikt, sondern die Angestellten der Post. Die Beamten gibt es nicht mehr - außer halt denen, die bei der Privatisierung diesen Status hatten und daher als Beamte übernommen werden mussten.


----------



## Nova (11. Mrz 2008)

Naja bei uns hieß es die Beamten hätten auch gestreikt. Unser Briefträger ist z.B. auch Beamter.
Sind hier ziemlich im ländlichen Gebiet, hier kommt kein DHL sondern immer noch der Briefträger der auch Pakete bringt

naja ist ja auch egal, auf jeden Fall gabs gestern keine Post.


----------



## Nova (12. Mrz 2008)

Wirklich sehr interessant, hab den Hibernate Teil schon durch und bin jetzt bei Spring.
Sind schon einige AHA-Effekte und man fragt sich wie man bisher nur ohne Hibernate zurecht gekommen ist...
Bei Spring blicke ich noch nicht so ganz durch, bei Klassennamen wie 
"SimpleRemoteStatelessSessionProxyFacotryBean"
aber wohl kein Wunder :lol: Und ich dachte ich hätte schon die Neigung zu übermäßig langen Klassen- und Methodennamen  :roll:


----------

