# Problem oder Denkfehler mit H2-Database



## chrisu74 (27. Jul 2015)

Liebe Leute,

ich bin was Java bzw. OOP betrifft ein kompletter Neuling (abgesehen vom 'Herumspielen' mit VB vor vielen Jahren). Allerdings habe ich viel Erfahrung mit PHP - also Programmierung verstehe ich durchaus. Und ich denke, dass ich das Prinzip der OOP auch größtenteils verstanden habe.

Nun möchte ich mich langsam in Java einarbeiten und habe mir als kleines Projekt eine Lagerverwaltung vorgenommen. Dazu brauche ich natürlich eine Datenbank und habe mich für H2 (embedded) entschieden - zugegeben: Google hat mir die Entscheidung abgenommen .

Dieser Beispielcode funktioniert ohne Probleme:


```
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class H2Class {
    /*
    public static void main(String[] args) {
        H2Class conn = new H2Class();
        conn.setConnID();
    }
   
    public void setConnID () {
    */

    public static void main(String[] a) throws Exception {
        Connection conn = null;
        try {             
            Class.forName("org.h2.Driver");
            
            conn = DriverManager.getConnection("jdbc:h2:~./h2", "root", "");            
            System.out.println(conn);
            conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            if (conn != null)
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
        }
    }
}
```

Dieser allerdings nicht (Exception in thread "main" java.lang.Error: Unresolved compilation problem: Unhandled exception type ClassNotFoundException):


```
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class H2Class {
   
    public static void main(String[] args) {
        H2Class connID = new H2Class();
        connID.setConnID();
    }
   
    public void setConnID () {
    //public static void main(String[] a) throws Exception {
        Connection conn = null;
        try {             
            Class.forName("org.h2.Driver");
            
            conn = DriverManager.getConnection("jdbc:h2:~./h2", "root", "");            
            System.out.println(conn);
            conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            if (conn != null)
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
        }
    }
}
```

Nun muss ich natürlich Querys dynamisch übergeben können, sonst bringt mir die Datenbank ja nichts. Somit brauche ich eine Möglichkeit, die Datenbank über Methoden anzusprechen.

Wo ist hier mein Denkfehler? Bzw. wie kann man das Problem lösen?

Die 'Applikation' soll im 'Endausbau' über eine grafische Oberfläche bedient werden können, sonst hätte sie ja auch keinen Sinn. Aber das nur am Rande.

Vielen Dank!


----------



## Tom299 (28. Jul 2015)

Die SQLException behandelt nur DirverManager.getConnection(...) aber Class.forName mußt du auch noch behandeln. Evtl. einfach nur die SQLException durch Exception austauschen.


----------



## pitsoft21 (5. Okt 2015)

Hallo, das conn.close + finally {} muß in eine andere Methode z.B. closeConnection ausgelagert werden , sonst ist die Verbindung zur DB ja gleich wieder weg. Die Connection global merken und damit alle Abfragen machen. Bei Applikationsende closeConnection rufen.


----------



## Joose (5. Okt 2015)

Tom299 hat dir den Fehler bezüglich des Compiler Fehler schon gesagt.



pitsoft21 hat gesagt.:


> Hallo, das conn.close + finally {} muß in eine andere Methode z.B. closeConnection ausgelagert werden , sonst ist die Verbindung zur DB ja gleich wieder weg. Die Connection global merken und damit alle Abfragen machen. Bei Applikationsende closeConnection rufen.



Du hast schon recht das bei diesem Code die Verbindung zur DB gleich wieder geschlossen wird. Und generell sollte dieser Code ausgelagert werden in eine eigene Klasse.
Connection global merken und erst bei Applikationsende schließen ist hingegen keine gute Programmierung.

Sobald die Applikation ein Statement absetzen will soll sie sich eine/die Verbindung holen und das Statement feuern. Sobald der Arbeitsschritt erledigt ist sollte man die Verbindung wieder freigeben.
(Pool Implementierung)
Vorteil: manchmal sind gleichzeitige Verbindungen begrenzt, außerdem belegt die Verbindung nur unnötig Ressourcen während man nicht mit der DB arbeitet, und auf eingestellte Timeouts muss man ebenfalls achten


----------

