# Warum Stored Procedures in JDBC



## seinesgleichen (23. Okt 2006)

Servus alle zusammen,

ich hätte mal ein paar allgemeine Fragen zu Stored P.:

Warum sollte ich überhaupt SP in mein Programm einbinden, ich weiß die preformens Vorteile sind signifikant, allerdings schreibe ich gerade an ner annwendung die nicht sooooo riesig seinen wird, also fällt dieser vorteil für mich raus.

Der andere Vorteil is ja das ich die rechte für das backoffice bzw frontend genauer zuteilen kann als wenn ich nur insert, select.. -Rechte vergebe, gut ok das argument zieht. 

Aber gibt es darüber hinaus noch andere Vorteil die den einsatz von SP rechtfertigen. (Jetzt mal von Redundanzen abgesehen) 

Außerdem bin ich mir im allgemeinen net so sicher wie das mit den SP abläuft. wollte eingentilch eine select SP anlegen die, je nach übergebenen Parameter einen ander view ausgibt:




```
CREATE OR REPLACE
PROCEDURE jub_select
(
view_in in varchar,
er_out out jub_uebersicht%rowtyp
)

AS
	
begin
	select * into er_out from view_in;

--END;
```

- Ich bin mir nicht sicher wie ich den out parameter in jdbc weiterverarbeiten soll. 
- Liefert mir den der aufruf der Stored P. ebenfalls ein resultSet?? (callablestatement......)
- oder is das quatsch für ein einfaches select ein SP anzulegen???????


----------



## foobar (24. Okt 2006)

> oder is das quatsch für ein einfaches select ein SP anzulegen???????


Allerdings. Ich sehe sowieso keinen Vorteil in Stored Procedures, ausser einen kleinen Performancegewinn. Aber dafür verlagert man Geschäftslogik ins Backend. Es muß also jeder selber wissen, ob es ihm das Wert ist.


----------



## seinesgleichen (24. Okt 2006)

erstmal besten dank für deine antwort. 

Zitat:
"Ich sehe sowieso keinen Vorteil in Stored Procedures, ausser einen kleinen Performancegewinn. Aber dafür verlagert man Geschäftslogik ins Backend. Es muß also jeder selber wissen, ob es ihm das Wert ist."

Also das Argument kann ich nicht akzeptieren, is doch much sinnvoller die Logistik in backend zu verlagern:

a) die zugriffe auf die DB sind sicherer (genaues zuteilen von rechten an das frontend) 
b) ich muss kein autocommit (false) setzen wenn ich keine probleme mit den foreign key bekommen will, beim insert /update
c) die manipulationsgefahr is ehrheblich geringer, da die SP auf der DB liegt und nicht verändert werden kann, das reine sql is das schon anfälliger. 
d) die SP können mehrmals genutze weren, also keine redundanzen, wäre ja mal gut scheiße wenn ich die DB abändere und meinen ganzen code aufarbeiten muss.

-->Allgemein gesehen sind SP also ne feine sache.

Aber zurück zu meinen anderen fragen, vielleicht kannst du mir dabei auch helfen:

- wie behandle ich den out parameter in JDBC?? 
-- zum einen wenn ich eine ergebnismenge zurückbekomme 
-- zum anderen wenn es einfach nur eine var. ist (zb. int)


Wäre echt super wenn du mir dabei helfen könntest. 

Danke


----------



## bronks (25. Okt 2006)

seinesgleichen hat gesagt.:
			
		

> ... Also das Argument kann ich nicht akzeptieren, is doch much sinnvoller die Logistik in backend zu verlagern: ...


Backend? Das ist kein Backend. Das ist nur eine Datenbank. Ein gelangweilter Prozess, welcher nur dafür da ist Daten zu speichern und wieder zurückzugeben. 



			
				seinesgleichen hat gesagt.:
			
		

> a) ... b) ...  c) ... d)


Java ist größtenteils Platformunabhängig und in den BluePrints wird zusätzlich Unabhängigkeit von der Datenbankmaschine demonstriert. Deine o.g. Punkte treffen nur dann zu wenn Du mit VB an MsSql rangehst. In Java heißt es immer Client/Server. Vor allem dann, wenn man schon das Wörter "sicherer" oder "Sicherheit" erwähnt hat.

