Usuwanie wierszy z JTable

0

Witam.
Mam problem z usunięciem wiersza z tabeli JTable. Stworzyłem metodę analogicznie do metody (działającej) InsertData, która umieszcza dane w bazie danych, następnie odświeża zawartość JTable w celu pokzania zmian. Funkcję usuwającą stworzyłem na tej samej zasadzie, ale jednak nie działa. Gdzie leży błąd, lub czego brakuje mi, aby to działało poprawnie.

Funkcja usuwająca rekord z bazy danych: (wyświetla komunikat o powodzeniu, więc domyślam się, że rzeczywiście usuwa rekord z bazy):

void removeData(){
		
		try{
			
		int wiersz = table.getSelectedRow();
		System.out.print("Wiersz: "+wiersz);
		String remove = "DELETE FROM spinning WHERE id = '"+wiersz+"'";
		 stmt = conn.createStatement();
		 stmt.executeUpdate(remove);
		 stmt.close();
		 
System.out.print("Dane z pozycji nr "+table.getSelectedRow()+" usunięto z tabeli");
		}catch (NullPointerException e) {
			e.getStackTrace();
		}catch (SQLException e){
			e.getStackTrace();
		}
	}

a następnie metoda (działa bez zarzutu dla dodawania rekordów), która jest wywoływana każdorazowo po dodaniu danych lub tak jak w tym przykładzie, ich usunięciu:

public void refreshAll(){
		panelTabela.remove(scrollPane);
		RybyModel modello = new RybyModel();
		tableNew = new JTable(modello);
		((RybyModel) tableNew.getModel()).setDane(SelectAllData());
		tableNew.setAutoCreateRowSorter(true);
		scrollPane = new JScrollPane(tableNew);
		panelTabela.add(scrollPane);
		container.add(panelTabela, gbc());
		validate();
		
	}

Po naciśnieciu guzika, są wywoływane jedna po drugiej:

removeData();
refreshAll();

ps. korzystam z klasy dziedziczącej po AbstractTableModel

0

Nie chcę mi sie analizować twojego kodu - wydaje mi się zbyt skomplikowany. Ja to robię tak:

model.remove(identyfikator_wiersza_do_usunięcia); 
model.fireTableDataChanged();                              

model dziedziczy po AbstractTableModel, metoda remove(..) zajmuje się usunięciem z modelu i ewentualnym usunięciem z bazy
pozdrawiam

0

Spróbuje tak jak mówisz, dodam do modelu tą metodę i zobacze czy działą. Mam jednak pytanie w związku z moim domysłem. Czy aby działała metoda tabela.getSelectedRow (), to czy ta metoda musi być zaimplementowana w modelu? Bo ja jej w modelu nie posiadam i nie jestem pewien, czy rzeczywiście pobiera zaznaczony rząd [???] . Bo jak wpisze na sztywno w kod, ze np:

String delete = "DELETE FROM tabela WHERE id = '48'";

to działa, bo usuwa wiersz z tabeli z bazy i z JTable, ale jak napisze...

String delete = "DELETE FROM spinning WHERE id = '"+tabela.getSelectedRow()+"'";

to nie działa. Więc może jest tu problem z samą selekcją danego wiersza?

0

Działa, ja robię tak (jeżeli tabela dopuszcza sortowanie - wtedy numer wiersza w tabeli i w modelu mogą sie różnic)

     int index=tabela.getSelectedRow();
      if(index==-1)
      {
            return;
      }
      int indexInModel=tabela.convertRowIndexToModel(index);

na podstawie indexInModel powinieneś odczytać wiersz z tabeli (o ile pamiętam będzie to jakaś rybka), odczytać ID tej rybki i wykonać polecenie

"DELETE FROM spinning WHERE id = '"+ID+"'"

Przecież numer wiersza, to nie to samo co ID w odczytanym wierszu
pozdrawiam

0

Dzięki. Sprawdzę popołudniu, bo teraz nie mam takiej możliwości, w razie problemów, napisze :). Pozdrawiam

0

