JavaFX动态表视图 [重复]

问题描述 投票:0回答:1

我试图从DB(使用MySQL)中填充数据到TableView中,我得到的问题是,每当有一个或多个数据出现时,我就会有一个问题。NULL 某个列的数据会出现错误 NullPointerException在使用前 FX 使用 摆动 我使用NetBeans IDE和Gluon Scene Builder。NULL DB上的数据被用于一些条件性的情况下在我的DB中创建视图.我想我知道我的问题是位于我的数据填充。HandlerComponent.java 但我不知道该怎么做。

这是代码列表控制器(TableController).java

public class TableController implements Initializable {
    Connection CONN;
    Database DB = new Database();
    HandlerComponent COMP_HANDLER;
    @FXML
    private TableView tblView;
    @FXML
    private Button btnLoad;
    @FXML
    private TextField txTable;
    @FXML
    private Label lblKolom1;
    @FXML
    private TextField txKolom1;
    @FXML
    private Label lblKolom2;
    @FXML
    private TextField txKolom2;
    @FXML
    private Button btnTambah;
    @FXML
    private Button btnHapus;
    @FXML
    private Button btnReset;

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        try {
            COMP_HANDLER = new HandlerComponent();
            tblView = COMP_HANDLER.iniTable(tblView, "SELECT * FROM items", DB);

        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }    

    @FXML
    public void loadTable() {
        try {
            tblView.getColumns().clear();
            tblView = COMP_HANDLER.iniTable(tblView, "SELECT * FROM "+txTable.getText(), DB);
            tblView.refresh();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    @FXML
    public void getDataTable(javafx.scene.input.MouseEvent e) {
        if(e.getClickCount() == 2 && !e.isConsumed()) {
            System.out.println("double Clicked");
        }
    }
}

表.fxml

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

<?import java.net.URL?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.FlowPane?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.layout.VBox?>

<AnchorPane id="AnchorPane" prefHeight="513.0" prefWidth="600.0" style="-fx-background-color: #123456;" styleClass="mainFxmlClass" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="Controller.TableController">
    <stylesheets>
        <URL value="@designskena.css" />
    </stylesheets>
   <children>
      <VBox prefHeight="497.0" prefWidth="600.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
         <children>
            <FlowPane prefHeight="79.0" prefWidth="600.0">
               <children>
                  <Button fx:id="btnLoad" mnemonicParsing="false" onAction="#loadTable" prefHeight="58.0" prefWidth="92.0" text="Load Data">
                     <FlowPane.margin>
                        <Insets />
                     </FlowPane.margin>
                  </Button>
                  <TextField fx:id="txTable" prefHeight="58.0" prefWidth="431.0" text="Table">
                     <FlowPane.margin>
                        <Insets left="25.0" />
                     </FlowPane.margin>
                  </TextField>
               </children>
               <VBox.margin>
                  <Insets />
               </VBox.margin>
               <padding>
                  <Insets bottom="25.0" left="25.0" right="25.0" top="25.0" />
               </padding></FlowPane>
            <TableView fx:id="tblView" onMouseClicked="#getDataTable" prefHeight="258.0" prefWidth="600.0" style="-fx-background-color: black;" stylesheets="@designskena.css">              
               <VBox.margin>
                  <Insets left="25.0" right="25.0" />
               </VBox.margin>
            </TableView>
            <Pane prefHeight="165.0" prefWidth="600.0">
               <children>
                  <Label fx:id="lblKolom1" layoutX="25.0" layoutY="14.0" prefHeight="17.0" prefWidth="58.0" text="Kolom 1" />
                  <TextField fx:id="txKolom1" layoutX="25.0" layoutY="38.0" />
                  <Label fx:id="lblKolom2" layoutX="206.0" layoutY="14.0" prefHeight="17.0" prefWidth="58.0" text="Kolom 2" />
                  <TextField fx:id="txKolom2" layoutX="206.0" layoutY="38.0" />
                  <Button fx:id="btnTambah" layoutX="25.0" layoutY="86.0" mnemonicParsing="false" text="Tambah" />
                  <Button fx:id="btnHapus" layoutX="99.0" layoutY="86.0" mnemonicParsing="false" text="Hapus" />
                  <Button fx:id="btnReset" layoutX="163.0" layoutY="86.0" mnemonicParsing="false" text="Reset" />
               </children>
               <padding>
                  <Insets bottom="25.0" left="25.0" right="25.0" top="25.0" />
               </padding>
            </Pane>
         </children>
      </VBox>
   </children>
</AnchorPane>

这就是 HandlerComponent.java

import java.sql.Connection;
import java.sql.SQLException;
import java.sql.ResultSet;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableColumn.CellDataFeatures;
import javafx.scene.control.TableView;
import javafx.util.Callback;
/**
 * Class untuk membantu konfigurasi setiap COMPONENT JavaFX
 * yang terdapat pada java dengan koneksi Database.
 * @author RHS
 * @version 0.1a
 */
public class HandlerComponent {
    protected Connection H_CONN;
    protected ResultSet H_RESULTSET;
    // Properti yang dibutuhkan untuk Handler Tabel
    public String[] COLUMN_TYPE, COLUMN_NAME;
    public Object[] OBJ_DATA;

    /**
     * <b>Constructor</b> untuk kelas <i>HandlerComponent</i>, akan memanggil metode untuk 
     * koneksi driver database pada kelas database, dengan menyimpan 
     * koneksi pada variable <i><b>H_CONN</b></i>
     * @throws SQLException 
     */
    public HandlerComponent() throws SQLException {
        H_CONN = new Database().inisiasiDB();
    }

    public TableView iniTable(TableView TABLE, String SQL, Database DBClass) {
        ObservableList<ObservableList> DATA = FXCollections.observableArrayList();
        try 
        {
            //H_CONN = new DBClass().inisiasiDB();
            H_RESULTSET = DBClass.getSQL(SQL);
            int count = H_RESULTSET.getMetaData().getColumnCount();
            COLUMN_NAME = new String[count];
            COLUMN_TYPE = new String[count];
            OBJ_DATA = new Object[count];

            /**
             * ======================================
             * Pembuatan Kolom tabel secara dinamis *
             * ======================================
             */
            for(int x=0; x<count; x++) {
                final int j = x;
                // pengecekan nama-kolom pada database untuk digenerate pada 
                // tabel yang dituju serta pengecekan tipedata pada tiap kolom
                // yang kemudian akan disimpan pada variable String array
                // COLUMN_NAME[] dan COLUMN_TYPE
                COLUMN_NAME[x] = H_RESULTSET.getMetaData().getColumnName(x+1);
                COLUMN_TYPE[x] = H_RESULTSET.getMetaData().getColumnTypeName(x+1);
                System.out.print(COLUMN_TYPE[x]);

                // pembuatan kolom tabel berdasarkan COLUMN_NAME
                // yang telah dibuat
                TableColumn col = new TableColumn(COLUMN_NAME[x]);

                // this is where the NullPointerException are triggered
                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());
                    }
                });

                // Menambahkan kolom yang sudah di generate sebelumnya
                // ke dalam tabel tabel tujuan
                TABLE.getColumns().addAll(col);
                System.out.println(" | Column [" + x + "] "+col);
            }