Alle von Dir genannten Punkte sind nicht vollständig durchdacht oder es waren falsche Vorstellungen wegen Halbwissen im spiel.


----------



## Guest (25. Okt 2006)

Java ist größtenteils Platformunabhängig und in den BluePrints wird zusätzlich Unabhängigkeit von der Datenbankmaschine demonstriert. Deine o.g. Punkte treffen nur dann zu wenn Du mit VB an MsSql rangehst. In Java heißt es immer Client/Server. Vor allem dann, wenn man schon das Wörter "sicherer" oder "Sicherheit" erwähnt hat.

Alle von Dir genannten Punkte sind nicht vollständig durchdacht oder es waren falsche Vorstellungen wegen Halbwissen im spiel.

samma über mein halbwissen mukieren und es selber ne besser wissen! Jetzt mal ohne witz aus welchem grund sollten meine Punkte nur auf VB mit MSSql zutreffen? 
Kennt nur MsSql keine redundanzen  oder was? Und die tatsache das SQL direkt an die DB über JDBC schicken nciht grade die beste idee ist stimmt wohl auch net?? 

Jetzt mal ohne witz wie kommst du auf solche aussagen? duch den Einsatz von SP wird doch garnicht die Plattformunabhängigkeit von java eingeschränkt!!!

WEnn meine Aussagen net zutreffen dann wiederleg sie auch bitte, einfach nur behaupten das sie nicht durchdacht sind, is net sooo die leistung.
Zeig mir an welchen stellen ich nicht bis zum ende gedacht habe, bitte.


----------



## KSG9|sebastian (25. Okt 2006)

Gast hat gesagt.:
			
		

> a) die zugriffe auf die DB sind sicherer (genaues zuteilen von rechten an das frontend)


Das gehört aber nicht in die Datenbank sondern zur Geschäftslogik (=Middle-Tier)



			
				Gast hat gesagt.:
			
		

> b) ich muss kein autocommit (false) setzen wenn ich keine probleme mit den foreign key bekommen will, beim insert /update


Das Problem bekommst du im Code auch nicht wenn du alles sauber machst (Transaktionsmanagement...)



			
				Gast hat gesagt.:
			
		

> c) die manipulationsgefahr is ehrheblich geringer, da die SP auf der DB liegt und nicht verändert werden kann, das reine sql is das schon anfälliger.


Wieso das denn? Das Problem sind nicht erlaubte Werte bzw. Werte welche zu Problemen führen, z.B. ein einzelnes Anführungszeichen. Das Problem tritt aber genauso in einer SP auf. Du musst die Zeichen bzw. Werte so oder so filtern.



			
				Gast hat gesagt.:
			
		

> d) die SP können mehrmals genutze weren, also keine redundanzen, wäre ja mal gut scheiße wenn ich die DB abändere und meinen ganzen code aufarbeiten muss.


Und wo hast du im Code Redundanzen? Wenn du eine zentrale Klasse benutzt dann hast du auch keine Redundanzen drin. Und wenn du nen O/R-Mapper verwendest gleich zweimal nicht.


----------



## bronks (25. Okt 2006)

Anonymous hat gesagt.:
			
		

> ... WEnn meine Aussagen net zutreffen dann wiederleg sie auch bitte, einfach nur behaupten das sie nicht durchdacht sind, is net sooo die leistung. Zeig mir an welchen stellen ich nicht bis zum ende gedacht habe, bitte.


Niemand sonst hat hier im Forum so viele Diskussionen über SP geduldig mitgemacht wie Foobar. Foobar hat Dir eine Antwort gegeben, welche an Ausführlichkeit nicht zu übertreffen ist. Du stellst 4 Punkte auf, welche an Unfug durch nichts zu übertreffen sind und bist gleich eingeschnappt, wenn man Dich ganz soft darauf hinweist.

Ich werde nicht nocheinmal etwas Tippen, was in diesem Forum bereits geschrieben wurde >> SuFu: Stored Procedure


----------



## KSG9|sebastian (25. Okt 2006)

