System.gc() ?

Hi,

Es sind keine Pakete von J2EE dabei. Eine Record-Klasse kannst Du leicht selbst schreiben. Sie kapselt den Zugriff auf die Datenbank.

Ich würde stattdessen eher eine Tableklasse schreiben, mit den einzelnen Methoden

int getColumnCount();
String getValue(int column);
String getValue(String columnName);
String getColumnName(int column);
long getRowCount();
boolean moveToRow(long row);

oder meinetwegen auch

String valueAt(long row, int column);

Den SelectString kann man schon bei der Konstruktion mitgeben. Das Paging-Model bedient sich dann aus dieser Klasse ( die am besten Ihrerseits die Zeilen puffert). Die Klasse "ArrowIcon" ist nur zum malen auf die Buttons da.

Habe leider etwas Stress, sonst würde ich mal eine Lösung schreiben. Vielleicht nächste Woche.

Gruß

Danke nochmal für deine Mühe. Bei meiner Lösung habe ich die Tableklasse so implementiert, dass Sie alle Daten in ein Array reinschreibt. Auf diese Art und Weise, kann ich mir zwar sehr viel größere Tabellen anzeigen lassen, als innerhalb einer einzigen ScrollPane aber bei wirklich großen Tabellen hab ich natürlich immernoch das Speicherproblem. Meine Frage ist wie kann ich die Methoden boolean moveToRow(long row); und String valueAt(long row, int column); ohne scrollable Resultsets implementieren?
 
Aus aktuellem Anlass (Nachfrage) führe ich diesen Thread weiter...

Zum Problem:

Ich hatte Dir ein SQL-Beispiel gepostet, mit dem Du die Daten "päckchenweise" aus der Datenbank auslesen kannst. Wenn Du gemäß meines Beispiels im SQL-Statement Zeilennummern erzeugst, kannst Du mit einer einfachen Abfrage jeweils so viele Datensätze lesen, wie Du verarbeiten kannst.

Hier nochmal der SQLString:

SELECT emp_id, lname, fname, job_id,
(SELECT COUNT(*) FROM employee e2 WHERE e2.lname <= e.lname AND e2.job_id = 10) AS rownumber
FROM employee e
WHERE job_id = 10
ORDER BY lname


Der Unterselect "(SELECT COUNT(*) FROM employee e2 WHERE e2.lname <= e.lname AND e2.job_id = 10) AS rownumber" erzeugt eine Zeilennummer.

Mache daraus einen View (Abfrage), dann kannst du einen Select auf den view Ausführen, hast aber immer zeilennummern in der Abfrage.

Dadurch kannst du mit
Select * from MyView where rownumber between x and y

die Daten paketweise lesen. Also nicht alle Daten auf einmal in ein Array packen, sondern das TableModel (oder wer auch immer) lädt bei Bedarf immer nur wenige hundert Zeilen über diesen View ein. damit können Deine Tabellen Terrabyte groß sein, Du liest nur was Du brauchst...

Gruß
 
Vielen Dank für Deine Antwort!

Mein Problem ist leider, dass der User meines ies die DB zur Laufzeit auswählt und auch SQL-Statements zur Laufzeit eingeben können soll. Von diesen Statements brauche ich denn das Ergebnis innerhalb meiner JTable, deshalb kann ich keine Views anlegen, weil ich eben vorher nicht weis wie die entsprechende DB aussieht.
Ich könnte höchstens versuchen die Strings mit den SQL-Statements auseinander zu nehmen und automatisch ein Feld mit der Zeilennummer in diese Statements einzufügen, aber allein schon bei dem Gedanken daran wird mir schlecht ;)
 
Hi,

wenn ich mal mehr Zeit habe, werde ich dem dem Problem mal näher widmen. Aaaaber andere Leute haben das Problem ja auch. In der Regel wird es dadurch gelöst, dass man erst einen Select count(*) auf die where -Klausel los läßt, dann beim Überschreiten einer Schwelle den Anwender zur Präzessierung der Auswahl auffordert.

Ist es möglich mehr über die Hintergründe zu erfahren? Möglicherweise, kann man das Problem ja an einer ganz anderen Stelle lösen.

Meine Neugier ist geweckt.

Grüße
 
Also... ich hab mich dann mal entschlossen für verschiedene DBMSs verschiedene PagingModels zu schreiben.

hier einmal das zu MSSQL geht auch mit Oracle:
Code:
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;

import javax.swing.table.*;
import javax.swing.*;
import java.awt.event.*;

public class MSSQLPagingModel extends AbstractTableModel
{
	private Connection conn;
	private ResultSet rs;
	private ResultSetMetaData rsmd;
	private String statement;
	
