Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[JAVA] SQL -> JTable

Pagina: 1
Acties:

  • dupondje
  • Registratie: Augustus 2003
  • Laatst online: 07-09 13:27

dupondje

Powa 2 Tha PPL :)

Topicstarter
Hallo,

Ik moet een CRUD use-case uitwerken. Bij deze moet het mogelijk zijn om verschillende tabellen (7 voor het moment) te tonen in een JTable, en hierin moet het mogelijk zijn om records te verwijderen, toe te voegen, aan te passen etc ...
Nu vraag ik mij af of het mogelijk is om 1 methode te schrijven voor UPDATE/SELECT/INSERT/DELETE die kan gebruikt worden voor elke tabel. En niet voor elke tabel 4 nieuwe methoden schrijven ...
Ook omdat het mogelijk is dat de tabellen veranderen, of dat er tabellen bijkomen, en dit moet zo gemakkelijk mogelijk zijn toe te passen

Tips hoe dit uit te werken zijn altijd welkom :)

[ Voor 12% gewijzigd door dupondje op 04-03-2008 20:38 ]


  • Varienaja
  • Registratie: Februari 2001
  • Laatst online: 14-06 16:43

Varienaja

Wie dit leest is gek.

Denk eens aan objecten.

Een tabel bijvoorbeeld: zo'n ding bestaat uit rijen en kolommen. Een rij is in principe niet meer dan een array van verschillende waardes. Een kolom heb je in je JTable ook.

Het enige dat tabellen daadwerkelijk van elkaar onderscheid is de naam, gebruik dat. De rest is in principe altijd gelijk, toch?

Siditamentis astuentis pactum.


  • dupondje
  • Registratie: Augustus 2003
  • Laatst online: 07-09 13:27

dupondje

Powa 2 Tha PPL :)

Topicstarter
Maar het probleem is hoe haal ik onbekende data uit tabel ? voor string is het bijvoorbeeld resultset.getString(), int is resultset.getInt() ... zelfde voor setInt setString setDouble etc ... hoe moet dat opgelost worden hé :)

  • Gerco
  • Registratie: Mei 2000
  • Laatst online: 15:59

Gerco

Professional Newbie

Daar hebben ze de resultset metadata voor uitgevonden, die informatie staat daarin.

- "Als ik zou willen dat je het begreep, legde ik het wel beter uit!" | All number systems are base 10!


  • Robtimus
  • Registratie: November 2002
  • Laatst online: 13:37

Robtimus

me Robtimus no like you

Een custom TableModel lijkt me de way to go. Maak een subclass van AbstractTableModel, en overwrite zo goed als alle methods.

Je TableModel zal gebacked moeten worden door een ResultSet, die is gecreeerd met als type ResultSet.TYPE_SCROLL_SENSITIVE of ResultSet.TYPE_SCROLL_INSENSITIVE - anders kun je niet door je ResultSet heen en weer springen. Verder moet hij ook met ResultSet.CONCUR_UPDATABLE gecreeerd zijn omdat je anders niet kan updaten.

De volgende code is een deel van de oplossing (zonder Exception handling), die helaas verre van efficient zal zijn:
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public Object getValueAt(int row, int column)
{
    rs.absolute(row);
    return rs.getObject(column + 1); // want ResultSets zijn 1 based
}

public void setValueAt(Object value, int row, int column)
{
    rs.absolute(row);
    rs.updateObject(column + 1, value);
    rs.updateRow();
    fireTableCellUpdated(row, column);
}

public int getRowCount()
{
    rs.last();
    return getRow() + 1;
}

public void deleteRow(int row)
{
    rs.absolute(row);
    rs.deleteRow();
    fireTableRowsDeleted(row, row);

}

Dit is een basic opzet - ik heb er ooit naar gekeken maar ben nooit ver gekomen. Vooral de getRowCount method is lastig als je niet wilt wachten totdat de hele ResultSet klaar is.

Als je een primary key of unique key hebt voor alle tabellen is het wel een stuk eenvoudiger. Je kan dan een DefaultTableModel gebruiken, vantevoren vullen met je data en alleen de nodige methods overwriten:
Java:
1
2
3
4
5
6
7
8
9
10
11
public void setValueAt(Object value, int row, int column)
{
    updateDataBaseForPkey(...);
    super.setValueAt(value, row, column);
}

public void removeRow(int row)
{
    deleteRowForPkey(...);
    super.removeRow(row);
}

More than meets the eye
There is no I in TEAM... but there is ME
system specs


  • dupondje
  • Registratie: Augustus 2003
  • Laatst online: 07-09 13:27

dupondje

Powa 2 Tha PPL :)

Topicstarter
Bedank voor de uitleg :)

Heb je soms code van updateDataBaseForPkey ? :)

  • Robtimus
  • Registratie: November 2002
  • Laatst online: 13:37

Robtimus

me Robtimus no like you

Je moet dan vantevoren opgeven welke velden je pkey vormen. Laten we deze in een int[] stoppen genaamd pkeyFields die altijd minimaal 1 index bevat.

Dan is het gewoon een prepared statement:
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
StringBuffer query = new StringBuffer();
query.append("UPDATE ");
query.append(table);
query.append(" SET ");
query.append(getColumnName(column));
query.append(" = ? WHERE ");
query.append(getColumnName
query.append(getColumnName(pkeyFields[0]));
query.append(" = ?");
for (int i = 1; i < pkeyFields.length; i++)
{
    query.append(" AND ");
    query.append(getColumnName(pkeyFields[i]));
    query.append("= ?");
}
PreparedStatement stmt = connection.prepareStatement(query.toString());
stmt.setObject(1, value);
smt.setObject(2, getValueAt(row, pkeyFields[0]));
for (int i = 1, index = 3; i < pkeyFields.length; i++, index++)
{
     stmt.setObject(index, getValueAt(row, pkeyFields[i]));
}
stmt.executeUpdate();

Natuurlijk zonder exception handling.

Ook ga ik er hierbij vanuit dat de column names van je table model gelijk zijn aan die van je result set (kun je ophalen met getMetaData(), daarna de getColumnCount() en getColumnName()).

Verder is setObject niet helemaal de meest veilige manier, je kunt daar beter de versie die ook nog een int voor type neemt voor gebruiken - dat type haal je ook uit je ResultSetMetaData.


Als je je keys niet wilt opgeven kun je deze trouwens ook uit DatabaseMetaData halen dmv getPrimaryKeys. Daarmee weet je meteen ook de column names en hoef je die niet uit je table model te halen:
Java:
1
2
3
4
5
6
7
8
9
DatabaseMetaData md = connection.getMetaData();
ResultSet rs = md.getPrimaryKeys(null, null, table);
List keys = new ArrayList();
while (rs.next())
{
    String name = rs.getString("COLUMN_NAME");
    keys.add(name);
}
rs.close();



NOTE!!
Dit is allemaal theorie, ik heb deze code niet getest maar vooral uit de losse pols geschreven. Gebruik deze code zeker niet als je geen primary key hebt. Dan loop je zwaar het risico meerdere rows tegelijk te updaten.

Let er ook op dat TableModel standaard geen exceptions ondersteund. Je zult die dus moeten catchen en op een of andere manier (JOptionPane met als component je JTable is een idee) de gebruiker laten weten wanneer het fout gaat, en waardoor.

[ Voor 11% gewijzigd door Robtimus op 06-03-2008 20:44 ]

More than meets the eye
There is no I in TEAM... but there is ME
system specs

Pagina: 1