# Problem mit Access abfrage



## Dagobert (23. Jun 2008)

So ich habe auch nochmal ein par Fragen zu der DB.
Ich habe versucht die ID als rückgabewert zu bekommen, soblad ich ein neuen Datensatz einfüge. Nur leider geht jetzt gar nichts mehr mit folgender Fehlermeldung:


> Exception in thread "main" java.sql.SQLException: Invalid Cursor Type.
> at sun.jdbc.odbc.JdbcOdbcStatement.initialize(Unknown Source)
> at sun.jdbc.odbc.JdbcOdbcConnection.createStatement(Unknown Source)
> at Datenbank.HDR_Datenbank.openDB(HDR_Datenbank.java:17)
> at Datenbank.HDR_Datenbank.main(HDR_Datenbank.java:60)


Und wie kann ich nur das Datum in einer Access Datenbank speichern?
Mein Code:

```
package Datenbank;

import java.sql.*;
import java.util.Date;
import java.util.Vector;

public class HDR_Datenbank {
	private static Connection con;
	private static Statement stmt;
	private static ResultSet rs;
	// Methode zum Verbinden mit der Herr der Ringe Datenbank
	public static void openDB() throws SQLException, ClassNotFoundException {
		Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
		con = DriverManager
				.getConnection("jdbc:odbc:DRIVER={Microsoft Access Driver (*.mdb)};DBQ=resourcen/hdr.mdb");

		stmt = con.createStatement(Statement.CLOSE_ALL_RESULTS, Statement.RETURN_GENERATED_KEYS);
	}
	// Methoden zur Abfrage der Optionen
	public static String[] abfrageOptionen() {
		try {
			rs = stmt.executeQuery("SELECT * FROM Optionen");
			ResultSetMetaData rsmd = rs.getMetaData();
	  		int clmCnt = rsmd.getColumnCount();
	  		String[] erg = new String[clmCnt];
			while(rs.next()){
				for(int i = 0; i < erg.length; i++){
					erg[i] = rs.getString(i+1);
				}
			}
			return erg;
		} catch (SQLException e) {
			System.out.println("Fehler beim laden der Datenbank!");
			e.printStackTrace();
			return null;
		}
	}
	// Methode zum hinzufügen eines neuen Profils
	public static void addNewProfil(String name){
		try {
			Date date = new Date();
			System.out.println(date);
			int key = -1;
			stmt.execute("INSERT INTO Profil VALUES ('"+name+"','0','0','"+date+"','"+date+"'))", key);
			System.out.println("Key: " + key);
			stmt.executeUpdate("UPDATE Optionen SET LastProfil = " + key);
		} catch (SQLException e) {
			e.printStackTrace();
			System.out.println("Fehler beim laden der Datenbank!");
		}
	}
	
	public static void closeDB() throws SQLException {
		rs.close();
		stmt.close();
		con.close();
	}
	
	public static void main(String argv[]) throws SQLException, ClassNotFoundException{
		HDR_Datenbank.openDB();
		HDR_Datenbank.addNewProfil("Test");
		HDR_Datenbank.closeDB();
	}
}
```


----------



## Guest (23. Jun 2008)

Die Fehlermeldung beschreibt doch, was falsch ist. Der folgende Aufruf ist falsch. Lese in der Beschreibung 
zu createStatement, was die Parameter zu bedeuten haben und welche Werte möglich sind.
	
	
	
	





```
stmt = con.createStatement(Statement.CLOSE_ALL_RESULTS, Statement.RETURN_GENERATED_KEYS);
```
Verwende am besten PreparedStatements, dann hast du den Ärger mit unterschiedlicher Formattierung nicht,
das ganze wird auch übersichtlicher. Bennen auch alle Spalten, die du bei Insert einfügst, das schützt dich vor 
bösen Überraschungen, wenn du die Datenbank änderst und es ist auch besser sofort im Code erkennen zu 
können, was gespeicher wird.


----------



## Dagobert (24. Jun 2008)

Ja der Fehler liegt da.
Ich weis nur nicht wie ich ihn umgehen kann. Ich brauche ja eingetlich nur 
	
	
	
	





```
Statement.RETURN_GENERATED_KEYS
```
 aber wie stelle ich das an. Ich kann den anderen Parameter ja nicht null oder 0 setzten. Aber was soll ich denn da reinschreiben.
Ich habe in der API geguckt, aber ich weis trozdem nichts passendes.

mfg Dagobert

auchja hast du auch ne lösung für mein Datum  ?


----------



## FArt (24. Jun 2008)

Vielleicht ging die Antwort ja unter:


> Verwende am besten PreparedStatements



Nachdem du hier kein Hexenwerk veranstaltest, könntest du von einem Tutorial profitieren:

http://java.sun.com/docs/books/tutorial/jdbc/index.html


----------



## Dagobert (24. Jun 2008)

So ich habe schonmal eine Methode mit PreparedStatment angepasst.
Ist dies nun besser?