konkret: http://www.java-forum.org/de/viewtopic.php?t=35284&highlight=stored+procedure


----------



## robertpic71 (27. Okt 2006)

Der Vollständigkeit halber möchte ich noch anmerken, dass es durchaus sinnvolle/notwendige Anwendungen für stored Procedures gibt. 

1) In der Praxis (*) nicht selten, ist der Einsatz der Datenbank als "Middleware".
1a) Hier geht es darum alte Programme (Cobol, RPG, Fotran, C) weiterverwenden zu können. Die ersten Schritte der Anwendungsmodernisierung sind oft nur eine neue Oberfläche mit der alten Businesslogik. Der schnellste Weg ein altes Programm in einer Multi-Tier-Umgebung zugänglich zu machen, ist eine stored Procedure darüber zu legen. 
1b) Die Kommunikation muss nicht unbedingt auf ein eine Datenbanktransaktion beschränkt sein. Stored Procedures können auch verwendet werden um z.B. einen Batchjob (im Host = Datenbank-Tier) anzustossen.

(*) damit meine ich meine praktischen Erfahrungen im Groß- und Midrangerechner-Umfeld

2.) Es gibt auch noch andere Anwendungen (z.B. die Datenbank als Steuerzentrale - Trigger statt Listener), aber damit kommt man als Javaprogrammierer normalerweise nicht mehr in Berührung.

3.) Der Punkt a) vom Threadsteller ist der einzige, welcher in Sonderfällen zutreffen kann. Wenn man Softwarepakete zukauft (z.B. CRM oder Katalogwesen zur Warenwirtschaft), dann öffnet man diesem i.d.Regel den Zugang zur Datenbank um Zugriff auf die aktuellen Kunden- bzw. Artikeldaten zu holen. Wenn das CRM-Sytem auch noch Kundendaten updaten darf, dann ist es mir lieber, es verwendet dafür ein von mir vorgesehene stored Procedure als selber rumzuwerken.

Bei einer alleinstehenden Javaapplikation halte ich die doppelte Berechtiungswartung (SQL/Applikation) aber für Quatsch.

Falls es den Threadsteller noch interessiert, kann ich auch schreiben, warum ich die Punkte b-d für nicht richtig halte. Natürlich auch wie man stored Procedures anspricht.


Die von mir beschriebenen Lösungen sind natürlich nicht aus dem Lehrbuch, sondern aus der Praxis. Datenbankunabhängigkeit ist noch unbedingt ein Argument, wenn ich dem Rechner sowieso noch zigtausende Cobolprogramme laufen habe. SOA fängt erst jetzt langsam zu greifen an wird über kurz oder lang in den Punkten 1 und 3 Einzug halten.

Zu erwähnen noch, dass in anderen Sprachen (z.B. Access 97-2000) fleißig ( im MSDN) zu stored Procedures geraten wurde.

Für neue eigenständige Javaentwicklungen sehe ich keine Veranlassung mit stored Procedures zu arbeiten.


----------



## Guest (27. Okt 2006)

nochmal servus, 

sorry wenn ich etwas zu grob geantwortet hab, hatte nen schlechten tag. 
Mag es aber ehrlich gesagt auch nicht wenn behauptungen aufgestellt werden ohne eine begründungen zu liefern. 


So nun hab ich mich mal etwas schlau gemacht und gebe zu das meine argumente net durchdacht waren. besonders das mit der Sicherheit. 

Aber an einem Punkt halte ich felsenfest: Die SP sind ne feine sache! 
Es ist und bleibt ein problem das die änderung der DB auch eine änderung des frontends nachsich zieht! 
Wenn es dem Admin einfällt das die foreign key nicht mehr deferrable seinen sollen, würde dies eine erhebliche veränderung des frontends nachsich ziehen (müssen). Gleiches gilt für die deletRules.  Das frontend erfährt ja nix davon wenn die deletrules von noAction auf cascade geändert wurden. Das nicht-beachten einer solchen änderung würde nicht immer erfreuliche folgen haben.  Das einzige was man erfährt ist: "1 Row updated" (obwohl 800 Datensätze gelöscht wurden -->cascade)
Zumal die kommunikation zwischen DB Admin und javaguru nicht immer die beste ist. 
Wird jedoch auf eine SP zugegriffen, ist die anpassungen eine sache von 2min. 

