LINUX.ORG.RU

[java]заполнение jtable из БД MySQL

 


0

0

Заполняю таблицу из БД. Проблема следующая: jtable заполняется только первой строчкой из БД. Дальше не берет. Вот как у меня реализован костыль:

private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {                                         
try {
Statement stmt = null;
ResultSet rs = null;
String SQL = "SELECT * FROM student";
stmt = con.createStatement();
rs = stmt.executeQuery(SQL);
while (rs.next()) {
jTable1.setModel(new javax.swing.table.DefaultTableModel(
new Object [][] {
{rs.getString("id"), rs.getString("name")},
},
new String [] {"id", "name"}
)
);
}
} catch (SQLException e) {
jTextField1.setText("SQL Exception: "+ e.toString());
}

графические компоненты автоматически сгенерированы. Помогите исправить :)
------
скрин.

Дай угадаю

При этом ощущаются дикие тормоза (приложение ни на что не реагирует), а в конце отработки кода (когда кнопка отвиснет) в таблице оказывается только последняя запись?

iZEN ★★★★★
()

>while (rs.next()) {

jTable1.setModel(new javax.swing.table.DefaultTableModel(

Ух тыж е-мое. Ты уверен что это надо делать в цикле?

theos ★★★
()

Уважаемый, вы извращенец. Там достаточно продуманная модель таблицы в кою можно динамически подгружать хоть постранично данные из базы. А вы тупо на каждую запись добавляете новую модель (которая пееркрывает старую) - этож писец.

wfrr ★★☆
()
Ответ на: комментарий от theos

Вообще этот код надо на соотвествующий сайт-кунсткамеру кода отправить, жаль я не помню как он называется.

wfrr ★★☆
()

Что-то у тебя совсем левое тут происходит. Как надо правильно - не скажу, так как не помню. Могу лишь посоветовать почитать туториал по использованию таблиц на сайте Sun, у них весьма толково объяснялось, как с ними работать (вплоть до запихивания туда собственных компонент итп.)

runtime ★★★★
()
Ответ на: комментарий от theos

ну как бы если строчек много, вроде да.

anonimbus ★★
() автор топика
Ответ на: комментарий от wfrr

зато оригинально. Я 20 раз копался, чтобы добиться такого вида. Оно полноценно работала в текстовом поле, пока таблица не приспичила.

anonimbus ★★
() автор топика
Ответ на: комментарий от wfrr

>жаль я не помню как он называется.

Мне кажется в названии фигурировала яркая аллегория c экскрементами.

Картину дополняет то, что ResultSet & Statement не закрывают. Веселых вам, топикастер, эксепшнов!

theos ★★★
()

ай спасибо, хорошо посмеялся в конце дня))

JFreeM ★★★☆
()
Ответ на: комментарий от anonimbus

Читаем теорию баз данных - в базах данных нет первой или последней записи. ))) Это в большей мере касается iZEN, потому что он как раз умничает.

Буду первым кто вам таки ответит. Вам нужно создать модель один раз и один раз ее установить. А вот в саму модель внутрь нужно добавить ваши данные. А вы сейчас просто в каждой итерации создаете новую модель, добавляете туда одну запись и потом устанавливаете ее в таблицу.

vertexua ★★★★★
()
Ответ на: комментарий от vertexua

>Читаем теорию баз данных - в базах данных нет первой или последней записи

Однакое ResultSet выдает строки в определенном порядке, который и имел ввиду iZEN.

theos ★★★
()
Ответ на: комментарий от theos

Это не он выдает, поверьте, а сама СУБД. В другой СУБД был бы другой порядок. Да и в этой тоже через время тоже может все измениться. В записях БД нет порядка, СУБД свободно имеет право выдавать записи в любом порядке если отсутствует ORDER BY

vertexua ★★★★★
()
Ответ на: комментарий от vertexua

Бульте проще, уважаемый, и не буквоедствуйте.

wfrr ★★☆
()
Ответ на: комментарий от vertexua
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {                                         
try{
Statement stmt=con.createStatement();
ResultSet rs=stmt.executeQuery("SELECT * FROM student");
//бд
ResultSetMetaData md = rs.getMetaData();
int columnCount = md.getColumnCount();
Vector columns = new Vector(columnCount);
for(int i=1; i<=columnCount; i++)
columns.add(md.getColumnName(i));
Vector data = new Vector();
Vector row;
while(rs.next())
{
row = new Vector(columnCount);
for(int i=1; i<=columnCount; i++)
{
row.add(rs.getString(i));
}
data.add(row);
}
jTable1 = new JTable  (data, columns);
} catch (SQLException e) {
jTextField1.setText("Ошибка SQL: "+ e.toString());
}
}

