# DB-Klasse für häufig verwendete Aufgaben



## Anjax (31. Okt 2007)

Jede Literatur zeigt mir nur die Standard-Befehle, um mit JDBC zu arbeiten.

Ich finde es aber nicht praktisch, jedes mal wenn ich etwas aus der DB benötige, connecten, SQL senden, while-Schleife durchlaufen, etc.

Vieles wird immer wieder benötigt und ich möchte diese Aufgaben zentral halten können, z.B. in einer Klasse mit folgenden Methoden:

* getArray(SQL) - der Inhalt einer Abfrage wird als Array geliefert
* getValue(SQL) - es wird nur ein einzelner Wert geliefert
* fillTreeView (SQL, myTreeView) - das TreeView wird mit dem Inhalt der Abfrage gefüllt

Zusätzlich könnte sich die Klasse um die Fehler kümmern. Beispielsweise kann angegeben werden, ob Fehler einfach nur geworfen werden, oder die Klasse selbst die Fehler in einem aussagekräftigen Fenster anzeigen soll.


Gibt es solch eine Klasse schon, oder wie macht ihr das mit der Datenbank?


----------



## SlaterB (31. Okt 2007)

wenn ich irgendwas mit JDBC mache, dann ist das immer so ziemlich das erste,
einen Standard braucht man dafür aber nicht,

gibts auch gar nicht für die eigene indidviduelle Connection, Fehlerbehandlung,
package, Vererbung, import, usw.

schreibe dir die 10 Zeilen hin und fertig ist es


----------



## Anjax (31. Okt 2007)

danke für deinen Beitrag 

Wenn du etwas mit JDBC machst, schreibst du dir also zuerst selbst eine Klasse, die häufig verwendete Aufgaben übernimmt, wie z.B. eine Abfrage-Ergebnis als Array zurückzugeben.

Aber warum gibt es dazu nicht schon eine fertige Klasse?
Von PHP kenne ich z.B. solch eine generische DB-Klasse und diese hat viele Dinge enthalten, an die ich zunächst gar nicht gedacht hatte.



*Noch eine wichtige Frage*:
Wie werden die Verbindungen gehandhabt?
a) Wird jedes mal eine neue Verbindung aufgebaut und dann wieder beendet, wenn z.B. die Methode querySQL() der Klasse ausgeführt wird.
b) Oder macht man zu Beginn ein Connect (z.B. wenn die Klasse initiiert wird) und alle weiteren Aufrufe verwenden die gleiche Verbindung?


----------



## SlaterB (31. Okt 2007)

> Aber warum gibt es dazu nicht schon eine fertige Klasse? 

wenn ich eine Java-Programm schreibe, dann schreibe ich mir jedesmal eine Klasse, die das Programm enthält,
wieso gibt es keine fertige Klasse?..

eben wie oben geschrieben, weil das für jeden Programmierer anders aussieht, meist sogar in verschiedenen Projeken eines Programmierers/ Teams

> Von PHP kenne ich z.B. solch eine generische DB-Klasse und diese hat viele Dinge enthalten, an die ich zunächst gar nicht gedacht hatte. 

man darf die JDBC-Klassen wie ResultSet/ Connection nicht unterschätzen,
die enthalten alles, was jeder braucht

dass man man trotzdem noch was selber zu programmieren hat,
sehe ich eher als Stärke von Java gegenüber PHP, als Mächtigkeit, alle (mehr) Schritte zu kontrollieren

-----------

> Wie werden die Verbindungen gehandhabt? 

im einfachen Falle b)
über a) musst du wahrscheinlich erst nachdenken, wenn du so efahren bist, dass sich solche Fragen gar nicht mehr stellen


----------



## Kim Stebel (31. Okt 2007)

vielleicht sollte man hier schon mal auf die JPA und hibernate hinweisen. Wahrscheinlich ist das aber zu umfangreich für dich.


----------



## ARadauer (2. Nov 2007)

> Wie werden die Verbindungen gehandhabt?


ich schreib mir immer einen kleinen connection pool.
der bietet die möglichkeit, eine verbindung anzufordern und diese wieder zurück zugeben.

wird eine angefordert und es ist keine verbindung frei, öffnet er eine neue verbindung und gibt sie weiter.

wird an ihm eine verbindung zurück gegeben, schließt er sie nicht sondern, markiert sie als frei.
so muss nicht bei jedem anfordern eine neu verbindung geöffnet werden.

ich könnte dir den code geben, hab ihn aber nicht hier ....


----------



## ARadauer (2. Nov 2007)

doch hier..