	protected int pageSize;
	protected int pageOffset;
	private int row;
	private int rowCount;
	private int columnCount;
	private String[] columnNames;
	protected String[][] data;

	public MSSQLPagingModel(String statement)
	{
		this.statement = statement;
		conn = DBConnection.getConnection();
		row = 0;
		pageOffset = 0;
		pageSize = 100;
		try 
		{
			rs = DBConnection.executeQuery(statement);
			rsmd = rs.getMetaData();
			//Zeilenzahl berechnen
			rs.last();
			rowCount = rs.getRow();
			rs.beforeFirst();
			//////
			columnCount = rsmd.getColumnCount();
			columnNames = new String[columnCount];
			for (int i=0; i<columnCount; i++)
			{
				columnNames[i] = rsmd.getColumnName(i+1);
			}
			data = new String[pageSize][columnCount];
			int i=0;
			while (rs.next() && i<pageSize)
			{
				for (int j=0; j<columnCount; j++)
				{
					data[i][j]= rs.getString(j+1);					
				}
				i++;
			}
			rs.close();
		}
		catch (SQLException e) 
		{
			e.printStackTrace();
		}
	}

	//Return values appropriate for the visible table part.
	public int getRowCount() { return Math.min(pageSize, rowCount); }
	public int getColumnCount() { return columnCount; }

	// Work only on the visible part of the table.
	public Object getValueAt(int row, int col) 
	{
	 return data[row][col];
	}
	public String getColumnName(int col) 
	{
	 return columnNames[col];
	}
	//Use this method to figure out which page you are on.
	public int getPageOffset() { return pageOffset; }

	public int getPageCount() 
	{ 
	 return (int)Math.ceil((double)rowCount / pageSize);
	}

	// Use this method if you want to know how big the real table is . . . we
	// could also write "getRealValueAt()" if needed.
	public int getRealRowCount() 
	{
	 return rowCount;
	}

	public int getPageSize() { return pageSize; }
	
	public void setPageSize(int s) 
	{ 
	 if (s == pageSize) { return; }
	 int oldPageSize = pageSize;
	 pageSize = s;
	 pageOffset = (oldPageSize * pageOffset) / pageSize;
	 fireTableDataChanged();
	 if (pageSize < oldPageSize) 
	 {
	   fireTableRowsDeleted(pageSize, oldPageSize - 1);
	 }
	 else 
	 {
	   fireTableRowsInserted(oldPageSize, pageSize - 1);
	 }
	}

	//Update the page offset and fire a data changed (all rows).
	public void pageDown() 
	{
	 if (pageOffset < getPageCount() - 1) 
	 {
	   pageOffset++;
	   //System.out.println(pageOffset);
	   try 
	   {
		   rs = DBConnection.executeQuery(statement);
		   rs.first();
		   rs.relative((pageOffset*pageSize)-1);
		   int i=0;
		   while (rs.next() && i<pageSize)
		   {
			   for (int j=0; j<columnCount; j++)
			   {
				   data[i][j] = rs.getString(j+1);
			   }
			   i++;
		   }
		   //letzte Seite mit leerzeichen füllen
		   for (int k=i; k<pageSize; k++)
		   {
			   for (int j=0; j<columnCount; j++)
			   {
				   data[k][j] = "";
			   }
		   }
	   }
	   catch (SQLException e)
	   {
		   e.printStackTrace();
	   }
	   fireTableDataChanged();
	 }
	}

//	 Update the page offset and fire a data changed (all rows).
	public void pageUp() 
	{
	 if (pageOffset > 0) 
	 {
	   pageOffset--;
	   //System.out.println(pageOffset);
	   try 
	   {
		   rs = DBConnection.executeQuery(statement);
		   rs.first();
		   rs.relative((pageOffset*pageSize)-1);
		   //System.out.println(test);
		   int i=0;
		   while (rs.next() && i<pageSize)
		   {
			   for (int j=0; j<columnCount; j++)
			   {
				   data[i][j] = rs.getString(j+1);
			   }
			   i++;
		   }
	   }
	   catch (SQLException e)
	   {
		   e.printStackTrace();
	   }
	   fireTableDataChanged();
	 }
	}

//	 We provide our own version of a scrollpane that includes
//	 the page up and page down buttons by default.
	public static JScrollPane createPagingScrollPaneForTable(JTable jt) 
	{
	 JScrollPane jsp = new JScrollPane(jt);
	 TableModel tmodel = jt.getModel();
	 
	 // Don't choke if this is called on a regular table . . .
	 if (! (tmodel instanceof MySQLPagingModel || tmodel instanceof MSSQLPagingModel || tmodel instanceof PagingModel)) 
	 {
	   return jsp;
	 }

	 // Okay, go ahead and build the real scrollpane
	 final MSSQLPagingModel model = (MSSQLPagingModel)tmodel;
	 final JButton upButton = new JButton(/*new ArrowIcon(ArrowIcon.UP)*/"UP");
	 upButton.setEnabled(false);  // starts off at 0, so can't go up
	 final JButton downButton = new JButton(/*new ArrowIcon(ArrowIcon.DOWN)*/"DOWN");
	 if (model.getPageCount() <= 1) 
	 {
	   downButton.setEnabled(false);  // One page...can't scroll down
	 }

	 upButton.addActionListener(new ActionListener() 
	 {
	   public void actionPerformed(ActionEvent ae) 
	   {
	     model.pageUp();

	     // If we hit the top of the data, disable the up button.
	     if (model.getPageOffset() == 0) 
	     {
	       upButton.setEnabled(false);
	     }
	     downButton.setEnabled(true);
	   }
	 } );

	 downButton.addActionListener(new ActionListener() {
	   public void actionPerformed(ActionEvent ae) {
	     model.pageDown();

	     // If we hit the bottom of the data, disable the down button.
	     if (model.getPageOffset() == (model.getPageCount() - 1)) {
	       downButton.setEnabled(false);
	     }
	     upButton.setEnabled(true);
	   }
	 } );

	 // Turn on the scrollbars; otherwise we won't get our corners.
	 jsp.setVerticalScrollBarPolicy
	     (ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
	 jsp.setHorizontalScrollBarPolicy
	     (ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);

	 // Add in the corners (page up/down).
	 jsp.setCorner(ScrollPaneConstants.UPPER_RIGHT_CORNER, upButton);
	 jsp.setCorner(ScrollPaneConstants.LOWER_RIGHT_CORNER, downButton);

	 return jsp;
	}
}

Der obige code funktioniert leider nicht mit MySQL. Da kommt immernoch dieser Speichererror. Also hab ich für MySQL ein eigenes PageingModel geschrieben:

Code:
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;

import javax.swing.table.*;
import javax.swing.*;
import java.awt.event.*;

public class MySQLPagingModel extends AbstractTableModel
{
	private Connection conn;
	private ResultSet rs;
	private ResultSetMetaData rsmd;
	private String statement;
	
