# Datenbankverbindung kann nicht hergestellt werden



## Rawan (8. Jan 2014)

Hallo,
ich habe folgendes Problem:
Ich möchte in meiner H2-Datenbank eine Tabelle "Student" erstellen, jedoch wird meine Datenbank nicht verbunden..Im Quellcode werden keine Fehler angezeigt, jedoch kommt die Fehlermeldung, dass keine Verbindung zur Datenbank hergestellt werden kann. Wenn ich mich über den Browser mit der Datenbank manuell verbinde, dann erscheint keine Tabelle in der Datenbank.
Ich habe auch die jar-Datei für die h2 in meinen build path von eclipse eingebunden.
Kann mir jemand helfen und sagen, was mein Fehler ist?
Hier ist mein Quellcode:


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


public class Database {

	/**
	 * @param args
	 */
	public static void main(String[] args)  throws Exception {
		Connection conn = null;		

		try { 

		Class.forName("org.h2.Driver").newInstance(); 

		conn = DriverManager.getConnection( 
				"jdbc:h2:~/Softwaretechnik", "", ""); 
		
		// create our java jdbc statement
		Statement stmt = conn.createStatement();
		
		
		// create table "Student"
		String createQ = "CREATE TABLE student(firstname VARCHAR(30)," +
				"lastname VARCHAR(30), matriculationNumber VARCHAR(14) PRIMARY KEY, " +
				"email VARCHAR(255), title CHAR(4), degree_course VARCHAR(255), " +
				"date_and_timeOfRegistration VARCHAR(255)"; 
		stmt.executeUpdate(createQ); 
		

        // insert data to the table "student"
		String insertQ = "INSERT INTO student (firstname, lastname, matriculationNumber," +
				"email, title, degree_course, date_and_timeOfRegistration)" +
		"VALUES ('', '','','','','','')";
		stmt.executeUpdate(insertQ);
		
		
/**	   ResultSet rs = stmt.executeQuery("SELECT * FROM student");
		while (rs.next()) { 
			System.out.println(rs.getString(1)+ " "+ rs.getString(2)+ " " + rs.getString(3)+ " " +
		rs.getString(4) + " " + rs.getString(5) + " " + rs.getString(6) + " " + rs.getString(7) + " " );
		}
*/
		
		
		stmt.close();
	//	rs.close();
		conn.close(); 
		
		}catch(SQLException e){
			System.err.println("Keine Verbindung zur Datenbank möglich");
			System.err.println("Fehlercode: " + e.getErrorCode());
		}	
	}
}
```


----------



## turtle (8. Jan 2014)

Also, bei mir geht das Connecten problemlos.

Du weisst schon das die Datenbank im Home-Verzeichnis erzeugt wird ? (bei mir C:\Users\testuser\Softwaretechnik.h2.db).

Aber das SQL-Statement funzt nicht, denn da fehlt wohl ein ")" am Ende.

Ich nehme immer squirrel, um SQL-Befehle auszuprobieren, bevor ich sie in Code "schweisse".


----------



## Rawan (8. Jan 2014)

turtle hat gesagt.:


> Also, bei mir geht das Connecten problemlos.
> 
> Du weisst schon das die Datenbank im Home-Verzeichnis erzeugt wird ? (bei mir C:\Users\testuser\Softwaretechnik.h2.db).
> 
> ...





Ja ich weiß, dass die Datenbank im home-Verzeichnis erzeugt wird. Bei mir wird eine .trace und .h2 Datei erstellt, aber keine .lock :/
Ich weiß nicht, was ich falsch gemacht habe..

Wie verwendet man squirrel?


----------



## turtle (8. Jan 2014)

> Wie verwendet man squirrel?


Hier ganz kurz ein paar Sätze.
Natürlcih downloaden und squirrel-sql.bat starten
Dann

Driver konfigurieren
H2 Unter ExtraClasspath den jdbc-Treiber von h2 hinzufügen
Alias einrichten
Dieser neue Alias verwendet h2 Treiber
Du gibst die URL jdbc... an, die du schon kennst.
Connect sollte funktionieren.
Im Dateisystem kannst du prüfen, das Datenbank erzeugt wurd.
in Squirrel auf die SQL-Seite gehen
create table-Statement eingeben und laufen lassen
Im Dateisystem kannst du prüfen, das lock-Datei angelegt wirrd


----------



## Rawan (8. Jan 2014)

turtle hat gesagt.:


> Also, bei mir geht das Connecten problemlos.
> 
> Du weisst schon das die Datenbank im Home-Verzeichnis erzeugt wird ? (bei mir C:\Users\testuser\Softwaretechnik.h2.db).
> 
> ...






turtle hat gesagt.:


> Also, bei mir geht das Connecten problemlos.
> 
> Du weisst schon das die Datenbank im Home-Verzeichnis erzeugt wird ? (bei mir C:\Users\testuser\Softwaretechnik.h2.db).
> 
> ...





Ja ich weiß, dass die Datenbank im home-Verzeichnis erzeugt wird. Bei mir wird eine .trace und .h2 Datei erstellt, aber keine .lock :/
Ich weiß nicht, was ich falsch gemacht habe..
Danke trotzdem  Ich werde es nochmal versuchen.

Kann mir jemand vielleicht sagen, ob ich in die GUI SQL-Befehle benutzen darf? Ich meine, wenn ich z.B. den vom Benutzer eingegebenen Text aus Textfelder einlesen möchte und diese dann gleich in die Datenbank speichern möchte. Benötige ich hierfür SQL-Befehle in der GUI (oder muss ich in der Datenbank die Methoden mit den SQL-Befehlen implementieren/erzeugen)? Und wenn ja, kann mir vielleicht jemand ein Beispiel machen, wie ich das realisiere?
Also kann ich das einfach als ActionListener für die Textfelder machen und darin einfach einen Scanner einbauen und anschließend noch den SQL-Befehl zum speichern des eingelesenen Textes? Oder wie funktioniert das?

Meine Idee wäre folgende:


```
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.Scanner;
import javax.swing.JLabel;