```
import java.sql.Connection; 
import java.sql.DriverManager; 
import java.sql.ResultSet; 
import java.sql.SQLException; 
import java.sql.Statement; 
import java.util.Iterator; 
import java.util.Vector; 

import javax.sql.DataSource; 

import com.bmw.bedarfsplanung.main.Globals; 

import oracle.jdbc.pool.OracleDataSource; 

/** 
* DbHandler ist ein einfacher Connection Pool, der nach Bedarf Verbindungen zu Datenbanken aufmacht, 
* aber aus performance Gründen, diese nicht gleich wieder schließst sondern, bei erneuter anfrage, bereits 
* offene Verbindungen zurück gibt. 
* @author Q240764 
* 
*/ 
public class DbHandler { 

   public static int MIS2 = 0; 
   public static int LEMO = 1; 

   private ConnectionData[] connData = {new MIS2Db(), new LemoDb()}; 
    
   //die offenen verbindungen 
   private Connection[] connections; 
   //ist die verbindung in benützung 
   private boolean[] inUse; 
   //damit ich weiß welche datenbank eine verbindung gehört 
   private int[] database; 

   private static DbHandler instance; 
    
   //anzahl der maximal offenen verbindunge 
   private int maxConnections = 10; 

   public static synchronized DbHandler getInstance(){ 
      if(instance == null){ 
         instance = new DbHandler(); 
      } 
      return instance; 
   } 

   /** 
    * Standard konnstruktor, registriert den jdbc Treiber und legt das array für die offenen verbindunge an 
    * 
    */ 
   private DbHandler(){ 
      connections = new Connection[maxConnections]; 
      inUse = new boolean[maxConnections]; 
      database = new int[maxConnections]; 
      try { 
         DriverManager.registerDriver(new oracle.jdbc.OracleDriver()); 
      } catch (SQLException e) { 
         // TODO Auto-generated catch block 
         e.printStackTrace(); 
      }       
   } 

   /** 
    * liefert eine offene Verbindung, für die angeforderte Datenbank aus dem Connection Pool 
    * ist keine offene vorhanden, wird eine Verbindung aufgebaut 
    * Es muss sicher gestellt sein, dass eine angeforderte Verbindung über returnConnection wieder zurück gegeben wird 
    * @param db die Datenbank für die die Verbindung angeforderd wird 
    * @return eine offenen JDBC Connection 
    * @throws SQLException wenn ein verbindungsaufbau fehlschlägt 
    */ 
   public synchronized Connection getConnection(int db)throws SQLException { 

      //wenn die verbindung noch null ist: anlegen 
      for(int i = 0; i < maxConnections; i++){ 
         if(connections[i]==null){ 
            connections[i] = DriverManager.getConnection(connData[db].getHost(), connData[db].getUser(), connData[db].getPass()); 
            inUse[i] = true; 
            database[i] = db; 
            return connections[i]; 
            //ist die verbindung, nicht in benützung und von der selben datenbank: zurück geben 
         }else if((!inUse[i]) && (database[i]==db)){ 
            //ist sie geschlossen muss vorher verbunden werden 
            if(connections[i].isClosed()){ 
               connections[i] = DriverManager.getConnection(connData[db].getHost(), connData[db].getUser(), connData[db].getPass()); 
            } 
            database[i] = db; 
            inUse[i] = true; 
            return connections[i]; 
         } 

      } 
      System.out.println("Max Connections überschritten"); 
      return null; 
   } 

   /** 
    * über getConnection angeforderte Verbindungen, MÜSSEN über diese Methode wieder zurück gegeben werden 
    * die verbindungen werden nicht geschlossen, sondern über inUse zu Wiederverwendung freigegeben 
    * @param con 
    */ 
   public synchronized void returnConnection(Connection con){ 
      for(int i =0; i < connections.length;i++){ 
         if(con.equals(connections[i])){ 
            inUse[i] = false; 
            return; 
         } 
      } 
      System.out.println("Connection war nicht vorhanden"); 
   } 


   /** 
    * um ein update auszuführen, Connection anfordern, updaten, connection zurück geben 
    * spart im grunde nur Schreibarbeit 
    * @param query, die auszuführende abfrage 
    * @param db die Datenbank, in der die Abfrage ausgeführt werden soll 
    * @throws SQLException 
    */ 
   public static void executeUpdate(String query, int db) throws SQLException{ 
      Connection con = getInstance().getConnection(db); 
 Statement stmt = null; 
      try { 
         stmt = con.createStatement(); 
         if(Globals.debug){ 
            System.out.println(query); 
         } 
         stmt.executeUpdate(query); 
      } catch (SQLException e) { 
         throw e; 
      }finally{
    if(stmt!=null)
        stmt.close();     
         getInstance().returnConnection(con); 
      }       
   } 
}
```

der code is aber schon älter, kann leicht sein, dass ich ihn mal geändert habe.

sowas wie meine statische executeUpdate, könntest du natürlich auch für das Lesen von Werten schreiben...


----------