Zum thema redundanzen: Ja klar kann ich eine Zentrale Klasse anlegen die mit all den Methoden ausgestattet ist, die ich für meinen DB-Zugriff /Update benötige. Aber wenn ich mir dann schon die arbeit machen, warum dann nicht eine SP ist doch genau das gleich! Eine Zentral (in der DB) hinterlegte schnittstelle. 
Hinzu kommt der Vorzug der guten Preformence, da kann auch BatchUpdate (allein) nicht mithalten. 

@robertpic71: Ja ich bin sehr daran interessiert (bezüglich der andern Punkte). Aber noch mehr interesiert mich wie ich mit den out-Parameter verfahre (in JDBC).


----------



## robertpic71 (28. Okt 2006)

Anonymous hat gesagt.:
			
		

> @robertpic71: Ja ich bin sehr daran interessiert (bezüglich der andern Punkte). Aber noch mehr interesiert mich wie ich mit den out-Parameter verfahre (in JDBC).



Weiter unten hast du dann ein Beispielprogramm. Eigentlich hat meine stored Procedure 3 Input und einen Outputparameter. Je nach SQL-Dialekt kann man die Parameter aber nur Input, nur Output oder I/O definieren. Der Übersicht halber, definiere ich mein Parameter immer I/O. Es ist sonst etwas verwirrend, wenn das 4. Fragezeigen der erste Outputparameter ist usw. 

Ob das CallableStatement ein ResultSet erwartet oder nicht, hängt vom Aufruf ab: bei executeQuery ein ResultSet bei execute ein Statusschalter (siehe API).

Wenn ich als Output nur ein Resultset habe, könnte man auch die Inputparameter in den String "verwursten" und mit Resultset rs = conn.executeQuery("{call stored('Parm1'}") 
an die Daten kommen. Die Kombination prepareCall, Connectionpool mit lazyClose hat bei mir (DB2) den Vorteil, dass die stored Procedures (und die dahinterliegenden Backofficeprogramme) offen bleiben und die Folgeaufrufe viel schneller gehen.


```
import com.ibm.as400.access.*;
import java.sql.*;

public class JdbcTest10 {

   public void run () throws SQLException {
      // Hier deinen JBDC-Treiber einsetzen
       DriverManager.registerDriver(new com.ibm.as400.access.AS400JDBCDriver());

       // deine Connectdaten
       Connection conn =
           DriverManager.getConnection("jdbc:as400://192.168.1.45",
                     "user", "pass");

       // OutParameter registrieren, die Types.xxxx sind SQL-Datentypen
       // der Callbefehl hängt auch vom SQL-Dialekt ab
       CallableStatement callStmt = conn.prepareCall("{call PWRDWN.ARCIVCSP (?, ?, ?, ?)}");
       callStmt.registerOutParameter(1, Types.CHAR);
       callStmt.registerOutParameter(2, Types.CHAR);
       callStmt.registerOutParameter(3, Types.CHAR);
       callStmt.registerOutParameter(4, Types.CHAR);
       callStmt.setString(1, "inv0459.txt");
       callStmt.setString(2, "FIRMA_1");
       callStmt.setString(3, "7622");
      // Status NO COnnection setzen, falls keine Verbindung zustande kommt 
       callStmt.setString(4, "NOCO");
       
       // Aufruf für eine stored Procedure mit Resultset
       ResultSet rs = callStmt.executeQuery();
       
       // oder Aufruf für eine SP ohne Resultset (Return boolean für Fehleranzeige)
       System.out.println("Execute Return: " + callStmt.execute());
       System.out.println("Return Parameter 4/Status: " +  callStmt.getString(4));

       callStmt.close();
       conn.close();

  }

  public static void main (String args []) throws SQLException {

      new JdbcTest10().run();
  }
}
```

Jetzt noch zu den anderen Punkten:



> b) ich muss kein autocommit (false) setzen wenn ich keine probleme mit den foreign key bekommen will, beim insert /update