	protected int pageSize;
	protected int pageOffset;
	private int row;
	private int rowCount;
	private int columnCount;
	private String[] columnNames;
	protected String[][] data;

	public MySQLPagingModel(String statement)
	{
		this.statement = statement;
		conn = DBConnection.getConnection();
		row = 0;
		pageOffset = 0;
		pageSize = 100;
		try 
		{
			rs = DBConnection.executeQuery("SELECT * FROM ("+statement+") AS tmp LIMIT 0, "+pageSize);
			rsmd = rs.getMetaData();
			//Zeilenzahl berechnen
			Statement stm2 = conn.createStatement();
			ResultSet rs2 = stm2.executeQuery("SELECT COUNT(*) FROM ("+statement+") AS tmp");
			rs2.next();
			rowCount = rs2.getInt(1);
			rs2.close();
			stm2.close();
			//////
			columnCount = rsmd.getColumnCount();
			columnNames = new String[columnCount];
			for (int i=0; i<columnCount; i++)
			{
				columnNames[i] = rsmd.getColumnName(i+1);
			}
			data = new String[pageSize][columnCount];
			int i=0;
			while (rs.next())
			{
				for (int j=0; j<columnCount; j++)
				{
					data[i][j]= rs.getString(j+1);					
				}
				i++;
			}
			rs.close();
		}
		catch (SQLException e) 
		{
			e.printStackTrace();
		}
	}

	//Return values appropriate for the visible table part.
	public int getRowCount() { return Math.min(pageSize, rowCount); }
	public int getColumnCount() { return columnCount; }

	// Work only on the visible part of the table.
	public Object getValueAt(int row, int col) 
	{
	 //int realRow = row + (pageOffset * pageSize);
	 return data[row][col];
	}
	public String getColumnName(int col) 
	{
	 return columnNames[col];
	}
	//Use this method to figure out which page you are on.
	public int getPageOffset() { return pageOffset; }

	public int getPageCount() 
	{ 
	 return (int)Math.ceil((double)rowCount / pageSize);
	}

	// Use this method if you want to know how big the real table is . . . we
	// could also write "getRealValueAt()" if needed.
	public int getRealRowCount() 
	{
	 return rowCount;
	}

