AbstractTableModel - setValueAt - Wert übergeben

Hallo, ich brauche Hilfe, suche mir hier einen Wolf.

Ich habe ein AbstractTableModel das Daten aus einer Oracle Datenbank liefert. Funktioniert auch prima. Allerdings scheitere ich beim Versuch einen Wert in der JTable zu ändern.

Meine Frage ist, was muss ich hier an setValueAt übergeben (Bitte Beispiel)

Hier ist mein AbstractTableModel:

Java:
public class FillTable extends AbstractTableModel{

	private ResultSet rs;
	private int rowCount;
	private int columnCount;
	private ArrayList data=new ArrayList();
	Object[][] contents;
	
	public FillTable(ResultSet _rs) throws Exception
	{
		setRS(_rs);
	}

	public void setRS(ResultSet _rs) throws Exception {
		this.rs=_rs;
		ResultSetMetaData metaData=_rs.getMetaData();
		rowCount=0;
		columnCount=metaData.getColumnCount();
		while(_rs.next()){
			Object[] row=new Object[columnCount];
			for(int j=0;j<columnCount;j++){
				row[j]=_rs.getObject(j+1);
			}
			data.add(row);
			rowCount++;
		}
	}

	public int getColumnCount(){
		return columnCount;
	}

	public int getRowCount(){
		return rowCount;
	}

	public Object getValueAt(int rowIndex, int columnIndex){
		Object[] row=(Object[]) data.get(rowIndex);
		return row[columnIndex];
	}

	
	public void setValueAt(Object value, int row, int col) {
		contents[row][col] = value;
		fireTableCellUpdated(row,col);

	}
	
	
	public String getColumnName(int columnIndex){
		try{
			ResultSetMetaData metaData=rs.getMetaData();
			return metaData.getColumnName(columnIndex+1);
		}catch(Exception e){
			e.printStackTrace();
			return null;
		}
	}
}
 
Hallo.
Erstens solltest du Generics verwenden bei deiner ArrayList, zweitens solltest du alle ArrayList durch List ersetzen.

Drittens:
Du bist inkonsistent mit deiner Implementierung:
Du hast ein zweidimensionales Array von Object, das bei
Code:
setValueAt
geändert wird, und bei
Code:
getValueAt
gibst du einen Wert zurück, der in irgendeiner Liste liegt... Das leuchtet mir nicht ein!

Ich würde eher deine Methode
Code:
setRS
folgendermaßen implementieren. (außer du willst beim ArrayList bleiben):

Java:
public void setRS(ResultSet _rs, int size) throws Exception {
	this.rs=_rs;
	ResultSetMetaData metaData=_rs.getMetaData();
	rowCount=0;
	columnCount=metaData.getColumnCount();
	contents = new Object[size][];
	while(_rs.next()) {
		Object[] row=new Object[columnCount];
		for(int j=0;j<columnCount;j++){
			row[j]=_rs.getObject(j+1);
		}
		contents[rowCount++] = row;
	}
}

oder deins beibehalten und
Code:
setValueAt
ändern, wovon ich denke, dass es dir eher zusagen wird:

Java:
public void setValueAt(Object value, int row, int col) {
	data.get( row )[ col ] = value;
	fireTableCellUpdated(row,col);
}

Beim dieser Variante kannst du deine contents-Variable löschen ( bei der anderen hingegen die data-Variable)

VIERTENS:
statt
Code:
throws Exception
lieber
Code:
throws SQLException
, es ist schlechter Stil, immer auf Exception zurückzugreifen, wenn es nicht nötig ist.
 
Zuletzt bearbeitet:
Habe mal die Variante setValueAt nach deinem Vorschlag geändert.

... wenn ich das hier verwende bekomme ich einen Fehler,

Hallo.

oder deins beibehalten und
Code:
setValueAt
ändern, wovon ich denke, dass es dir eher zusagen wird:

Java:
public void setValueAt(Object value, int row, int col) {
	data.get( row )[ col ] = value;
	fireTableCellUpdated(row,col);
}

Beim dieser Variante kannst du deine contents-Variable löschen ( bei der anderen hingegen die data-Variable)


und dieser Fehler lautet: The type of the expression must be an array type but it resolved to Object
 