            /** 
             * ============================
             * Penambahan Data pada tabel *
             * ============================
             */
            while(H_RESULTSET.next()) {
                // pembuatan tipe data ObservableList untuk digunakan 
                // dalam menampung data yang akan dimasukan dalam tabel perbarisnya
                ObservableList<Object> row = FXCollections.observableArrayList();
                for (int x = 1; x <= count; x++) {
                    // pengecekan data pada setiap kolom yang ada di database
                    // pada baris yang sama untuk disesuaikan tipedata yg nantinya
                    // akan disimpan dalam tipedata Object
                    switch(COLUMN_TYPE[x-1]) {
                        case "INT" :
                            OBJ_DATA[x-1] = H_RESULTSET.getInt(x);
                            break;
                        case "DOUBLE" :
                            OBJ_DATA[x-1] = H_RESULTSET.getDouble(x);
                            break;
                        case "FLOAT" :
                            OBJ_DATA[x-1] = H_RESULTSET.getFloat(x);
                            break;
                        case "VARCHAR" :
                            OBJ_DATA[x-1] = H_RESULTSET.getString(x);
                            break;
                        case "CHAR" :
                            OBJ_DATA[x-1] = H_RESULTSET.getString(x);
                            break;
                        case "TEXT" :
                            OBJ_DATA[x-1] = H_RESULTSET.getString(x);
                            break;
                        case "DATE" :
                            OBJ_DATA[x-1] = H_RESULTSET.getString(x);
                            break;                        
                        default :
                            OBJ_DATA[x-1] = "Unkown Datatype (HandlerComponent.Java)";
                            break;
                    }
                    //
                    row.add(OBJ_DATA[x-1]);
                }
                System.out.println("Row [1] added " + row);
                DATA.add(row);
            }