In 95% meiner Anwendungen kann ich das Autocommit nicht brauchen und daher ist bei uns sowieso auf "false". Wenn man eine komplexe Anwendung per stored Procedure auf autocommit(false) trimmen will, müsste man wohl die meisten Updates in stored Procedures machen - die Parameterlisten schau ich mir dann aber an.....



> c) die manipulationsgefahr is ehrheblich geringer, da die SP auf der DB liegt und nicht verändert werden kann, das reine sql is das schon anfälliger.


?? Meine Sourcen der stored Procedures sind gleich sicher wie die Javasourcen - wenn das so gemeint ist. Wenn die Fehleranfälligkeit gemeint ist, sind die Parameterlisten für stored Procedures genauso anfällig wie welche für SQL-Statements. Wenn ich eine Persistenzschicht wie Hibernate verwende (oder selbst OAM's mache), bin ich weitgehend frei von solchen "herumgezähle" von Parametern.  



> d) die SP können mehrmals genutzt weren, also keine redundanzen, wäre ja mal gut scheiße wenn ich die DB abändere und meinen ganzen code aufarbeiten muss.


Mit Java (und OOP) hat man gute Chancen ein Problem bzw. eine Arbeit wirklich nur einmal im Source haben zu müssen. Was die Datenbank angeht, kann ich wieder nur zu zentralen Zugriffsmodulen - sebstgemacht oder ala Hibernate raten. 

Aber spielen wir noch ein wenig stored Procedure:
- Ich wette einiges darauf, dass bei so einer Lösung das Anpassen der Parameter zum täglichen Brot gehört.
- Stichwort Deployment: Wenn man Logik + Parameter in der DB hat muss man das immer gemeinsam mit den Programmen einsetzen. Das ist sicher eine Fehlerquelle mehr und man kann nicht mal schon einen Client mit der neuen Software testen - die braucht ja schon die neuen stored Procedures.
- Debugging von stored Procedures. Das ist auf der DB2 schon mühsam, viele DB's bieten das erst gar nicht an. 
- Wenn die Businesslogik in Java und stored Procedures aufteile, mache ich mir die Wartung nicht leichter. Das ist mMn auch ein klarer Verstoss gegen die Multi-Tier-Architektur. 
Wenn man sich daran gewöhnt hat, ist Eclipse mit seinem Refactoring ein mächtiges Instrument, welches schon mal automatisch den ganzen Code "aufarbeitet" (d). Das Refactoring endet natürlich bei den stored Procedures.

Ein paar andere Sachen die mir so aufgefallen sind:


> Wenn es dem Admin einfällt das die foreign key nicht mehr deferrable seinen soll...


Ein Admin hat nichts an den Tabellendefinitionen der DB rumzufummeln. Das ist Sache der Applikation bzw. dessen Betreuer.



> Zumal die kommunikation zwischen DB Admin und javaguru nicht immer die beste ist.


