如何用数据库数据填充 TableView

Posted

技术标签:

【中文标题】如何用数据库数据填充 TableView【英文标题】:How to fill up a TableView with database data 【发布时间】:2013-09-27 06:39:42 【问题描述】:

我一直在尝试使用从数据库查询的数据加载 TableView,但似乎无法正常工作。

这是我第一次尝试使用数据库查询项填充 TableView - 以防我的代码看起来杂乱无章并且远非良好。

FXML 是通过 JavaFX SceneBuilder 完成的。

这是数据库查询类:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.control.TableView;

public class StudentInfo 
    static String JDBC_DRIVER = "org.h2.Driver";
    static String DB_URL = "jdbc:h2:file:C:/WAKILI/WAKILIdb";
    //  Database credentials
    static final String USER = "sa";
    static final String PASS = "";
    
    public static Connection conn = null;
    @FXML
    private TableView<StudentInfo> lovelyStudents;
    
    private ObservableList data;

    // Public static ObservableList<COA> getAllCOA()
    public void getAllstudentInfo() 
        Statement st = null;
        ResultSet rs;
        String driver = "org.h2.Driver";

        try 
            Class.forName(driver);
            conn = DriverManager.getConnection(DB_URL, USER, PASS);
            st = conn.createStatement();
            String recordQuery = ("SELECT id, KIWI FROM KIWI");
            
            rs = st.executeQuery(recordQuery);
            while (rs.next()) 
                ObservableList row = FXCollections.observableArrayList();
                
                for (int i = 1; i <= rs.getMetaData().getColumnCount(); i++) 
                    row.add(rs.getString(i));
                    System.out.println(row);
                
                
                data.add(row);
                
            
            lovelyStudents.setItems(data);
            
         catch (ClassNotFoundException | SQLException ex) 
            // CATCH SOMETHING
        
    

这是通过 JavaFX 场景生成器生成的 FXML 脚本:

<?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<AnchorPane id="AnchorPane" prefHeight="400.0" prefWidth="700.0" xmlns:fx="http://javafx.com/fxml" fx:controller="wakiliproject.SampleController">
  <children>
    <TableView prefHeight="400.0" prefWidth="700.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
      <columns>
        <TableColumn prefWidth="75.0" text="Column X" />
      </columns>
    </TableView>
  </children>
</AnchorPane>

【问题讨论】:

Filling up a Table with database data not working 的可能重复项 【参考方案1】:

这里是从数据库向tableView填充数据的最佳方案。

import java.sql.Connection;
import java.sql.ResultSet;
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableColumn.CellDataFeatures;
import javafx.scene.control.TableView;
import javafx.stage.Stage;
import javafx.util.Callback;

/**
 * 
 * @author Narayan
 */

public class DynamicTable extends Application

    //TABLE VIEW AND DATA
    private ObservableList<ObservableList> data;
    private TableView tableview;

    //MAIN EXECUTOR
    public static void main(String[] args) 
        launch(args);
    

    //CONNECTION DATABASE
    public void buildData()
          Connection c ;
          data = FXCollections.observableArrayList();
          try
            c = DBConnect.connect();
            //SQL FOR SELECTING ALL OF CUSTOMER
            String SQL = "SELECT * from CUSTOMer";
            //ResultSet
            ResultSet rs = c.createStatement().executeQuery(SQL);

            /**********************************
             * TABLE COLUMN ADDED DYNAMICALLY *
             **********************************/
            for(int i=0 ; i<rs.getMetaData().getColumnCount(); i++)
                //We are using non property style for making dynamic table
                final int j = i;                
                TableColumn col = new TableColumn(rs.getMetaData().getColumnName(i+1));
                col.setCellValueFactory(new Callback<CellDataFeatures<ObservableList,String>,ObservableValue<String>>()                    
                    public ObservableValue<String> call(CellDataFeatures<ObservableList, String> param)                                                                                               
                        return new SimpleStringProperty(param.getValue().get(j).toString());                        
                                        
                );

                tableview.getColumns().addAll(col); 
                System.out.println("Column ["+i+"] ");
            

            /********************************
             * Data added to ObservableList *
             ********************************/
            while(rs.next())
                //Iterate Row
                ObservableList<String> row = FXCollections.observableArrayList();
                for(int i=1 ; i<=rs.getMetaData().getColumnCount(); i++)
                    //Iterate Column
                    row.add(rs.getString(i));
                
                System.out.println("Row [1] added "+row );
                data.add(row);

            

            //FINALLY ADDED TO TableView
            tableview.setItems(data);
          catch(Exception e)
              e.printStackTrace();
              System.out.println("Error on Building Data");             
          
      


      @Override
      public void start(Stage stage) throws Exception 
        //TableView
        tableview = new TableView();
        buildData();

        //Main Scene
        Scene scene = new Scene(tableview);        

        stage.setScene(scene);
        stage.show();
      

这里是Reference

谢谢..

【讨论】:

我已将此代码连接到 sqlite 数据库,它工作正常,但仅在我不使用此代码“tableview.setItems(data);”时添加列当我使用此代码时,它会加载列但不加载行并给出大量错误【参考方案2】:

如果Database包含不同类型的数据,不仅仅是String,那么列类型分配最好是动态的:

package sample;

import javafx.application.Application;
import javafx.beans.property.*;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.stage.Stage;
import java.sql.*;
import java.util.ArrayList;
import java.util.TimeZone;

//Author: Yerbol
//SQL database "sqlbase_schema" contains a Table "sqlbase_table" with 3 columns: "id" (Integer(INT(11))), "name" (String(VARCHAR(45))), "married" (Boolean(TINYINT(1)));