	public int getPageSize() { return pageSize; }
	/*
	public void setPageSize(int s) 
	{ 
	 if (s == pageSize) { return; }
	 int oldPageSize = pageSize;
	 pageSize = s;
	 pageOffset = (oldPageSize * pageOffset) / pageSize;
	 fireTableDataChanged();
	*/
	/*
	 if (pageSize < oldPageSize) {
	   fireTableRowsDeleted(pageSize, oldPageSize - 1);
	 }
	 else {
	   fireTableRowsInserted(oldPageSize, pageSize - 1);
	 }
	*/
	//}

	//Update the page offset and fire a data changed (all rows).
	public void pageDown() 
	{
	 System.out.println(pageOffset);
	 if (pageOffset < getPageCount() - 1) 
	 {
	   pageOffset++;
	   try 
	   {
		   rs = DBConnection.executeQuery("SELECT * FROM ("+statement+") AS tmp LIMIT "+(pageOffset*pageSize)+", "+pageSize);
		   int i=0;
		   while (rs.next() /*&& i<pageSize*/)
		   {
			   for (int j=0; j<columnCount; j++)
			   {
				   data[i][j] = rs.getString(j+1);
			   }
			   i++;
		   }
		   for (int k=i; k<pageSize; k++)
		   {
			   for (int j=0; j<columnCount; j++)
			   {
				   data[k][j] = "";
			   }
		   }
	   }
	   catch (SQLException e)
	   {
		   e.printStackTrace();
	   }
	   fireTableDataChanged();
	 }
	}

//	 Update the page offset and fire a data changed (all rows).
	public void pageUp() 
	{
	 System.out.println(pageOffset);
	 if (pageOffset > 0) 
	 {
	   pageOffset--;
	   try 
	   {
		   String test = "SELECT * FROM ("+statement+") AS tmp LIMIT "+(pageOffset*pageSize)+", "+pageSize;
		   rs = DBConnection.executeQuery(test);
		   System.out.println(test);
		   int i=0;
		   while (rs.next() /*&& i<pageSize*/)
		   {
			   for (int j=0; j<columnCount; j++)
			   {
				   data[i][j] = rs.getString(j+1);
			   }
			   i++;
		   }
	   }
	   catch (SQLException e)
	   {
		   e.printStackTrace();
	   }
	   fireTableDataChanged();
	 }
	}

//	 We provide our own version of a scrollpane that includes
//	 the page up and page down buttons by default.
	public static JScrollPane createPagingScrollPaneForTable(JTable jt) 
	{
	 JScrollPane jsp = new JScrollPane(jt);
	 TableModel tmodel = jt.getModel();
	 
	 // Don't choke if this is called on a regular table . . .
	 if (! (tmodel instanceof MySQLPagingModel || tmodel instanceof PagingModel)) 
	 {
	   return jsp;
	 }

	 // Okay, go ahead and build the real scrollpane
	 final MySQLPagingModel model = (MySQLPagingModel)tmodel;
	 final JButton upButton = new JButton(/*new ArrowIcon(ArrowIcon.UP)*/"UP");
	 upButton.setEnabled(false);  // starts off at 0, so can't go up
	 final JButton downButton = new JButton(/*new ArrowIcon(ArrowIcon.DOWN)*/"DOWN");
	 if (model.getPageCount() <= 1) 
	 {
	   downButton.setEnabled(false);  // One page...can't scroll down
	 }

	 upButton.addActionListener(new ActionListener() 
	 {
	   public void actionPerformed(ActionEvent ae) 
	   {
	     model.pageUp();

	     // If we hit the top of the data, disable the up button.
	     if (model.getPageOffset() == 0) 
	     {
	       upButton.setEnabled(false);
	     }
	     downButton.setEnabled(true);
	   }
	 } );

	 downButton.addActionListener(new ActionListener() {
	   public void actionPerformed(ActionEvent ae) {
	     model.pageDown();

	     // If we hit the bottom of the data, disable the down button.
	     if (model.getPageOffset() == (model.getPageCount() - 1)) {
	       downButton.setEnabled(false);
	     }
	     upButton.setEnabled(true);
	   }
	 } );

	 // Turn on the scrollbars; otherwise we won't get our corners.
	 jsp.setVerticalScrollBarPolicy
	     (ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
	 jsp.setHorizontalScrollBarPolicy
	     (ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);

	 // Add in the corners (page up/down).
	 jsp.setCorner(ScrollPaneConstants.UPPER_RIGHT_CORNER, upButton);
	 jsp.setCorner(ScrollPaneConstants.LOWER_RIGHT_CORNER, downButton);

	 return jsp;
	}
}

So das funktioniert zwar Theoretisch. Aber jeder Pagewechsel dauert ewig (so 30 - 45 sec) bei einer PageSize von 100. Irgendwie scheint der MySQL-Server die ergebnisse aber zu cachen oder irgendwelche temporären StoredProcedures anzulegen oder weiß der Geier. Auf jeden Fall geht das Angucken von Seiten, die ich schonmal angeguckt hab richtig schön schnell, auch wenn ich mein Prog zwischendurch schliesse und wieder neu öffne.

Meine Frage wäre, wieso ist das so lahm? Wie kann ich das schneller machen?

Und so aus mehr allgemeinem Interesse. Wie speichert der MySQL-Server welche Daten, dass ich so schnell darauf zugriff habe, wenn ich sie vorher schon irgendwann mal abgerufen habe? (Der kann ja nicht hunderte von Ergebnissmengen cachen oder etwa doch?)
 
Hi,

hier mal ein Schnellschuss aus der Hüfte... Ich würde die Statements, wenn es geht in PreparedStatements umwandeln. Dann werden Sie oft deutlich schneller ausgeführt.

Soweit ich weiss, muss bei einem Statement immer der SQL-String von dem DBMS geparst und ein Ausführungsplan erstellt werden. Wenn Du Glück hast, wird das Statement danach gecached.

Ein PreparedStatement macht das gleich und landet gleich im Cache. Es kann parametriesiert werden und sollte deswegen die Geschwindigkeit erhöhen...

Versuchs mal.

Gruss
 
Logisch da hätt ich auch mal drauf kommen können.
Aber, ich hab das jetzt gemacht und scheinbar scheinen preparedStatements in verbindung mit LIMIT nicht viel zu nützen. Denn jetzt hab ich ca. 15sec pro zu Ladender Seite. Allerding cacht der SQLServer jetzt nix mehr und so dauert der seitenaufbau immer 15sec.

Code:
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;

import javax.swing.table.*;
import javax.swing.*;
import java.awt.event.*;

public class MySQLPagingModel extends AbstractTableModel
{
	private Connection conn;
	private PreparedStatement preparedStatement;
	private ResultSet rs;
	private ResultSetMetaData rsmd;
	private String statement;
	