```
// Methode zum hinzufügen eines neuen Profils
	public static void addNewProfil(String name){
		try {
			int key = -1;
			Date date = new Date();
			Timestamp timestamp = new Timestamp(date.getTime());
			PreparedStatement updateProfiel = con.prepareStatement(
			"INSERT INTO Profil (Name, Siege, Niederlagen, Anlegedatum, LetzterLogin) VALUES (?,0,0,?,?)");
			updateProfiel.setString(1, name);
			updateProfiel.setTimestamp(2, timestamp);
			updateProfiel.setTimestamp(3, timestamp);
			updateProfiel.executeUpdate();
			System.out.println(key);
		} catch (SQLException e) {
			e.printStackTrace();
			System.out.println("Fehler beim laden der Datenbank!");
		}
	}
```
Nur leider scheiterts noch immer an der Rückgabe der ID. Kann das sein das der Treiber keine 
	
	
	
	





```
PreparedStatement.RETURN_GENERATED_KEYS.
```
unterstüzt.
Ich bekommen immer sobald ich ihn jetzt einbaue eine 





> java.lang.UnsupportedOperationException


Stimmt meine vermutung? Habe dazu auch schon hinweise im Forum gefunden.
Wie kann ich den dann an meinene letzte ID kommen?


----------



## yajp (24. Jun 2008)

Hallo Hagobert,
stimmt kannst Du da nicht verwenden.
Um bei M$ Access an den gerade generierten Autowert zu kommen kannst Du 

```
SELECT @@IDENTITY
```
 verwenden.
Einfach mit  Statement.executeQuery() ausfuehren und das Ergebnis auslesen.


Soviel ich weiss musst Du das aber vor einem Commit machen (hab mit Access jetzt länger nicht mehr gearbeitet).
hth

Grüsse


----------



## Dagobert (24. Jun 2008)

Ok danke für den Tipp
Was soll ich machen?


> Soviel ich weiss musst Du das aber vor einem Commit machen (hab mit Access jetzt länger nicht mehr gearbeitet).


 :?:


----------



## Gast (24. Jun 2008)

In der createStatement-Anweisung solltest Du Konstante von "ResultSet" und nicht von "Statement" verwenden, dadurch hast Du ungewollte Zahlwerte.

Gruß wicki


----------



## Dagobert (24. Jun 2008)

So läuft läuft

vielen Dank für eure Hilfe
Ist der Code den so in ordnung oder hab ihr noch ein par Anmerkungen?

```
// Methode zum hinzufügen eines neuen Profils
	public static void addNewProfil(String name){
		try {
			int key = -1;
			Date date = new Date();
			Timestamp timestamp = new Timestamp(date.getTime());
			PreparedStatement updateProfiel = con.prepareStatement(
				"INSERT INTO Profil (Name, Siege, Niederlagen, Anlegedatum, LetzterLogin) VALUES (?,0,0,?,?)");
			updateProfiel.setString(1, name);
			updateProfiel.setTimestamp(2, timestamp);
			updateProfiel.setTimestamp(3, timestamp);
			updateProfiel.executeUpdate();
			updateProfiel.clearParameters();
			rs = stmt.executeQuery("SELECT @@IDENTITY");
			rs.next();
			key = rs.getInt(1);
			updateProfiel = con.prepareStatement("UPDATE Optionen Set LastProfil = ?");
			updateProfiel.setInt(1, key);
			updateProfiel.executeUpdate();
		} catch (SQLException e) {
			e.printStackTrace();
			System.out.println("Fehler beim laden der Datenbank!");
		}
	}
```
mfg. Dagobert


----------



## Guest (24. Jun 2008)

Verwende direkt die generierten PKs, statt irgendwelche Exoten aus MS-Access zu verwemden
	
	
	
	





```
public static int addNewProfil(String name) throws DaoException {
   PreparedStatement stmt = null;
   try {
      stmt = con.prepareStatement(
         "INSERT INTO Profil (Name, Siege, Niederlagen, Anlegedatum, LetzterLogin) "
        +"VALUES (?,0,0,CURRENT_TIMESTAMP(),CURRENT_TIMESTAMP())"
        , Statement.RETURN_GENERATED_KEYS
      );
      stmt.setString(1, name);
      stmt.executeUpdate();
      ResultSet rs = stmt.getGeneratedKeys();
      if(!rs.next()) {
         // Kein PK, dann läuft hier was schief
         throw new DaoException("007", "Fehler beim Erstellen von ....");
      }
      return rs.getInt(1);
   }
   catch(SQLException e) {
      Logger
      throw new DaoException(e);
   }
   finally {
      if(stmt != null) {
         try {
            stmt.close();
         }
         catch(SQLException e) {
            // Sollte nie kommen und wenn, dann hast du an zig anderen Stellen ein Problem.
            throw new DaoException(e);
         }
      }
   }
}
```
Das Update für Optionenen gehört in eine getrennte Methode.


----------



## Dagobert (24. Jun 2008)

Hm... mein Access weigert sich immer noch
	
	
	
	





```
Statement.RETURN_GENERATED_KEYS
```
 azunehmen.
Und auch 
	
	
	
	





```
CURRENT_TIMESTAMP()
```
 nimmt er nicht. oO
Ich habe als DB nur eine Access mappe XD und kein SQL Server o.a.


----------

