Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: GUI и Java FX приложения > Заполнить таблицу содержимым из БД


Автор: olexander 9.5.2008, 21:33
Самостоятельно во многом разобрался.
Пока не получается по результатам запроса к SQL (MySQL) серверу получить в GUI табличку с содержимым таблицы на сервере.

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

Создать таблицу получилось. 

Не смог прикрутить результаты запроса SELECT * FROM `test` к таблице в GUI ...

- к серверу подключаюсь:
Код

conn = DriverManager.getConnection("jdbc:mysql://server.ip/test?user=user.name&password=user.pass");


По примерам что нашёл подключиться не удалось ... 
2 том Хорстмана с. 460, пример 6.11 ResultSetTable не пошёл ... 

Похоже что не совсем правильно подключаюсь к серверу ... Так не получается ... Где в этом случае правильно ложить файл "database.properties".
Код


... 

 public static Connection getConnection()
      throws SQLException, IOException
   {  
      Properties props = new Properties();
      FileInputStream in = new FileInputStream("database.properties");
      props.load(in);
      in.close();

      String drivers = props.getProperty("jdbc.drivers");
      if (drivers != null) System.setProperty("jdbc.drivers", drivers);
      String url = props.getProperty("jdbc.url");
      String username = props.getProperty("jdbc.username");
      String password = props.getProperty("jdbc.password");

      return DriverManager.getConnection(url, username, password);
   }

... 


Ещё не совсем все гладко с локализацией, но это с понедельника.

Нужен протенький пример заполнения таблицы по результатам запроса. в идеале без файла "database.properties".

Заканчивается время на эксперименты.

Заранее спасибо за помощь.

Автор: Старовъръ 10.5.2008, 09:51
Скажи какие исключения выбрасываются и где, что конкретно не выходит, что надо. А то фразы "пока не получается что-то" или "похоже что-то здесь неправильно" не особо раскрывают смысл проблемы.

Автор: almagnit 10.5.2008, 10:00
Цитата(olexander @  9.5.2008,  21:33 Найти цитируемый пост)
Похоже что не совсем правильно подключаюсь к серверу ...


А где твой сервер находится, в сети или на твоем компе ?


Цитата(olexander @  9.5.2008,  21:33 Найти цитируемый пост)
Нужен протенький пример заполнения таблицы по результатам запроса. в идеале без файла "database.properties"


Попрошу попорядку, а то ты как-то все сразу и соединиться и заполнить.

ЗЫ:

Для заполнения лучше используй DatabaseTableModel. Но сначала разберись с первым вопросом.

ЗЗЫ:

Не пойму что тема далет в разделе FAQ

Автор: olexander 11.5.2008, 19:08
Соединиться у меня получилось.
Получилось добавить / изменить данные в БД.

Сервер в сети и работает нормально.

Не получилось запихнуть результаты простейшего запроса в табличку.

Автор: v2v 11.5.2008, 19:15
а что получилось? данные запроса вывести в консоль получилось? посмотреть что данные вернулись корректно получилось?

вот тривиальный пример таблички. такое удавалось вывести и увидеть таблицу?

Код

import java.awt.BorderLayout;

import javax.swing.JFrame;
import javax.swing.JTable;

public class ScrollTableSample {
  public static void main(String args[]) {
    Object rows[][] = { { "one", "ichi - \u4E00" },
        { "two", "ni - \u4E8C" }, { "three", "san - \u4E09" },
        { "four", "shi - \u56DB" }, { "five", "go - \u4E94" },
        { "six", "roku - \u516D" }, { "seven", "shichi - \u4E03" },
        { "eight", "hachi - \u516B" }, { "nine", "kyu - \u4E5D" },
        { "ten", "ju - \u5341" } };
    Object headers[] = { "English", "Japanese" };
    JFrame frame = new JFrame("Scrollless Table");
    JTable table = new JTable(rows, headers);
    frame.getContentPane().add(table, BorderLayout.CENTER);
    frame.setSize(300, 150);
    frame.setVisible(true);
  }
}