	protected int pageSize;
	protected int pageOffset;
	private int row;
	private int rowCount;
	private int columnCount;
	private String[] columnNames;
	protected String[][] data;

	public MySQLPagingModel(String statement)
	{
		this.statement = statement;
		conn = DBConnection.getConnection();
		row = 0;
		pageOffset = 0;
		pageSize = 100;
		try 
		{
			preparedStatement = conn.prepareStatement("SELECT * FROM ("+statement+") AS tmp LIMIT ?, ?");
			rs = DBConnection.executeQuery("SELECT * FROM ("+statement+") AS tmp LIMIT 0, "+pageSize);
			rsmd = rs.getMetaData();
			//Zeilenzahl berechnen
			Statement stm2 = conn.createStatement();
			ResultSet rs2 = stm2.executeQuery("SELECT COUNT(*) FROM ("+statement+") AS tmp");
			rs2.next();
			rowCount = rs2.getInt(1);
			rs2.close();
			stm2.close();
			//////
			columnCount = rsmd.getColumnCount();
			columnNames = new String[columnCount];
			for (int i=0; i<columnCount; i++)
			{
				columnNames[i] = rsmd.getColumnName(i+1);
			}
			data = new String[pageSize][columnCount];
			int i=0;
			while (rs.next())
			{
				for (int j=0; j<columnCount; j++)
				{
					data[i][j]= rs.getString(j+1);					
				}
				i++;
			}
			rs.close();
		}
		catch (SQLException e) 
		{
			e.printStackTrace();
		}
	}

	//Return values appropriate for the visible table part.
	public int getRowCount() { return Math.min(pageSize, rowCount); }
	public int getColumnCount() { return columnCount; }

	// Work only on the visible part of the table.
	public Object getValueAt(int row, int col) 
	{
	 return data[row][col];
	}
	public String getColumnName(int col) 
	{
	 return columnNames[col];
	}
	//Use this method to figure out which page you are on.
	public int getPageOffset() { return pageOffset; }

	public int getPageCount() 
	{ 
	 return (int)Math.ceil((double)rowCount / pageSize);
	}

	// Use this method if you want to know how big the real table is . . . we
	// could also write "getRealValueAt()" if needed.
	public int getRealRowCount() 
	{
	 return rowCount;
	}

	public int getPageSize() { return pageSize; }
	/*
	public void setPageSize(int s) 
	{ 
	 if (s == pageSize) { return; }
	 int oldPageSize = pageSize;
	 pageSize = s;
	 pageOffset = (oldPageSize * pageOffset) / pageSize;
	 fireTableDataChanged();
	*/
	/*
	 if (pageSize < oldPageSize) {
	   fireTableRowsDeleted(pageSize, oldPageSize - 1);
	 }
	 else {
	   fireTableRowsInserted(oldPageSize, pageSize - 1);
	 }
	*/
	//}