Habt ihr 2 da im Bewerb stehende Teams, oder was? Mit scheint du willst mit den stored Procedures mögliche Datenbankänderungen von anderer Seite ausgleichen? Das kann man auch mit Java (OAM's selbstgemacht oder Hibernate) zum Teil erreichen. 


Ich arbeite recht häufig mit stored Procedures und werde das noch oft tun. Aber eine reinen Javaanwendung würde ich jederzeit den Vorzug geben.


----------



## seinesgleichen (28. Okt 2006)

besten Dank für die Antworten!

das mit Hibernate hab ich zwar nicht verstand, da ich diese Technik nicht kenne, aber man kann ja mal nachlesen... 

Bin aber der meinung das der Admin sehrwohl was mit der TableDefinition zutun hat... aber egal. 

Ich hätte nochmal ne frage: 
Bekomme beim folgenden prog. immer so ne dolle fehlermeldung: "Ungeueltige Argument in Aufruf". Hast du vielleicht ne idee was ich falsch mache? 


```
import java.io.*;
import java.sql.*;


class Batch extends Thread
{
  public static void main(String args [])  	
  {
  	
	try{ Class.forName ("oracle.jdbc.driver.OracleDriver");} 
    
        catch(ClassNotFoundException exNotFound){
        System.out.println("\nClassNotFound :\n" + exNotFound.getMessage());
    }
	[code]
	
	try 
	{
      	Connection con =
        DriverManager.getConnection ("jdbc:oracle:thin:@localhost:1521:XE",user, passs);
        
		CallableStatement cstmt = con.prepareCall("EMP_INSERT(?,?)");
		
		StoppUhr timer = new StoppUhr();
        	Thread messen = new Thread(timer);
		messen.start();
				
			/*Batsch Insert*/
			for (int i = 100; i< 5001; i++)
			{
				String currentName = ("Name"+i);
			
				System.out.println(currentName);
	
				cstmt.setString(1, currentName);
				cstmt.setInt(2, 10);
				cstmt.addBatch();
				
				
				if(i==5000)
				{
					int [] ergebnis = cstmt.executeBatch();
					con.commit(); 
					System.out.println("Commit wurde durchgeführt");								  
					//con.setAutoCommit(true); 
					messen.stop();
					System.out.println("Zeit(sec) /Batch :" + timer.getLaufzeit());
				} 
			}
...
```

Meine SP sieht wie folgt aus:
[/code]
create or replace PROCEDURE emp_insert
(
ename_in in varchar2,
deptno_in in Number
)

AS
	v_ename   varchar2(10) :=ename_in;
	v_deptno  Number(4) :=deptno_in;
begin
	insert into emp(empno, ename, deptno)
	values (emp_seq.nextval, v_ename, v_deptno);

END emp_insert;


```
Hast du ne idee??
```


----------



## Guest (29. Okt 2006)

gut ok hat sich von allein geklärt


----------



## robertpic71 (29. Okt 2006)

Der prepareCall ermöglicht nur auf der Javaseite Parameter zu setzen und registrieren. Die DB weiß aber nicht automatisch das es sich um ein Call handelt.

Deshalb solltest du wie in meinem Beispiel geschwungene Klammern und ein call beim Aufruf verwenden, also


```
CallableStatement cstmt = con.prepareCall("{call EMP_INSERT(?,?)}");
```

>> Hier << noch ein paar Beispiele für Aufrufe von stored Procedures unter Oracle.

Zum DB-Admin: Kommt darauf an, wieweiter der Admin in die Entwicklung eingebunden ist. Meiner Definition nach, hat ein Admin dafür Sorge zu tragen, das die Datenbank läuft, genug Speicherplatz hat, gesichert wird und die Berechtigungen stimmen. Das höchste der Gefühle ist mMn einen zusätzlich Index anzulegen. 

Aber speziell wenn man mit den DB-Features arbeitet (und davon hat Oracle eine Menge) kommen da auch andere Aufgaben dazu. Aber wie schon in der Diskussion erwähnt: Multi-Tier zielt eher darauf ab diese Schichten zu trennen und austauschbar zu machen.


----------



## bronks (29. Okt 2006)

Anonymous hat gesagt.:
			
		

> ... Zum thema redundanzen: Ja klar kann ich eine Zentrale Klasse anlegen die mit all den Methoden ausgestattet ist, die ich für meinen DB-Zugriff /Update benötige. Aber wenn ich mir dann schon die arbeit machen, warum dann nicht eine SP ist doch genau das gleich! Eine Zentral (in der DB) hinterlegte schnittstelle.
> Hinzu kommt der Vorzug der guten Preformence, da kann auch BatchUpdate (allein) nicht mithalten ...


Es gibt bestimmte Strategien bei der Javaentwicklung, die entsprechende Vorgehensweisen verlangen. Mit Java ist fast alles möglich und ebenfalls Deine Idee mit den SP. Für Heim und Hobby ist das OK, aber wenn Du im professionellen Bereich Anerkennung und Anfragen ernten möchtest, dann bist Du auf dem falschen Weg. Wenn jemand einen Javamenschen sucht, dann nicht deswegen, weil er die Sprache kann, sondern weil er sich mit den üblichen Patterns und Architekturen auskennt.

Evtl. hilft das hier: http://java.sun.com/blueprints/corej2eepatterns/Patterns/index.html


----------

