# MAX und ResultSet#next



## The_S (1. Aug 2006)

Tach,

ich möchte den höchsten Wert einer Spalte in einer Tabelle rausfinden, dazu habe ich folgende Methoden geschrieben:


```
public int getNextID(String table, String id) {
		
		try {
			ResultSet rs = getQuery("SELECT MAX(" + id + ") FROM " + table);
			if (rs.next()) {
				return rs.getInt(1);
			}
		}
		catch (SQLException e) {
			e.printStackTrace();
		}
		return 0;
	}

	public ResultSet getQuery(String statement) {
		
		try {
			Statement stmt = conn.createStatement();
			ResultSet rs = stmt.executeQuery(statement);
			return rs;
		}
		catch (SQLException e) {
			e.printStackTrace();
			return null;
		}
	}
```

funktioniert auch wunderbar, aber nur wenn ich wie man sieht ein rs.next() miteinbaue. Lasse ich das rs.next() weg bekomme ich eine SQLException geworfen. Aber mit diesem Statement sollte ich ja eigentlich nur den höchsten Wert zurückbekommen und somit auch nur einen Datensatz im ResultSet haben.

Hoffe mir kann das jemand erklären!

Danke!


----------



## AlArenal (1. Aug 2006)

API hat gesagt.:
			
		

> A ResultSet object maintains a cursor pointing to its current row of data. Initially the cursor is positioned *before* the first row.



Daraus folgt, dass man ein #next machen muss, um überhaupt auf die erste Position zu kommen. Oder ein #first und schauen, ob true geliefert wird.


----------



## The_S (1. Aug 2006)

ah, ok. Wer lesen kann ist klar im Vorteil 

[edit] und wie bekomm ich jetzt raus, ob überhaupt etwas gefunden wurde? Also ob das ResultSet leer ist? Mit isLast() will ich nicht unbedingt arbeiten, weil das ja laut API recht performance-fressend sein kann :?


----------



## Murray (1. Aug 2006)

Wenn nichts gefunden wurde, dann sollte bereits das erste rs.next() false liefern.


----------



## The_S (1. Aug 2006)

Murray hat gesagt.:
			
		

> Wenn nichts gefunden wurde, dann sollte bereits das erste rs.next() false liefern.



Gibt MAX aufjedenfall 0 zurück wenn nichts gefunden wurde (nutze HSQLDB)? Dann würde das nämlich meine Verwirrung erklären


----------



## AlArenal (1. Aug 2006)

Probier die Abfrage doch zu Fuß auf ner leeren Tabelle aus und du dürftest feststellen, dass das Statement NULL liefert. Entsprechend wird das ResultSet keine Einträge haben.


----------



## The_S (1. Aug 2006)

Hm, ok. next() scheint zu funktionieren. Danke euch!


----------



## thE_29 (1. Aug 2006)

Ich will nix sagen, aber das ist PFUI!!!

1. resultsets werden mit einem einfachen .close() net immer geschlossen!!

Dh, wenn auf dem resultset noch 100 Sätze liegen würden, du aber nur den ersten ausliest und rs.close() sagst, ist dieser gar nicht zu!

Deswegen empfiehlt es sich bei ResultSets und Prepared/Statements close Methoden zu schreiben!

2. Wenn du das statement offen lässt, braucht das jedes mal eine Verbindung und irgendwann sind alle weg!

Dh, 

try {
         Statement stmt = conn.createStatement();
         ResultSet rs = stmt.executeQuery(statement);
         return rs;
      } 

sowas ist nie zum Empfehlen, da das statement immer offen bleibt!

Mann sollte auch immer mit finally arbeiten und die ResultSets vor den Statements closen

Bsp.:


```
pubic static void _close(ResultSet rs)
{
try{
if(rs != null)
{
   while (rs.next()) ; //; hier also einfach nur durchgehen
   rs.close();
}
}catch(Exception ex)
{ ex.printStackTrace(); } //musst du selber entscheiden ob dich das hier interessieren würde
}

public static void _close(Statement stm)
{
  try{
    if(stm != null)
      stm.close();
  }
  catch(Exception ex)
  { }
}

public static void _close(PreparedStatement pstm)
{
  try{
    if(pstm != null)
      pstm.close();
  }
  catch(Exception ex)
  { }
}


public int getNextID(String table, String id) {
      
   Statement stm = null;
   ResultSet rs = null;
      try {
 stm = conn.createStatement();
  rs = stm.executeQuery("SELECT MAX(" + id + ") FROM " + table);
         if (rs.next()) {
            return rs.getInt(1);
         }
      }
      catch (SQLException e) {
         e.printStackTrace();
      }
      finally{
      _close(rs);
      _close(stm);
}
      return 0;
   }
```

Durch die Methoden kann man das immer im finally Block schreiben ohne nochmals try/catch einbauen zu müssen!


Zwar fällt das bei kleinern Anwendungen net so ins Gewicht, aber wennst dann doch mal größer wird und viel geschrieben wird, kann genau sowas zu einem Problem führen!!


----------



## The_S (2. Aug 2006)

Hey, danke für die Antwort. Das war bis jetzt mehr als Beispielcode gedacht, aber ich hab in der Tat immer "nur" einfach geclosed .

Wenn ich mir dein Beispiel mal anschaue, dann wird das ResultSet und das Statement nur geclosed wenn das ResultSet leer ist!?


----------



## thE_29 (2. Aug 2006)

Naja, das Statement könnte sogar geclosed werden!

Aber das resultset wird wirklich nur dann geclosed, wenn es leer ist!

Bei Oracle kann man auf die offenen Cursor abfragen und da bin ich auf das draufgekommen!


----------



## The_S (2. Aug 2006)

OK, danke. Dürfte soweit alles geklärt sein


----------