	//Update the page offset and fire a data changed (all rows).
	public void pageDown() 
	{
	 System.out.println(pageOffset);
	 if (pageOffset < getPageCount() - 1) 
	 {
	   pageOffset++;
	   try 
	   {
		   preparedStatement.setInt(1, (pageOffset*pageSize));
		   preparedStatement.setInt(2, pageSize);
		   rs = preparedStatement.executeQuery();
		   int i=0;
		   while (rs.next() /*&& i<pageSize*/)
		   {
			   for (int j=0; j<columnCount; j++)
			   {
				   data[i][j] = rs.getString(j+1);
			   }
			   i++;
		   }
		   for (int k=i; k<pageSize; k++)
		   {
			   for (int j=0; j<columnCount; j++)
			   {
				   data[k][j] = "";
			   }
		   }
	   }
	   catch (SQLException e)
	   {
		   e.printStackTrace();
	   }
	   fireTableDataChanged();
	 }
	}

//	 Update the page offset and fire a data changed (all rows).
	public void pageUp() 
	{
	 System.out.println(pageOffset);
	 if (pageOffset > 0) 
	 {
	   pageOffset--;
	   try 
	   {
		   //String test = statement+" LIMIT "+(pageOffset*pageSize)+", "+((pageOffset*pageSize)+pageSize);
		   //String test = "SELECT * FROM ("+statement+") AS tmp LIMIT "+(pageOffset*pageSize)+", "+pageSize;
		   //rs = DBConnection.executeQuery(test);
		   //System.out.println(test);
		   preparedStatement.setInt(1, (pageOffset*pageSize));
		   preparedStatement.setInt(2, pageSize);
		   rs = preparedStatement.executeQuery();
		   int i=0;
		   while (rs.next() /*&& i<pageSize*/)
		   {
			   for (int j=0; j<columnCount; j++)
			   {
				   data[i][j] = rs.getString(j+1);
			   }
			   i++;
		   }
	   }
	   catch (SQLException e)
	   {
		   e.printStackTrace();
	   }
	   fireTableDataChanged();
	 }
	}

//	 We provide our own version of a scrollpane that includes
//	 the page up and page down buttons by default.
	public static JScrollPane createPagingScrollPaneForTable(JTable jt) 
	{
	 JScrollPane jsp = new JScrollPane(jt);
	 TableModel tmodel = jt.getModel();
	 
	 // Don't choke if this is called on a regular table . . .
	 if (! (tmodel instanceof MySQLPagingModel || tmodel instanceof PagingModel)) 
	 {
	   return jsp;
	 }

	 // Okay, go ahead and build the real scrollpane
	 final MySQLPagingModel model = (MySQLPagingModel)tmodel;
	 final JButton upButton = new JButton(/*new ArrowIcon(ArrowIcon.UP)*/"UP");
	 upButton.setEnabled(false);  // starts off at 0, so can't go up
	 final JButton downButton = new JButton(/*new ArrowIcon(ArrowIcon.DOWN)*/"DOWN");
	 if (model.getPageCount() <= 1) 
	 {
	   downButton.setEnabled(false);  // One page...can't scroll down
	 }

	 upButton.addActionListener(new ActionListener() 
	 {
	   public void actionPerformed(ActionEvent ae) 
	   {
	     model.pageUp();

	     // If we hit the top of the data, disable the up button.
	     if (model.getPageOffset() == 0) 
	     {
	       upButton.setEnabled(false);
	     }
	     downButton.setEnabled(true);
	   }
	 } );

	 downButton.addActionListener(new ActionListener() {
	   public void actionPerformed(ActionEvent ae) {
	     model.pageDown();

	     // If we hit the bottom of the data, disable the down button.
	     if (model.getPageOffset() == (model.getPageCount() - 1)) {
	       downButton.setEnabled(false);
	     }
	     upButton.setEnabled(true);
	   }
	 } );

	 // Turn on the scrollbars; otherwise we won't get our corners.
	 jsp.setVerticalScrollBarPolicy
	     (ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
	 jsp.setHorizontalScrollBarPolicy
	     (ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);

	 // Add in the corners (page up/down).
	 jsp.setCorner(ScrollPaneConstants.UPPER_RIGHT_CORNER, upButton);
	 jsp.setCorner(ScrollPaneConstants.LOWER_RIGHT_CORNER, downButton);

	 return jsp;
	}
}
 
Hi,

dann weiss ich auch nicht weiter. Hört sich so an, als müsstest Du tief in den MySql abtauchen und das hat mit Java nix mehr zu tun. Die 15 bzw. 30 Sekunden wundern mich ehrlich gesagt ein wenig. Hast Du das mal nativ mit der MySQL-Console validiert?

Kannst Du die Daten denn nicht selbst cachen?

Wie auch immer, wenn Du eine Lösung findest, wäre ich sehr interessiert...

Gruß
 
So, hab jez ne einigermaßen akzeptable Lösung gefunden.
Hab statt "Select * From ("+statement+") as tmp LIMIT blabla.
Einfach nur "("+statement+") Limit blabla" gemacht. Jetzt gehts schön schnell. Aber die letzte Page wird leider bis zur pageSize aufgefüllt.
Wenn ich also z.B. (Select * From tabelle LIMIT 0, 150) LIMIT 0, 200; ausführe bekomme ich leider 200 ergebnisse und keine 150.
Da das aber nur in der Anzeige so ist und zum Weiterverarbeiten das original Statement was der user eingegeben hat ausgeführt wird ist das jetzt nicht so wichtig.

hier nochmal komplett:
Code:
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
//import java.util.List;

import javax.swing.table.*;
import javax.swing.*;
import java.awt.event.*;
//import java.awt.*;

public class MySQLPagingModel extends AbstractTableModel
{
	private Connection conn;
	private PreparedStatement preparedStatement;
	private ResultSet rs;
	private ResultSetMetaData rsmd;
	private String statement;
	