            TABLE.setItems(DATA);
        } catch (SQLException ex) {
            ex.printStackTrace();
            System.out.println("Error on Building Data");
        }
        return TABLE;
    }
}

这是 数据库.java

import com.mysql.jdbc.Driver;
import java.sql.Connection; import java.sql.DriverManager;
import java.sql.ResultSet; import java.sql.PreparedStatement;
import java.sql.Statement; import java.sql.SQLException;
import javax.swing.JOptionPane;

public class Database {
    private static Connection config;
    private Connection CONFIG;
    private static Driver DRIVER_MANAGER;
    private static String PARAMETER_CONN;
    public static String DB_HOST, DB_PORT, DB_NAME, DB_USER, DB_PASS, STMT, LOG;
    public ResultSet RES;
    public Statement STM;
    public PreparedStatement PREP;

    public Database() {
        Database.setDB_HOST("localhost");
        Database.setDB_NAME("rab");
        Database.setDB_USER("root");
        Database.setDB_PASS("");
        Database.setDB_PORT("3306");
    }

    public Database(String db_name, String user, String pass) {
        Database.DB_NAME = db_name; Database.DB_USER = user;
        Database.DB_PASS = pass;
    }

    public static void setDB_HOST(String DB_HOST) {
        Database.DB_HOST = DB_HOST;
    }

    public static void setDB_PORT(String DB_PORT) {
        Database.DB_PORT = DB_PORT;
    }

    public static void setDB_NAME(String DB_NAME) {
        Database.DB_NAME = DB_NAME;
    }

    public static void setDB_USER(String DB_USER) {
        Database.DB_USER = DB_USER;
    }

    public static void setDB_PASS(String DB_PASS) {
        Database.DB_PASS = DB_PASS;
    }

    public static void setConfig(Connection config) {
        Database.config = config;
    }

    public void setConfigs(Connection config) {
        CONFIG = config;
    }

    public static void setSTMT(String STMT) {
        Database.STMT = STMT;
    }

    public Connection getConfig() {
        return config;
    }

    protected String getLog() {
        return LOG;
    }
    protected void setLog(String Description)  {
        Database.LOG = ("\nQuery Performed :"+Description+" =========================================\n"
                + Database.STMT
                + "\n========================================================\n");
    }
    protected void setLog(String Description, String SQL)  {
        Database.LOG = ("\nQuery Performed :"+Description+" =========================================\n"
                + SQL
                + "\n========================================================\n");
    }
    /**
     * Query Select untuk SQL 
     * dengan syarat harus memberikan query pada property STMT
     * e.g. "<i>SELECT * FROM <b>namaTable</b></i>"<br> atau "<i>SELECT * FROM <b>namaTable</b> WHERE <b>kolom</b> = "<u>kondisi</u>"</i>"
     * @return ResultSet executeQuery();
     * @throws SQLException 
     * @see setSTMT();
     */
    public ResultSet getSQL() throws SQLException {
        checkConnection();
        STM = Database.config.createStatement();
        LOG = Database.STMT;
        RES = STM.executeQuery(Database.STMT);
        setLog("Getting Data");
        System.out.println(getLog());
        return RES;
    }

    /**
     * Query Select untuk SQL dengan Custom Parameter
     * @param Query String SQL
     * e.g. "<i>SELECT * FROM <b>namaTable</b></i>"<br> atau "<i>SELECT * FROM <b>namaTable</b> WHERE <b>kolom</b> = "<u>kondisi</u>"</i>"
     * @return ResultSet executeQuery();
     * @throws SQLException 
     */ 
    public ResultSet getSQL(String Query) throws SQLException {
        //checkConnection();
        STM = Database.config.createStatement();;
        setLog("Getting Data", Query);
        System.out.println(getLog());
        return (RES = STM.executeQuery(Query));
    }