public class Main extends Application 
    private TableView<Person> tableView = new TableView<>();

    @Override
    public void start(Stage primaryStage) throws SQLException, ClassNotFoundException 
        //Show window
        buildData();
        Parent root = tableView;
        primaryStage.setScene(new Scene(root, 300, 275));
        primaryStage.show();
    

    public void buildData() throws ClassNotFoundException, SQLException 

        Connection dbConnection;
        //SQL Database connection params
        String dbHost = "localhost";
        String dbPort = "3306";
        String dbUser = "root";
        String dbPassword = "12345";
        String dbName = "sqlbase_schema";
        String dbTableName = "sqlbase_table";
        String select = "SELECT * FROM " + dbTableName;
        String connectionString = "jdbc:mysql://" + dbHost + ":" + dbPort +"/" + dbName+"?useLegacyDatetimeCode=false&amp&serverTimezone=" + TimeZone.getDefault().getID();
        Class.forName("com.mysql.cj.jdbc.Driver");

        //Connecting to Database
        dbConnection = DriverManager.getConnection(connectionString, dbUser, dbPassword);

        //Extracting data from Databasee
        ResultSet resultSet = null;
        try 
            PreparedStatement preparedStatement = dbConnection.prepareStatement(select);
            resultSet = preparedStatement.executeQuery();

         catch (SQLException e) 
            e.printStackTrace();
        

        ObservableList dbData = FXCollections.observableArrayList(dataBaseArrayList(resultSet));

        //Giving readable names to columns
        for(int i=0 ; i<resultSet.getMetaData().getColumnCount(); i++) 
            TableColumn column = new TableColumn<>();
            switch (resultSet.getMetaData().getColumnName(i+1)) 
                case "id":
                    column.setText("ID #");
                    break;
                case "name":
                    column.setText("Person Name");
                    break;
                case "married":
                    column.setText("Marital Status");
                    break;
                default: column.setText(resultSet.getMetaData().getColumnName(i+1)); //if column name in SQL Database is not found, then TableView column receive SQL Database current column name (not readable)
                    break;
            
            column.setCellValueFactory(new PropertyValueFactory<>(resultSet.getMetaData().getColumnName(i+1))); //Setting cell property value to correct variable from Person class.
            tableView.getColumns().add(column);
        

        //Filling up tableView with data
        tableView.setItems(dbData);
    

    public class Person 

        IntegerProperty id = new SimpleIntegerProperty(); //variable names should be exactly as column names in SQL Database Table. In case if you want to use <int> type instead of <IntegerProperty>, then you need to use getter/setter procedures instead of xxxProperty() below
        StringProperty name = new SimpleStringProperty();
        BooleanProperty married = new SimpleBooleanProperty();

        public IntegerProperty idProperty()  //name should be exactly like this [IntegerProperty variable name (id) + (Property) = idProperty] (case sensitive)
            return id;
        

        public StringProperty nameProperty() 
            return name;
        

        public BooleanProperty marriedProperty() 
            return married;
        

        public Person(int idValue, String nameValue, boolean marriedValue) 
            id.set(idValue);
            name.set(nameValue);
            married.set(marriedValue);
        

        Person()
    

    //extracting data from ResulSet to ArrayList
    private ArrayList dataBaseArrayList(ResultSet resultSet) throws SQLException 
        ArrayList<Person> data =  new ArrayList<>();
        while (resultSet.next()) 
            Person person = new Person();
            person.id.set(resultSet.getInt("id"));
            person.name.set(resultSet.getString("name"));
            person.married.set(resultSet.getBoolean("married"));
            data.add(person);
        
        return data;
    

    public static void main(String[] args) 
        launch(args);
    

在此示例中,SQL 数据库“sqlbase_schema”包含一个包含 3 列的表“sqlbase_table”:“id”(Integer(INT(11)))、“name”(String(VARCHAR(45)))、“married (布尔(TINYINT(1)));

【讨论】:

检查这些链接link1 & link2【参考方案3】:
public TableView queryToTable(String sql) 
    TableView result = new TableView();
    ObservableList data = FXCollections.observableArrayList();

    jdbcTemplate.query(sql, (rs)->
        for(int i=0 ; i<rs.getMetaData().getColumnCount(); i++)
            final int j = i;
            TableColumn col = new TableColumn(rs.getMetaData().getColumnName(i+1));
            col.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<ObservableList,String>,ObservableValue<String>>()
                public ObservableValue<String> call(TableColumn.CellDataFeatures<ObservableList, String> param) 
                    return new SimpleStringProperty(param.getValue().get(j).toString());
                
            );
            result.getColumns().addAll(col);
        

        while(rs.next())
            ObservableList<String> row = FXCollections.observableArrayList();
            for(int i=1 ; i<=rs.getMetaData().getColumnCount(); i++)
                row.add(rs.getString(i));
            data.add(row);
        
        return null;
    );
    return result;

【讨论】:

不鼓励使用纯代码的答案。请点击edit 并添加一些词来总结您的代码如何解决问题,或者解释您的答案与之前的答案/答案有何不同。谢谢

以上是关于如何用数据库数据填充 TableView的主要内容,如果未能解决你的问题,请参考以下文章

如何用 ASIHttpRequest JSON 数据填充 UITableView?

如何用其他数据框的值填充缺失值

如何用随机字典值填充熊猫数据框列

如何用核心数据填充选择器控制器

如何用多个表填充数据集?

如何用 Ext.Net 数据库中的数据填充 GridPanel?