Wybacz moją niewiedzę, ale nie mogę sobie z tym poradzić :(. Nie wiem, jak dokładnie, to przełożyć na mój kod. Co więcej, jestem niemal pewien, że te dane nie są jednak usuwane z bazy, chociaż polecenie DELETE daje rezultat OK, że usunęło. Jeśli by jednak tak było, to po ponownym uruchomieniu aplikacji, w JTable widniałby jeden wiersz mniej, a tak nie jest. Załączam całą klasę z modelem. Reszta bez zmian, tak jak w początkowym poście. Tak jak mówiłem, dla metody, która dodaje dane do bazy, działa bez zarzutu, a metoda usuwająca dane, jest stworzona analogicznie i tak samo wywoływana, więc nie wiem dlaczego nie działa :(

import java.util.ArrayList;
import javax.swing.table.AbstractTableModel;

import com.sun.org.apache.bcel.internal.generic.RETURN;


public class RybyModel extends AbstractTableModel {

private static String [] nazwyKolumn = {"id","gatunek","waga","długość","przyn_rodz",
            "przyn_opis","łowiska","data"};

public ArrayList<Object> dane;

	public void setDane(ArrayList<Object> rybki){
		this.dane=rybki;
	}
	
	public int getColumnCount() {
		return nazwyKolumn.length;
	}

	public int getRowCount() {
		return dane.size();
	}
	
	public String getColumnName(int kolumna){
		return nazwyKolumn[kolumna];
		
	}
	

	public boolean isCellEditable(int rowIndex, int columnIndex){
		if(columnIndex==0)
			return false;
		else
			return true;
		
	}
	
	public Object getValueAt(int wiersz, int kolumna) {
		Ryba r = (Ryba) dane.get(wiersz);
		
		switch(kolumna){
		case 0:
			return r.id;
		case 1:
			return r.gatunek;
		case 2:
			return r.waga;
		case 3:
			return r.dlugosc;
		case 4:
			return r.przyn_rodz;
		case 5:
			return r.przyn_opis;
		case 6:
			return r.lowisko;
		case 7:
			return r.data;
			
		}
		return null;
	}

	public void setValueAt(Object aValue,int rowIndex,int columnIndex){
		Ryba r = (Ryba) dane.get(rowIndex);
		
		switch(columnIndex){
		case 0:
			r.id=(String)aValue;
			break;
		case 1:
			r.gatunek=(String) aValue;
			break;
		case 2:
			r.waga=(String)aValue;
			break;
		case 3:
			r.dlugosc = (String)aValue;
			break;
		case 4:
			r.przyn_rodz = (String)aValue;
			break;
		case 5:
			r.przyn_opis = (String)aValue;
			break;
		case 6:
			r.lowisko = (String)aValue;
			break;
		case 7:
			r.data = (String)aValue;
	        
	        fireTableCellUpdated(rowIndex, columnIndex);
	}

}

}
0

Wyobrażam to sobie tak, w obiekcie wyświetlającym (klasy JTable) w obsłudze zdarzenia "chcę usunąć zapis" jest taki kod

   int index=tabela.getSelectedRow();
   if(index==-1)
   {
         return;
   }
   int indexInModel=tabela.convertRowIndexToModel(index);
   model.remove(indexInModel);
   model.fireTableDataChanged();

W modelu (klasa RybyModel) jest metoda remove(int indeks)

public void remove(int indeks)
{
   Ryba r=(Ryba)dane.get(indeks);
   // u mnie byłoby Ryba r=dane.get(Indeks) bo ja bym definiował tak
   // ArrayList<Ryba> dane;
   int ind=r.id;
   dane.remove(index);
   //wywołanie polecenia SQL: DELETE FROM spinning WHERE id = ind   
}
0

Zanim usunie się wiersz z modelu, można wykonać najpierw polecenie DELETE do bazy danych. Wówczas w przypadku wystąpienia wyjątku, wiersz nie zostałby usunięty.

0

@pustak właśnie tak robiłem. Najpierw usuwałem wiersz z bazy danych, a następnie pobierałem nowe wartości z bazy danych (czyli bez tego wiersza). Czyli najpierw metoda kasująca dane z bazy danych, a następnie "odświeżenie" JTable. Jednak pomimo braku Exceptiona, dane z bazy nie były usuwane, ponieważ, jak pobierałem niby nowe wartości z bazy (odświeżałem) , to rekord ten jednak nie został usunięty i to jest właśnie mój problem? @bogdans zrobiłem według twojego przykładu i działa :). Jednak mam teraz problem następujący...po uruchomieniu aplikacji gdy od razu usuwam rekordy, to działa, jednak jeśli najpierw dodam jakiś rekord, a poźniej chce od razu usunąć (nikoniecznie ten dodany przed chwilą) to znowu nie działa. Nie usuwa już wtedy wiersza :(

0

Generalnie chodziło mi o taką kolejność:
< code = java >
public void remove(int indeks)
{
try {
Ryba r=(Ryba)dane.get(indeks);
int ind=r.id;
//wywołanie polecenia SQL: DELETE FROM spinning WHERE id = ind

  dane.remove(index); //wiersz jest usuwany po poprawnym wykonaniu DELETE

} catch(SQLException e) {
//obsluga wyjatku
}
}


Nie wiem, czy odświeżanie wszystkich danych , po wykonaniu polecenia INSERT/DELETE (a jak rozumiem tak to realizujesz), jest zbyt efektywne.
Jeżeli wiele procesów operuje na tych danych, możesz dodać jakiś przycisk "odśwież".

A co do braku efektu polecenia DELETE, może nie dałeś COMMIT'a (jeżeli masz wyłączone AUTO_COMMIT)?
0

Teraz już widzę, o co Ci chodziło. A co do polecenia commit, to nigdy tego nie używałem :), więc to pewnie przez to. Z tego co teraz przeczytałem, to przy tworzeniu nowego połączenia jest ustawiane automatycznie na true. Chociaż głowy nie dam. Więc jak dodać tą metodę (commit) w tym przypadku? Możesz mi podpowiedzieć?

0

Jak masz conn klasy Connection, to

conn.setAutoCommit(true);
0

A w ktorym miejscu dokładnie to dodać? Ponieważ Connection conn, mam zdefiniowane, jako zmienną globalną. A następnie w każdej metodzie (połączenie z bazą, dodawanie, usuwanie, szukanie rekordów) korzystam z tego conn. Więc, gdzie to dokładnie powinno być?

0

To zależy od Ciebie, jeśli nie chcesz tej własności zmieniać i nie chcesz grupować poleceń w transakcje, to w pierwszym wierszu po utworzeniu instancji conn.

0

Zrobiłem, tak jak mówiłeś i nie przyniosło to efektu. Teraz więc spróbuje tworzyć oddzielny connection lokalnie dla danej metody, rozumiem, ze tą operację nazwałeś tranzakcjami?

0

Poradziłem sobie z usuwaniem wierszy. Jednak tylko do pewnego stopnia. Gdy po uruchomieniu aplikacji od razu zaznaczam i usuwam wiersze to działa. Ale jak ją uruchomie i najpierw dodam jakiś rekord, a poźniej jak jakiś chce usunąć, to już nie działa Sad. Metoda removeData dochodzi wtedy do momentu (poniżej fragment kodu), gdzie zwraca wartosc "-1", czyli index==-1 i nie usuwa już rekordów (nawet jeśli dalej dam else). Czym to jest spowodowane? To tak jakby w ogóle nie zaznaczał tego wiersz, jeśli zwraca "-1" jeśli dorze rozumiem tak? Jak to rozwiązać? Poniżej fragment metody, która po operacji dodania rekordu, nie działa, zwraca "-1" pomimo tego, że wiersz jest zaznaczony:


        int index=table.getSelectedRow();
        if(index==-1)
        {
                         return;
        } 
0

Nie rozumiem o co pytasz, jeśli metoda

getSelectedRow()

zwraca -1, to znaczy że nic nie jest zaznaczone. Zaznacz wiersz, który chcesz usunąć i ponów operacje usunięcia.

0

No domyślałem się, że jak jest "-1" to nic nie jest zaznaczone. Właśnie o to mi chodzi, dlaczego to zwraca tą wartość, skoro wiersz jest zaznaczony? Jak tylko usuwam wiersze po uruchomieniu aplikacji, to działa bez zarzutu, ale jak np dodam z jeden wiersz, to pozniej jak zaznacze jakis wiersz do usuniecia, to metoda ta zwraca właśnie "-1". Nie wiem o chodzi [???]


Ale ze mnie gapa :). Na 99% nie działa, przez to, że jak odświeżałem JTable, to tworzyłem nowe o innej nazwie i na jego podstawie pokazywałem zawartość bazy. Więc table.getSelectedRow nie mogło działać po odświeżeniu, gdyż wtedy JTable nazywa się tableNew a nie table :). Przepraszam za to kłopot, moje niedopatrzenie i dziękuję za pomoc. Pozdrawiam

1 użytkowników online, w tym zalogowanych: 0, gości: 1