Wie gesagt,
Code:
ArrayList
durch
Code:
ArrayList<Object[]>
ersetzen und
Code:
ArrayList<Object[]>
durch
Code:
List<Object[]>
(außer bei
Code:
new ArrayList<Object[]>()
)!!

@mla.rue, weil das gegen Interface-Programmierung verstößt. Für gewöhnlich braucht keiner die speziellen Methoden der ArrayList, eine List genügt. Sollte man sich übrigens irgendwann entscheiden, die Implementierung von
Code:
ArrayList
zum Beispiel auf
Code:
LinkedList
zu ändern, hat man viel mehr Schwierigkeiten. Interfaces sind nicht umsonst da!
 
Zuletzt bearbeitet:
Wie gesagt,
Code:
ArrayList
durch
Code:
ArrayList<Object[]>
ersetzen und
Code:
ArrayList<Object[]>
durch
Code:
List<Object[]>
(außer bei
Code:
new ArrayList<Object[]>()
)!!

Java:
 private ArrayList data=new ArrayList();

ändern in .....

Java:
 private ArrayList<Object[]> data=new ArrayList();
 
Wie gesagt,
Code:
ArrayList
durch
Code:
ArrayList<Object[]>
ersetzen und
Code:
ArrayList<Object[]>
durch
Code:
List<Object[]>
(außer bei
Code:
new ArrayList<Object[]>()
)!!

habe jetzt aber noch eine Frage zu deinem Vorschlag:

Java:
public void setRS(ResultSet _rs, int size) throws Exception {
    this.rs=_rs;
    ResultSetMetaData metaData=_rs.getMetaData();
    rowCount=0;
    columnCount=metaData.getColumnCount();
    contents = new Object[size][];
    while(_rs.next()) {
        Object[] row=new Object[columnCount];
        for(int j=0;j<columnCount;j++){
            row[j]=_rs.getObject(j+1);
        }
        contents[rowCount++] = row;
    }
}


Dann muss ich aber auch hier ein "int" mitgeben...

Java:
public FillTable(ResultSet _rs) throws Exception
{
	setRS(_rs);
}


wie würde das dann aussehen ?
 
Kommt drauf an, wie du dein ResultSet holst, aber im Normalfall müsstest du eine weitere Anfrage an deine Datenbank senden um
Code:
COUNT(*)
zu ermitteln. Also etwa so:
Java:
ResultSet rs = ... // dein rs eben
ResultSet count = connection.createStatement().executeQuery("SELECT COUNT(*) FROM Table");
if(!count.next())
	System.err.println("Sollte nie vorkommen");
int size = count.getInt( 1 );
new FillTable(rs, size);
 
Zunächst noch einmal Danke ! Du hast mir schon sehr geholfen.

Aber um deine Frage zu beantworten:

Kommt drauf an, wie du dein ResultSet holst, aber im Normalfall müsstest du eine weitere Anfrage an deine Datenbank senden um
Code:
COUNT(*)
zu ermitteln. Also etwa so:
Java:
ResultSet rs = ... // dein rs eben
ResultSet count = connection.createStatement().executeQuery("SELECT COUNT(*) FROM Table");
if(!count.next())
	System.err.println("Sollte nie vorkommen");
int size = count.getInt( 1 );
new FillTable(rs, size);

Ich hole mein ResultSet wie folgt:

Java:
	public static FillTable myModel() throws Exception{
		String DriverClass = null;
		if(getDriverClass() != null) {
			DriverClass = getDriverClass();
		} else {
			DbHostDbaCon myDbHostDbaCon = new DbHostDbaCon(getDataBaseName());
			DriverClass = myDbHostDbaCon.getDriverClass();
		}
		try {
				Class.forName (DriverClass);
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
		}
				
		java.sql.Statement st = HostCon.createStatement();

		ResultSet rs = st.executeQuery(StrSql);
		FillTable model = new FillTable(rs);
		return model;
	}

Wenn ich davor ein Select Count(*) absetze, wie müsste dann dieses ResultSet abgehoöt werden ? Kannst du mir das so umbauen, wie von dir beschrieben ?
 
Java:
ResultSet rs = st.executeQuery(StrSql);
ResultSet count = st.executeQuery("SELECT COUNT(*) FROM " + StrSql);
if(!count.next())
    System.err.println("Sollte nicht passieren");
int size = count.getInt( 1 );
 

Zurück
Oben