Больше никак не знаю.

anonimbus ★★
() автор топика

и сегодня я утверждаю, что Свинг это дерьмо.

Такой ху**й интеграции с бд больше нигде нельзя было придумать.

anonimbus ★★
() автор топика
Ответ на: комментарий от anonimbus

Оно удачно работает когда данные очень разнообразные и динамические и вычисляются каким то вашим алгоритмом. А относительно БД, то просто оно не out-of-the-box. Хотя кто ее знает эту библиотеку классов

vertexua ★★★★★
()
Ответ на: комментарий от anonimbus

Вместо java.util.Vector лучше было бы использовать java.util.ArrayList — так гораздо быстрее было бы. Но проектировщики Swing были настолько глупы, что засунули в объявление конструктора JTable() в качестве параметров не интерфейс java.util.List, и даже не абстрактный класс java.util.AbstractList (от которого, кстати говоря, наследуется java.util.Vector), а класс java.util.Vector!

Во чудаки на букву м!

iZEN ★★★★★
()
Ответ на: комментарий от anonimbus

Я в очередной раз взглянул на ваш, код и решил не удивляться.

wfrr ★★☆
()
Ответ на: комментарий от iZEN

Чтобы туда все совали LinkedList и потом удивлялись тормозам при редактировании 7894 строчки? Думаю что лучшим был бы интерфейс, которые допускает Vector и ArrayList, но не LinkedList

vertexua ★★★★★
()
Ответ на: комментарий от vertexua

Нельзя «политику» зашивать в код — это со времён первых Unix известно. Что бывает с теми, кто нарушает этот принцип, известно тоже — пользователи жрут что дают, а потом удивляются, почему не с того конца и не туда оно выходит.

iZEN ★★★★★
()
Ответ на: комментарий от vertexua

Охринеть, у вас извращения в голове плодятся.

wfrr ★★☆
()
Ответ на: комментарий от iZEN

Мне кажется изменение интерфейса в соответствии с вашей рекомендацией - еще одно место для отстрела яиц. Если так продолжать, то Java станет С++, а Swing - ..., и того хуже.

В целом если они гарантируют что при создании они сразу данные перенесут в быструю (для произвольного доступа) структуру, то проблем нет. А так видно причины есть, мало ли что там внутри. Но в обычно в таких случаях долой связные списки.

vertexua ★★★★★
()
Ответ на: комментарий от vertexua

Зато тогда открывается заманчивая перспектива нагородить свой потомок от List с генерацией элементов. Но это костыль, ибо нормальная модель решает проблему

vertexua ★★★★★
()
Ответ на: комментарий от vertexua

Когда кажется, надо креститься, уважаемый. Стараниями подобных вам, ява превратилась в тормозное говно - достаточно того, что при каждом set\get в стандартной библиотеке почти всегда копируются массивы и объекты. Все для того чтобы идиоты не отстрелили ногу.

wfrr ★★☆
()
Ответ на: комментарий от wfrr

Поверьте, я вообще против смены интерфейса. Просто придумываю костыль для удовлетворения порывов iZENа, без костыля или тормозов это сделать нельзя

vertexua ★★★★★
()
Ответ на: комментарий от vertexua

Интерфейсы позволяют отказаться от зашивания политик (конкретных классов) в библиотечный код и избежать дополнительных преобразований между форматами хранения пользовательских данных.

Пользователю библиотеки было бы достаточно: реализовать в собственном контейнере данных интерфейс java.util.List и передать этот контейнер конструктору JTable (или модели) без всяких заморочек и дополнительных преобразований данных в массивы (Object [][]) или в Vector (в модели).

Что сейчас: преобразование из массивов в Vector, из других контейнеров в Vector и т.д. для отображения в JTable == двойная работа.

У JTable, как у всех AWT/Swing-компонентов, перегруженный API: с одной стороны есть высокоуровневые объектные модели данных (TableModel), с другой — примитивные массивы (Object [][]) объектов. Ужас!

iZEN ★★★★★
()
Ответ на: комментарий от iZEN

