JavaFX 动态表视图
JavaFX Dynamic TableView
我正在尝试将数据库中的数据(使用 MySQL)填充到 TableView 中,
我遇到的问题是,每当某些列中有 NULL 数据时
在使用FX之前会出现错误NullPointerException im using SWING组件
而且我的代码没有问题,我很难移植它。我正在使用 NetBeans IDE 和 Gluon Scene Builder。
数据库上的 NULL 数据专门用于某些条件情况以在我的数据库中创建视图。
我想我知道我的问题出在 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");
}
}
}
Table.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;
}
}
这是Database.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.call(HandlerComponent.java:67)
at Model.HandlerComponent.call(HandlerComponent.java:65)
您只需在尝试调用 toString()
:
之前检查是否为 null
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());
}
});
我正在尝试将数据库中的数据(使用 MySQL)填充到 TableView 中, 我遇到的问题是,每当某些列中有 NULL 数据时 在使用FX之前会出现错误NullPointerException im using SWING组件 而且我的代码没有问题,我很难移植它。我正在使用 NetBeans IDE 和 Gluon Scene Builder。 数据库上的 NULL 数据专门用于某些条件情况以在我的数据库中创建视图。 我想我知道我的问题出在 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");
}
}
}
Table.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;
}
}
这是Database.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.call(HandlerComponent.java:67)
at Model.HandlerComponent.call(HandlerComponent.java:65)
您只需在尝试调用 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());
}
});