	protected int pageSize;
	protected int pageOffset;
	private int row;
	private int rowCount;
	private int columnCount;
	private String[] columnNames;
	//protected Record[] data;
	protected String[][] data;

	public MySQLPagingModel(String statement)
	{
		this.statement = statement;
		conn = DBConnection.getConnection();
		row = 0;
		pageOffset = 0;
		pageSize = 100;
		try 
		{
			preparedStatement = conn.prepareStatement("("+statement+") LIMIT ?, ?");
			rs = DBConnection.executeQuery("SELECT * FROM ("+statement+") AS tmp LIMIT 0, "+pageSize);
			//rs = DBConnection.executeQuery(statement);
			rsmd = rs.getMetaData();
			//Zeilenzahl berechnen
			Statement stm2 = conn.createStatement();
			ResultSet rs2 = stm2.executeQuery("SELECT COUNT(*) FROM ("+statement+") AS tmp");
			rs2.next();
			rowCount = rs2.getInt(1);
			rs2.close();
			stm2.close();
			//////
			columnCount = rsmd.getColumnCount();
			columnNames = new String[columnCount];
			for (int i=0; i<columnCount; i++)
			{
				columnNames[i] = rsmd.getColumnName(i+1);
			}
			data = new String[pageSize][columnCount];
			int i=0;
			while (rs.next())
			{
				for (int j=0; j<columnCount; j++)
				{
					data[i][j]= rs.getString(j+1);					
				}
				i++;
			}
			rs.close();
		}
		catch (SQLException e) 
		{
			e.printStackTrace();
		}
	}

	//Return values appropriate for the visible table part.
	public int getRowCount() { return Math.min(pageSize, rowCount); }
	public int getColumnCount() { return columnCount; }

	// Work only on the visible part of the table.
	public Object getValueAt(int row, int col) 
	{
	 //int realRow = row + (pageOffset * pageSize);
	 return data[row][col];
	}
	public String getColumnName(int col) 
	{
	 return columnNames[col];
	}
	//Use this method to figure out which page you are on.
	public int getPageOffset() { return pageOffset; }

	public int getPageCount() 
	{ 
	 return (int)Math.ceil((double)rowCount / pageSize);
	}

	// Use this method if you want to know how big the real table is . . . we
	// could also write "getRealValueAt()" if needed.
	public int getRealRowCount() 
	{
	 return rowCount;
	}

	public int getPageSize() { return pageSize; }
	/*
	public void setPageSize(int s) 
	{ 
	 if (s == pageSize) { return; }
	 int oldPageSize = pageSize;
	 pageSize = s;
	 pageOffset = (oldPageSize * pageOffset) / pageSize;
	 fireTableDataChanged();
	*/
	/*
	 if (pageSize < oldPageSize) {
	   fireTableRowsDeleted(pageSize, oldPageSize - 1);
	 }
	 else {
	   fireTableRowsInserted(oldPageSize, pageSize - 1);
	 }
	*/
	//}