Автор: Старовъръ 11.5.2008, 19:30
Вот модель таблицы:
Код

import java.util.*;
import java.sql.*;
import javax.swing.table.*;
public class DatabaseTableModel extends AbstractTableModel 
{
    private static final long serialVersionUID = 1L;
    private ArrayList<String> columnNames = new ArrayList<String>();
    private ArrayList<Class> columnTypes = new ArrayList<Class>();
    private ArrayList data = new ArrayList();
    private Connection con;
    private String currentTable = "";
    public DatabaseTableModel()throws SQLException, ClassNotFoundException
    {
    }
    public void setConnection(ResultSet rs)throws SQLException, ClassNotFoundException
    {
        setDataSource(rs); 
        this.fireTableDataChanged();
    }
    public int getRowCount()
    {
        synchronized(data)
        {
            return data.size();
        }
    }
    public int getColumnCount()
    {
        return columnNames.size();
    }
    
    public Object getValueAt(int row, int col)
    {
        synchronized(data)
        {
            return ((ArrayList)data.get(row)).get(col);
        }
    }
    public String getColumnName(int col)
    {
        return columnNames.get(col);
    }
    public Class getColumnClass(int col)
    {
        return columnTypes.get(col);
    }
    public boolean isEditable()
    {
        return false;
    }
    public void setValueAt(Object obj, int row, int col)
    {
        synchronized(data)
        {
            ((ArrayList)data.get(row)).set(col, obj);
        }
    }
    public void setTable(String table)
    {
        currentTable = table;
    }
    public void setDataSource(ResultSet rs) throws SQLException, ClassNotFoundException
    {
        ResultSetMetaData rsmd = rs.getMetaData();
        columnNames.clear();
        columnTypes.clear();
        data.clear();
        
        int columnCount = rsmd.getColumnCount();
        for(int i = 0; i < columnCount; i++)
        {
            columnNames.add(rsmd.getColumnName(i+1));
            Class type = Class.forName(rsmd.getColumnClassName(i+1));
            columnTypes.add(type);
        }
        fireTableStructureChanged();
        while(rs.next())
        {
            ArrayList rowData = new ArrayList();
            for(int i = 0; i < columnCount; i++)
            {
                if(columnTypes.get(i) == String.class)
                    rowData.add(rs.getString(i+1));
                else
                    rowData.add(rs.getObject(i+1));
            }
            synchronized(data)
            {
                data.add(rowData);
                this.fireTableRowsInserted(data.size() - 1, data.size() - 1);
            }
        }
    }
}
 Вставляешь ее в таблицу и передаешь результаты своего запроса в модель: 
Код

DatabaseTableModel model = new DatabaseTableModel();
JTable table = new JTable(model);
model.setDataSource(resultSet);

Автор: olexander 20.5.2008, 21:38
Да, подключиться к серверу реально получилось, по примеру создать запрос (добавление данных) тоже.

v2v
Третий столбец - и должен в результате быть заполнен квадратиками?