венном контейнере данных интерфейс java.util.List и передать этот контейнер конструктору JTable

вот собсна поэтому не понятно, чево на делфи-то плеваться, когда те же полученные данные в таблице можно очень просто передать обратно к интерфейсу подключения.

anonimbus ★★
() автор топика
Ответ на: комментарий от wfrr

ява превратилась в тормозное говно


Пруф или небыло

Karapuz ★★★★★
()
Ответ на: комментарий от wfrr

У меня не порывы, а просто полет мысли «а что если бы». Но мне очевидно что менять интерфейс не имеет большого смысла.

Продолжаем полет мысли. А что если туда передавать immutable структуру, предварительно как то ее сконструировав? Этим решается проблема необходимости копирования для безопасности. Или mutable обьект превратить в immutable с помощью флажка при передаче другом обьекту. А?

vertexua ★★★★★
()
Ответ на: комментарий от vertexua

Причём тут mutable/immutable? Мы говорим о контейнерах вообще. Контейнеры по определению содержат ссылки на объекты и не могут быть immutable.

Раз уж не справились с TableModel-only, следовало бы сделать человеческий API с нормальными контейнерами (интерфейсом всех контейнеров), а не с конкретной реализацией (Vector).

Зачем выбрали именно Vector? Этот класс внутренне-синхронизирован и от этого жутко тормозной. И, как известно, Swing и так не гарантирует потокобезопасность в компонентах. Загадка.

iZEN ★★★★★
()

А тут жабу хвалят sql.ru/forum/actualthread.aspx?tid=743710&pg=6#8539004

Karapuz ★★★★★
()

А если так сделать, чего будет? Или оно в строки неправильно преобразуется? Или я опять ступил?

private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
try {
  Statement stmt=con.createStatement();
  ResultSet rs=stmt.executeQuery("SELECT * FROM student");
  //бд
  ResultSetMetaData md = rs.getMetaData();
  String[] ColumnNames = new String[md.getColumnCount()];
  for(int i=0; i < ColumnNames.length; i++)
    ColumnNames[i] = md.getColumnName(i); //Может, здесь лучше getColumnLabel?

  Object[][] RowData = new Object[ColumnNames.length][];
  for(int i=0; i < RowData.length; i++)
    RowData[i] = rs.getArray(i);

  //таблица
  jTable1 = new JTable(RowData, ColumnNames);

  //И закрыть надо, если больше не нужно
  rs.close();
}
catch (SQLException e) {
  jTextField1.setText("Ошибка SQL: "+ e.toString());
}
}
proud_anon ★★★★★
()
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;

import javax.swing.table.AbstractTableModel;

public class TipsTableModel extends AbstractTableModel {

    private static final long serialVersionUID = 7510661654684099630L;

    private ArrayList<String> columnNames = new ArrayList<String>();
    @SuppressWarnings("unchecked")
    private ArrayList<Class> columnTypes = new ArrayList<Class>();
    private ArrayList<Object> dataColl = new ArrayList<Object>();
    private ArrayList<Object> dataRow = new ArrayList<Object>();

    private Connection _conn = null;
    private Statement _st = null;
    private ResultSet _rs = null;
    private ResultSetMetaData _rsmd = null;

    public int getColumnCount() {
	return columnNames.size();
    }

    @Override
    public int getRowCount() {
	synchronized (dataRow) {
	    return dataRow.size();
	}
    }

    @SuppressWarnings("unchecked")
    @Override
    public Object getValueAt(int row, int col) {
	synchronized (dataRow) {
	    ArrayList<Object> dat = (ArrayList<Object>) dataRow.get(row);
	    return dat.get(col);
	}
    }

    public String getColumnName(int col) {
	return columnNames.get(col);
    }

    @SuppressWarnings("unchecked")
    public Class getColumnClass(int col) {
	return columnTypes.get(col);
    }

    public boolean isCellEditable(int row, int col) {
	if (col == 2) {
	    return true;
	} else {
	    return false;
	}
    }

    @SuppressWarnings("unchecked")
    public void setValueAt(Object obj, int row, int col) {
	synchronized (dataRow) {
	    ArrayList<Object> dat = (ArrayList<Object>) dataRow.get(row);
	    dat.add(col, obj);
	    fireTableRowsUpdated(row, col);
	    fireTableStructureChanged();
	}
    }