	//Update the page offset and fire a data changed (all rows).
	public void pageDown() 
	{
	 System.out.println(pageOffset);
	 if (pageOffset < getPageCount() - 1) 
	 {
	   pageOffset++;
	   try 
	   {
		   //rs = DBConnection.executeQuery(statement+" LIMIT "+(pageOffset*pageSize)+", "+((pageOffset*pageSize)+pageSize));
		   //preparedStatement = conn.prepareStatement("SELECT * FROM ("+statement+") AS tmp LIMIT ?, ?");
		   preparedStatement.setInt(1, (pageOffset*pageSize));
		   preparedStatement.setInt(2, pageSize);
		   //rs = DBConnection.executeQuery("SELECT * FROM ("+statement+") AS tmp LIMIT "+(pageOffset*pageSize)+", "+pageSize);
		   rs = preparedStatement.executeQuery();
		   int i=0;
		   while (rs.next() /*&& i<pageSize*/)
		   {
			   for (int j=0; j<columnCount; j++)
			   {
				   data[i][j] = rs.getString(j+1);
			   }
			   i++;
		   }
		   rs.close();
		   for (int k=i; k<pageSize; k++)
		   {
			   for (int j=0; j<columnCount; j++)
			   {
				   data[k][j] = "";
			   }
		   }
	   }
	   catch (SQLException e)
	   {
		   e.printStackTrace();
	   }
	   fireTableDataChanged();
	 }
	}

//	 Update the page offset and fire a data changed (all rows).
	public void pageUp() 
	{
	 System.out.println(pageOffset);
	 if (pageOffset > 0) 
	 {
	   pageOffset--;
	   try 
	   {
		   //String test = statement+" LIMIT "+(pageOffset*pageSize)+", "+((pageOffset*pageSize)+pageSize);
		   //String test = "SELECT * FROM ("+statement+") AS tmp LIMIT "+(pageOffset*pageSize)+", "+pageSize;
		   //rs = DBConnection.executeQuery(test);
		   //System.out.println(test);
		   preparedStatement.setInt(1, (pageOffset*pageSize));
		   preparedStatement.setInt(2, pageSize);
		   rs = preparedStatement.executeQuery();
		   int i=0;
		   while (rs.next() /*&& i<pageSize*/)
		   {
			   for (int j=0; j<columnCount; j++)
			   {
				   data[i][j] = rs.getString(j+1);
			   }
			   i++;
		   }
		   rs.close();
	   }
	   catch (SQLException e)
	   {
		   e.printStackTrace();
	   }
	   fireTableDataChanged();
	 }
	}

//	 We provide our own version of a scrollpane that includes
//	 the page up and page down buttons by default.
	public static JScrollPane createPagingScrollPaneForTable(JTable jt) 
	{
	 JScrollPane jsp = new JScrollPane(jt);
	 TableModel tmodel = jt.getModel();
	 
	 // Don't choke if this is called on a regular table . . .
	 if (! (tmodel instanceof MySQLPagingModel || tmodel instanceof PagingModel)) 
	 {
	   return jsp;
	 }

	 // Okay, go ahead and build the real scrollpane
	 final MySQLPagingModel model = (MySQLPagingModel)tmodel;
	 final JButton upButton = new JButton(/*new ArrowIcon(ArrowIcon.UP)*/"UP");
	 upButton.setEnabled(false);  // starts off at 0, so can't go up
	 final JButton downButton = new JButton(/*new ArrowIcon(ArrowIcon.DOWN)*/"DOWN");
	 if (model.getPageCount() <= 1) 
	 {
	   downButton.setEnabled(false);  // One page...can't scroll down
	 }

	 upButton.addActionListener(new ActionListener() 
	 {
	   public void actionPerformed(ActionEvent ae) 
	   {
	     model.pageUp();

	     // If we hit the top of the data, disable the up button.
	     if (model.getPageOffset() == 0) 
	     {
	       upButton.setEnabled(false);
	     }
	     downButton.setEnabled(true);
	   }
	 } );

	 downButton.addActionListener(new ActionListener() {
	   public void actionPerformed(ActionEvent ae) {
	     model.pageDown();

	     // If we hit the bottom of the data, disable the down button.
	     if (model.getPageOffset() == (model.getPageCount() - 1)) {
	       downButton.setEnabled(false);
	     }
	     upButton.setEnabled(true);
	   }
	 } );

	 // Turn on the scrollbars; otherwise we won't get our corners.
	 jsp.setVerticalScrollBarPolicy
	     (ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
	 jsp.setHorizontalScrollBarPolicy
	     (ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);

	 // Add in the corners (page up/down).
	 jsp.setCorner(ScrollPaneConstants.UPPER_RIGHT_CORNER, upButton);
	 jsp.setCorner(ScrollPaneConstants.LOWER_RIGHT_CORNER, downButton);

	 return jsp;
	}
}
 
Eine Frage hätt ich da noch.
Wo hastn Du das ArrowIcon her?
new ArrowIcon(ArrowIcon.UP) kennt eclipse bei mir nicht

hab was gefunden:
org.gui4j.core.swing.calendar;

meintest Du das?
 
Zuletzt bearbeitet:
Zurück