    public int insertSQL(Object[] DATA, String TABLE, String PRIMARY_KEY) throws SQLException {
        String[] SQL = Database.STMT.split("\\s");
        int result = 0;
        // pengecualian table cek
        if( (searchIndexDB(DATA[0].toString(),PRIMARY_KEY,TABLE) == -1)
            || (SQL[0].equalsIgnoreCase("UPDATE"))
            || (TABLE.equalsIgnoreCase("orderdetail"))
            || (TABLE.equalsIgnoreCase("recipe"))) {
            //System.out.println("Data ["+DATA[0]+"] belum ada di DB");
            PREP = Database.config.prepareStatement(STMT);
            String typedata = "";
            int pointer = 0;
            if(SQL[0].equalsIgnoreCase("UPDATE")){
                setLog("Update Data");
                result = 2;
            }
            else {
                setLog("Insert Data");
                result = 1;
            }
            System.out.println(getLog());
            for (Object temp : DATA) {
                typedata = temp.getClass().getSimpleName();
                System.out.println(temp.getClass().getSimpleName()+" : "+DATA[pointer]);
                switch (typedata) {
                    case "String" :
                        PREP.setString(pointer+1, DATA[pointer].toString());
                        break;
                    case "Integer" :
                        PREP.setInt(pointer+1, Integer.parseInt(DATA[pointer].toString()));
                        break;
                    case "Float" :
                        PREP.setFloat(pointer+1, Float.parseFloat(DATA[pointer].toString()));
                        break;
                    case "Double" :
                        PREP.setDouble(pointer+1,Double.parseDouble(DATA[pointer].toString()));
                        break;
                }
                pointer++;
            }
            PREP.executeUpdate();
            return result;
        }else{  
            System.out.println("Data ["+DATA[0]+"] Sudah ada di DB\n"
                            + "Silahkan Gunakan fitur Update");
            JOptionPane.showMessageDialog(null, "Ooppss!. Data tersebut sudah ada\n"
                    + "Silahkan gunakan Fitur UPDATE","Warning",1);
            return result;
        }
    }

    public int deleteSQL(String KEY) throws SQLException{
        checkConnection();
        PREP = Database.config.prepareStatement(STMT);
        PREP.setString(1, KEY);
        setLog("Delete Data");
        System.out.println(getLog());
        return (PREP.executeUpdate());
    }
    public int deleteSQL(String KEY, String SQL) throws SQLException{
        checkConnection();
        setSTMT(SQL);
        setLog("Delete Data");
        System.out.println(getLog());
        PREP = Database.config.prepareStatement(STMT);
        PREP.setString(1, KEY);
        return (PREP.executeUpdate());
    }

    /**
     * Metode untuk mencari adanya data dalam DB
     * e.g. searchIndexDB(<u>textField.getText(), "kolom", "table"</u>) atau<br>
     * searchIndexDB(<u>txID.getText(), "id", "user"</u>)
     * @param SEARCH data yang ingin dicari
     * @param FIELD kolom field yang dicari
     * @param TABLE table yang dicari
     * @return mengembalikan tipedata Integer, bernilai -1 jika tidak ditemukan,<br>dan akan mengembalikan nilai index jika ditemukan dalam DB;
     * @throws SQLException 
     */ 
    public int searchIndexDB(String SEARCH, String FIELD, String TABLE) throws SQLException {
        int index = -1, i = 0;
        //Database.setSTMT("SELECT "+FIELD+" FROM "+TABLE+" ORDER BY "+FIELD+" ASC");
        RES = getSQL("SELECT "+FIELD+" FROM "+TABLE+" ORDER BY "+FIELD+" ASC");
        while (RES.next()) {
            if(true == RES.getString(1).equalsIgnoreCase(SEARCH)) {                
                index = i;
                break;
            }
            i++;
        }
        setLog("Search Index");
        System.out.println(getLog());
        return index;
    }

    public static Connection inisiasiDB() throws SQLException {
        if ((Database.DB_NAME == null) || (Database.DB_USER == null) || (Database.DB_PASS == null) || (Database.DB_PORT == null) || (Database.DB_HOST == null)) {
            JOptionPane.showMessageDialog(null,"Database Belum disetting");
             if (Database.DB_NAME == null) {
                 String DBname = JOptionPane.showInputDialog("Nama Database");
                 Database.DB_NAME = DBname;
             }
             if (Database.DB_USER == null) setDB_USER(JOptionPane.showInputDialog("User"));
             if (Database.DB_PASS == null) Database.DB_PASS = JOptionPane.showInputDialog("Password");
             if (Database.DB_PORT == null) Database.DB_PORT = JOptionPane.showInputDialog("Port");
             if (Database.DB_HOST == null) Database.DB_HOST = JOptionPane.showInputDialog("Host");
             Database.PARAMETER_CONN = "jdbc:mysql://"+Database.DB_HOST+":"+Database.DB_PORT+"/"+Database.DB_NAME;
        }
        try {
            Database.DRIVER_MANAGER = new com.mysql.jdbc.Driver();
            Database.PARAMETER_CONN = "jdbc:mysql://"+Database.DB_HOST+":"+Database.DB_PORT+"/"+Database.DB_NAME;
            DriverManager.registerDriver(DRIVER_MANAGER);
            setConfig(DriverManager.getConnection(Database.PARAMETER_CONN,Database.DB_USER, Database.DB_PASS));
            System.out.println("Koneksi Sukses ========================\n DB_NAME : "+DB_NAME);
        } catch (SQLException ex) {
            ex.printStackTrace();
            JOptionPane.showMessageDialog(null,"Driver untuk Koneksi database tidak ada\nSilahkan nyalakan services MySQL pada XAMPP");
        }
        return config;
    }