// z.B. ich habe ein Textfeld, in dem eine Matrikelnummer eingelesen werden soll
fieldMatrikelnr.setText("");
fieldMatrikelnr.setBounds(50, 340, 180, 20);
add(fieldMatrikelnr);
fieldMatrikelnr.addActionListener(new ActionListener() {
	public void actionPerformed(ActionEvent e) {
              // hier den Scanner 
                try {
                     Scanner input = new Scanner(System.in);
                     while (input.hasNext()) {
                         System.out.println(input.next());
                   }
               } catch (FileNotFoundException e) {
                 System.out.println("Fehler");
                 e.printStackTrace();
              }

	//und SQL-Befehle: Einfügen der eingelesenen Matrikelnummer in die DB-Tabelle "Student"
              Class.forName("org.h2.Driver"); 

		conn = DriverManager.getConnection( 
				"jdbc:h2:~/Softwaretechnik", "", ""); 
		
              Statement stmt = conn.createStatement();
              stmt.executeUpdate("INSERT INTO student(Matrikelnummer) VALUES(input.next())"); //oder rufe ich hier anstatt von "input.next())" eine Methode auf, die den Scanner enthält?			
          }
});
```

Ich weiß meine Idee ist nicht ganz richtig, aber kann mir vielleicht jemand erklären, wie ich es anstatt von meinem Code realisieren könnte?
Ich weiß, dass ich den Treiber (h2) nicht in der GUI aufrufen soll, weil dies ja in das Paket für die Datenbank gehört, aber ich verstehe nicht, wie das mit dem Einlesen eines Textfeldes der GUI und das Speichern dieses eingelesenen Texts in die Datenbank, funktionieren sollte.
Kann mir jemand helfen?
Wäre über jede Hilfe dankbar 


P.S: Mein Post davor gilt nicht mehr (einfach ignorieren  )..Leider kann ich diesen nicht löschen.. :/


----------



## Rawan (8. Jan 2014)

turtle hat gesagt.:


> Hier ganz kurz ein paar Sätze.
> Natürlcih downloaden und squirrel-sql.bat starten
> Dann
> 
> ...




Danke..

Hast du meine Klasse "Database" aber auch in eclipse (oder was auch immer du verwendest) ausgeführt?
Öffnet sich dann von eclipse aus deine Datenbank (also die H2-Konsole) (bei Verwendung meiner Klasse "Database")?
Wird meine Tablle "Student" in der Datenbank bei dir erzeugt (Kannst du sie sehen?)?


----------



## turtle (8. Jan 2014)

> aus Textfelder einlesen möchte und diese dann gleich in die Datenbank speichern möchte


Davon rate ich DRINGEND davon ab.:bloed:

Dieses Problem nennt sich SQL-Injection und bedeutet das ein Benutzer ein Kommando sendet, was böse DInge tut (beispiel "select * from user; drop table user;")

Dies vermeidet man, indem man in Java Prepared-Statements einsetzt. Praktisch alle machen das so. Einige Hobbyprogrammier basteln sich SQL-Befehl via Strings zusammen. Pfui:shock:


> Benötige ich hierfür SQL-Befehle in der GUI


Ebenfalls rate ich DRINGEND davon ab.:bloed:

Eine GUI sollte nichts mit SQL zu tun haben. Das zeugt von extrem schlechter Trennung von View(GUI) und Backend (Datenbank).


----------



## Rawan (8. Jan 2014)

Ok, danke für deine Meinung 
Aber könntest du mir Schritt für Schritt erklären, wie ich das Einlesen eines Textfeldes und anschließendem Speichern in die Datenbank des eingelesenen Textes sonst realisieren könnte? Geht das Einlesen nicht mit Hilfe von ActionListener (in dem der Scanner dann in der actionPerformed() drin ist..so wie ich es im Beispiel gemacht habe) ?
Am besten an einem Beispiel..Wäre nett...
Vielleicht könntest du mein Textfeld für die Matrikelnummer verwenden und anhand von diesem das komplette Beispiel zeigen?


----------



## turtle (9. Jan 2014)

Nein, ich kann nicht die "ganze" Arbeit für dich tun

Ich kann dir als Hinweis geben, das man Software häufig in 3 Schichten (Layer) aufbaut. Als "oberster" Layer ist hier die GUI zu nennen. Als zweiter Layer ist die Business-Logik. Und der dritte Layer ist Backend, also Datenzugriff mit Datenbank. Normalerweise sollte ein Layer nur mit dem nächst tieferen kommunizieren.

Bei vielen Systemen sind die verschieden Layer auch auf verschiedenen Rechner eingerichtet. GUI zum Beispiel im Browser, Business-Logik im Application-Server und Backend auf Datenbank-Cluster.

Zwar stimmt es, das du in einer Swing-GUI ein JTextField oder JButton hast. Natürlich hast du dann auch eine Action, die sich darum kümmert "etwas" zu tun. 

Nichts spricht aber dagegen ein weiteres Objekt (aus Business-Ebene) zu erzeugen oder anzusprechen, dieses "Etwas" zu tun. Die Businesslogik spricht daraufhin mit der Datenbank und liefert das Ergebnis an die Businesslogik und die dann im Endeffekt an die GUI.

Der Vorteil dieses Aufbaus ist unter anderem eine lose Kopplung zwischen den Objekten, So solltest du beispielsweise die DB gegen eine andere tauschen können und Änderungen sind definitiv nicht in der GUI zu machen.


----------