Старовъръ
А можно хотя-бы в двух словах что с этой моделью таблицы нужно делать  ... 
Что-то я совсем не вкурю что куда ... :( ... и зачем ... 

Автор: Старовъръ 20.5.2008, 23:04
Да там вроде уже все ясно. Делаешь таблицу, в конструктор которой передаешь вышеуказанную модель. Добавляешь таблицу на панель. Создаешь соединение с БД и делаешь запрос на выборку(select). Передаешь его результаты в модель посредством метода setDataSource(). Модель сама все обновляет и делает.
Код

Connection con = new Connection("bla bla bla");
Statement st = con.createStatement();
ResultSet resultSet = st.executeQuery("select * from table");
DatabaseTableModel model = new DatabaseTableModel();
JTable table = new JTable(model);
add(table);
model.setDataSource(resultSet);

Автор: anti_snayper 25.5.2008, 16:16
Попутный вопрос:
извлекаю из базы данные запросом 
"SELECT Groups.Caption, Groups.Data, Groups.Group_id FROM Groups",
как сделать чтобы в таблице отображались только первые 2 поля?

Автор: Старовъръ 25.5.2008, 16:24
"SELECT Groups.Caption, Groups.Data FROM Groups" smile (убрал одно поле из запроса)
Или в модели поставить 
Код

getColumnCount{ return 2; }
   (не проверял, но должно сработать)
еще лучше:
Код

TableColumnModel columnModel = table.getColumnModel();
TableColumn column = columnModel.getColumn(2);
table.removeColumn(column);

Автор: nitzshe 27.5.2008, 01:38
Цитата

По примерам что нашёл подключиться не удалось ... 
2 том Хорстмана с. 460, пример 6.11 ResultSetTable не пошёл ... 



Я тоже наткнулся на этот код в этой же книге, который оказался нерабочим.
Что для новичков как я наверно негативно.

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

Порывшись в исходниках нашел у себя рабочий код приложения использования файла свойств,
вот ниже привожу его:

То что в файле db.properties:
db.connection.protocol=jdbc:mysql:
db.connection.host=127.0.0.1
db.connection.port=3306
db.connection.dbnametest=test
db.connection.dbname=test
db.connection.driver=com.mysql.jdbc.Driver

db.connection.username=root
db.connection.password=admin


Как пользовать:

Код

......
//в конструкторе переменные:
public static final String DEFAULT_PROPERTY_FILE = "db.properties";
Connection connect = null;

.......

    protected void initConnection() {
        Properties prop = new Properties();
        
        try {
            FileInputStream fis = new FileInputStream(DEFAULT_PROPERTY_FILE);
            try {
                prop.load(fis);
            } finally {
                fis.close();
            }
        } catch (Exception e) {
            System.err.println("Error loading config file: " + DEFAULT_PROPERTY_FILE);
            System.exit(1);
        }

        String dbUrl = prop.getProperty("db.connection.protocol") + "//" + 
                        prop.getProperty("db.connection.host") + ":" + 
                        prop.getProperty("db.connection.port") + "/" + 
                        prop.getProperty("db.connection.dbnametest");
        
        String dbDriver = prop.getProperty("db.connection.driver");
        String dbUser = prop.getProperty("db.connection.username");
        String dbPassword = prop.getProperty("db.connection.password");
        
        try {
            Class.forName(dbDriver).newInstance();
            connect = DriverManager.getConnection(dbUrl, dbUser, dbPassword);
            
        }
        catch (IllegalAccessException iae) {
            System.err.println(iae.getMessage());
            System.exit(1);
        }
        catch (InstantiationException ie) {
            System.err.println(ie.getMessage());
            System.exit(1);
        }
        catch (ClassNotFoundException cnfe) {
            System.err.println(cnfe.getMessage());
            System.exit(1);
        }
        catch (SQLException sqle) {
            System.err.println(sqle.getMessage());
            System.exit(1);
        }
}


Код не идеальный, но рабочий, возможно стоило включить бок finally где закрыть все, 
но для примера должен подойти. 

Автор: olexander 2.7.2008, 22:21
Всё ещё в свободную минутку пытаюсь расковырять задачку ... 

вопрос по примеру:
Старовъръ
Цитата

private ArrayList<String> columnNames = new ArrayList<String>();
private ArrayList<Class> columnTypes = new ArrayList<Class>();


<String>, <Class> - Это "уточняется" тип массива/ов или "здесь подставь своё"?

Автор: v2v 2.7.2008, 22:25
Цитата(olexander @  2.7.2008,  22:21 Найти цитируемый пост)
тип массива/ов

тип элементов массива.

Автор: olexander 13.7.2008, 15:34
Сейчас застрял на ошибке ошибку которой понять не получается:  smile 
Код

init:
deps-jar:
Compiling 5 source files to D:\workspace\InternalFrameDemo\build\classes
D:\workspace\InternalFrameDemo\src\MyInternalTableFrame_2.java:66: cannot find symbol
symbol  : class MyDatabaseTableModel
location: class components.ButtonPanel_2
            MyDatabaseTableModel model = new MyDatabaseTableModel();
D:\workspace\InternalFrameDemo\src\MyInternalTableFrame_2.java:66: cannot find symbol
symbol  : class MyDatabaseTableModel
location: class components.ButtonPanel_2
            MyDatabaseTableModel model = new MyDatabaseTableModel();
Note: D:\workspace\InternalFrameDemo\src\MyDatabaseTableModel.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
2 errors
BUILD FAILED (total time: 2 seconds)


файл MyDatabaseTableModel.java лежит в одном каталоге с остальными файлами проекта.
Регистр вызова и название вро-де должно совпадать, ибо спецом переносил через copy-paste.

Класс DatabaseTableModel на всяк случай переименовал что-бы исключить ошибку совпадения с существующим классом в MyDatabaseTableModel, но ошибка не пропала ... 

снимок экрана и файлы из каталога src додаю в архиве ...

На данный момент пытаюсь методом тыка слепил на примере InternalFrameDemo из книги инерфейс, состоящий из основного, окна, в котором меню (InternalFrameDemo.java). Пункты меню вызывают отдельные окошки. Сейчас (если не учитывать ошибку) работает изменение строки в БД (MyInternalTableFrame.java) (закоментарено добавление) и вывод таблицы из текста кода (MyInternalTableFrame_1.java). Если избавиться из таблицы то должно ещё в идеале показывать содержимое таблицы на сервере (MyInternalTableFrame_2.java). Файлы MyDatabaseTableModel.java и DatabaseTableModel.java - из примера выше ... 

Автор: olexander 17.7.2008, 10:26
Что можно попробовать? Проверить ... 

Автор: Старовъръ 17.7.2008, 10:35
Так у тебя же все классы находятся в пакете package, а MyDatabaseTableModel - в дефолтном.

Автор: olexander 18.7.2008, 09:30
Старовъръ

А что (как) подправить/изменить что-бы и класс  MyDatabaseTableModel был со всеми?

Автор: olexander 20.7.2008, 10:19
Если в начало файла "MyDatabaseTableModel" добавляю "package components;" аналогично остальным файлам, то ошибка меняется на другую:
Код

init:
deps-jar:
Compiling 5 source files to D:\workspace\InternalFrameDemo\build\classes
D:\workspace\InternalFrameDemo\src\MyInternalTableFrame_2.java:67: unreported exception java.lang.ClassNotFoundException; must be caught or declared to be thrown
            model = new MyDatabaseTableModel();
D:\workspace\InternalFrameDemo\src\MyInternalTableFrame_2.java:70: unreported exception java.lang.ClassNotFoundException; must be caught or declared to be thrown
            model.setDataSource(resultSet);
Note: D:\workspace\InternalFrameDemo\src\MyDatabaseTableModel.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
2 errors
BUILD FAILED (total time: 0 seconds)

Автор: Старовъръ 20.7.2008, 11:33
Вот исправляй теперь эти ошибки. Там все четко написано: из-за того, что не ловишь исключение в try...catch. Думать, думать и еще раз думать smile 

Автор: olexander 20.7.2008, 13:04
ААА !!! пошло !!! smile  smile 

СПАСИБО Старовъръ

а то я всё не мог понять чего он от меня хочет ... 

получается на данный момент итоговый вид после внесённых изменений в файл MyInternalTableFrame_2 получился вследующим:

Код

package components;

import javax.swing.JInternalFrame;

import java.awt.event.*;
import java.awt.*;
import java.lang.reflect.*;
import java.net.*;
import java.text.*;
import java.util.*;
import javax.swing.*;
import javax.swing.text.*;

import javax.swing.table.*;

import java.io.*;
import java.sql.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

/* Used by InternalFrameDemo.java. */
public class MyInternalTableFrame_2 extends JInternalFrame {
    static int openFrameCount = 0;
    static final int xOffset = 60, yOffset = 60;

    public MyInternalTableFrame_2() {
        super("Работники #" + (++openFrameCount), 
              true, //resizable
              true, //closable
              true, //maximizable
              true);//iconifiable

        //...Create the GUI and put it in the window...
        ButtonPanel_2 panel = new ButtonPanel_2();
        add(panel);
        //...Then set the window size or call pack...
        setSize(520, 140);

        //Set the window's location.
        setLocation(xOffset*openFrameCount, yOffset*openFrameCount);
    }
}

class ButtonPanel_2 extends JPanel
{
    private boolean DEBUG = false;
    public ButtonPanel_2()
    {
        Statement statement = null;
        ResultSet resultset;
        Connection conn;
        try
        {
               Class.forName("com.mysql.jdbc.Driver").newInstance();
        }
        catch (Exception ex)
        {
                System.out.println("error!");
        }
        try
        {          
            conn = DriverManager.getConnection(" бала бла бла ... ");
            Statement st = conn.createStatement();
            ResultSet resultSet = st.executeQuery("SELECT * FROM `test`");
            
            try {
                MyDatabaseTableModel model = new MyDatabaseTableModel();
                JTable table = new JTable(model);
                add(table);
                model.setDataSource(resultSet);
                }
            catch (Exception ex)
            {
                System.out.println("error!" + ex.getMessage());
            }
            
        }
        catch (SQLException ex)
        {                     
            System.out.println("SQLException: " + ex.getMessage()); 
            System.out.println("SQLState: "     + ex.getSQLState()); 
            System.out.println("VendorError: "  + ex.getErrorCode());                      
        }
    }
}

Автор: olexander 21.7.2008, 13:30
вопрос: 
Как проще всего согласовать кодировку на сервере БД и которая вводится в клиент под win?

Какую взять кодировку что-бы меньше было перекодировываний?

Пробовал на сервере создать базу и таблицу под UTF8, но не помогло ... 

Кирилица всё равно вопросами ... С латиницей проблем нету ...  smile 

Автор: Ulysses4j 21.7.2008, 14:23
Java по-умолчанию работает с UTF-16, так что базу лучше в ней создать попробовать. И где вы увидели вопросы: если в консоли, то это может означать, что просто консоль не поддерживает Unicode. Можно попорбовать прочитать из базы и записать в файл, а потом открыть в редакторе, который его поддерживает, и посмотреть.

Автор: olexander 22.7.2008, 12:26
и в базе данных и в результатах что показывает "моя табличка" ... 

А какая кодировка когда клиент вводит кирилицу текст под win без кодировок? Подумал создать таблицу под эту кодировку ... Только что ЭТО за кодировка? Сам пока ХЗ ... 

Автор: olexander 26.7.2008, 23:59
В общем удалось ... если в конец строки установки соединения после пароля и перед кавычкой добавить ещё и :
Код

&characterEncoding=KOI8_R


и перевести таблицу БД на KOI8_R то кирилица будет работать на ура. 


В итоге строка из 1-го сообщения получается во что-то подобное:
Код

conn = DriverManager.getConnection("jdbc:mysql://server.ip/test?user=user.name&password=user.pass&characterEncoding=KOI8_R");



PS: вопрос перед тем как закрыть тему: Как лучше организовать редактирование данных в БД (выбор что редактировать ... )

Автор: olexander 27.7.2008, 01:22
Если использовать UTF8, то и с украинскими символами глюка не будет ;)

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)