    public Connection inisiasiDBnoStatic() throws SQLException {
        if ((Database.DB_NAME == null) || (Database.DB_USER == null) || (Database.DB_PASS == null) || (Database.DB_PORT == null) || (Database.DB_HOST == null)) {
            JOptionPane.showMessageDialog(null,"Database Belum disetting");
             if (Database.DB_NAME == null) {
                 String DBname = JOptionPane.showInputDialog("Nama Database");
                 Database.DB_NAME = DBname;
             }
             if (Database.DB_USER == null) setDB_USER(JOptionPane.showInputDialog("User"));
             if (Database.DB_PASS == null) Database.DB_PASS = JOptionPane.showInputDialog("Password");
             if (Database.DB_PORT == null) Database.DB_PORT = JOptionPane.showInputDialog("Port");
             if (Database.DB_HOST == null) Database.DB_HOST = JOptionPane.showInputDialog("Host");
             Database.PARAMETER_CONN = "jdbc:mysql://"+Database.DB_HOST+":"+Database.DB_PORT+"/"+Database.DB_NAME;
        }
        try {
            Database.DRIVER_MANAGER = new com.mysql.jdbc.Driver();
            Database.PARAMETER_CONN = "jdbc:mysql://"+Database.DB_HOST+":"+Database.DB_PORT+"/"+Database.DB_NAME;
            DriverManager.registerDriver(DRIVER_MANAGER);
            setConfigs(DriverManager.getConnection(Database.PARAMETER_CONN,Database.DB_USER, Database.DB_PASS));
            System.out.println("Koneksi Sukses ========================\n DB_NAME : "+DB_NAME);
        } catch (SQLException ex) {
            ex.printStackTrace();
            JOptionPane.showMessageDialog(null,"Driver untuk Koneksi database tidak ada\nSilahkan nyalakan services MySQL pada XAMPP");
        }
        return CONFIG;
    }

    private void checkConnection() throws SQLException{
        if(getConfig() == null) {
            setConfig(inisiasiDB());
        }
    }

    public int lastInventID(){
        int result= -1;
        try {
            checkConnection(); 
            setSTMT("SELECT no FROM inventory ORDER BY no ASC");
            RES = getSQL(); RES.last();
            result = RES.getInt(1);
            result++;
        } catch (SQLException ex){
            ex.printStackTrace();
        }
        return result;
    }

    public String generateOrderID() {
        try {
            checkConnection();
            String temp;
            RES = getSQL("SELECT orderID FROM orderhead ORDER BY orderID");
            LOG = STMT;
            RES.last();
            temp = RES.getString("orderID");
            int increase = Integer.parseInt(temp);
            int digit = String.valueOf(increase).length();
            switch (digit) {
                case 1: {increase++;temp = "000"+increase;}
                    break;
                case 2: {increase++;temp = "00"+increase;}
                    break;
                case 3: {increase++;temp = "0"+increase;}
                    break;
                default: {increase++;temp = ""+increase;}
                    break;
            }
            RES.close();
            return temp;            
        } catch(SQLException ex) {
            ex.printStackTrace();
        }
        return "";
    }
}

异常堆栈

Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
    at Model.HandlerComponent$1.call(HandlerComponent.java:67)
    at Model.HandlerComponent$1.call(HandlerComponent.java:65)
java mysql javafx javafx-8
1个回答
1
投票

你只需要在调用之前检查是否为null就可以了 toString():

col.setCellValueFactory(new Callback<CellDataFeatures<ObservableList, String>, ObservableValue<String>>() {
    public ObservableValue<String> call(CellDataFeatures<ObservableList, String> param) {
        Object value = param.getValue().get(j) ;
        return new SimpleStringProperty(value == null ? "" : value.toString());
    }
});
© www.soinside.com 2019 - 2024. All rights reserved.