    public void clearData() {
	synchronized (dataRow) {
	    dataRow.clear();
	}
    }

    @SuppressWarnings("unchecked")
    public void load(String patern, int flag) {
	try {
	    columnNames.clear();
	    columnTypes.clear();
	    dataRow.clear();
	    dataColl.clear();

	    _conn = DBM.getSQLLiteConnect();
	    _st = (Statement) _conn.createStatement();

            _st.execute("SELECT id,title,name,ratio,date FROM tips");

	    _rs = _st.getResultSet();
	    _rsmd = (ResultSetMetaData) _rs.getMetaData();

	    int collCount = _rsmd.getColumnCount();
	    for (int s = 0; s < collCount; s++) {
		columnNames.add(_rsmd.getColumnName(s + 1));
		Class type = Class.forName(_rsmd.getColumnClassName(s + 1));
		columnTypes.add(type);
	    }
	    fireTableStructureChanged();
	    while (_rs.next()) {
		ArrayList rowData = new ArrayList();
		for (int i = 0; i < collCount; i++) {
		    if (columnTypes.get(i) == String.class) {
			rowData.add(_rs.getString(i + 1));
		    } else if (columnTypes.get(i) == Integer.class) {
			rowData.add(_rs.getInt(i + 1));
		    } else {
			rowData.add(_rs.getObject(i + 1));
		    }
		}
		synchronized (dataRow) {
		    dataRow.add(rowData);
		    this.fireTableRowsInserted(dataRow.size() - 1, dataRow
			    .size() - 1);
		}
	    }

	} catch (SQLException e) {
	    e.printStackTrace();
	} catch (ClassNotFoundException e) {
	    e.printStackTrace();
	} finally {
	    try {
		_rs.close();
		_st.close();
		_conn.close();
	    } catch (Exception e) {
		e.printStackTrace();
	    }
	}
    }

}

Типо этого..

Это просто пример..

Valor
()
Ответ на: комментарий от Valor

Соответственно в таблицу грузим примерно так..

private JTable table(){
	if (_tipsTable == null){
	    _tipsTable = new JTable();
	    _tipsTable.setAutoCreateColumnsFromModel(true);
	    _tipsTable.setModel(new TipsTableModel());
	  
	}
	return _tipsTable;
    }

далее в коде нужно вызвать примерно следующее TipsTableModel tm = (TipsTableModel) table().getModel(); tm.load();

Valor
()
Ответ на: комментарий от proud_anon

здесь при присвоении записей ругается RowData= rs.getArray(i); Хотя, я думал это из-за отсутствующих скобок после for.

anonimbus ★★
() автор топика

Полностью работоспособный код

private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {                                         
try{
Statement stmt=con.createStatement();
ResultSet rs=stmt.executeQuery("SELECT * FROM student");
int numColumns = rs.getMetaData().getColumnCount();
Vector column = new Vector();
for (int i = 1; i <= numColumns; i++) {
column.add(rs.getMetaData().getColumnName(i));        }
Vector data = new Vector();
while (rs.next()) {
Vector row = new Vector();
for (int i = 1; i <= numColumns; i++) {
row.add(rs.getString(i));
}
data.add(row);
}
jTable1.setModel(new javax.swing.table.DefaultTableModel(data, column)
);
} catch (SQLException e) {
jTextField1.setText("Ошибка SQL: "+ e.toString());
}
}                               

Вопрос решен :)

anonimbus ★★
() автор топика

Вот так вот вроде работает:

public void SetResultQueryInTable(JTable Table, ResultSet qryResult, Integer ColumnStart, Integer ColumnCount) { try { int RowNumber = 0; DefaultTableModel dmd = new DefaultTableModel(); Object[] RowData = new Object[ColumnCount - 1]; for(int i = ColumnStart; i <= ColumnCount; i++) dmd.addColumn(qryResult.getMetaData().getColumnName(i)); while (qryResult.next()) { for(int i = ColumnStart; i <= ColumnCount; i++) { RowData[RowNumber] = qryResult.getObject(i); RowNumber++; } dmd.addRow(RowData); RowNumber = 0; } Table.setModel(dmd); } catch(SQLException Error) { JOptionPane.showMessageDialog(Table.getParent(), Error.getMessage()); } }

anonymous
()
Ответ на: комментарий от anonymous

Прости, не знал, что вот так текст выведет. Думаю разберешься в редакторе.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.