I’ve been trying to load a TableView with data queried from a database but I can’t seem to understand how I am supposed to attach it to the database and display it on the TableView. Note: I wanna access multiple tables within my database
This is the database connection:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
//dataAccess
public class DBConnect {
public Connection link;
public DBConnect(String driverClassName, String dbURL, String user, String password) throws ClassNotFoundException, SQLException {
Class.forName(driverClassName);
link = DriverManager.getConnection(dbURL, user, password);
}
public void shutdown() throws SQLException {
if (link != null){
link.close();
}
}
public List<Data> getDataList() throws SQLException {
try (Statement stmnt = link.createStatement();
ResultSet rs = stmnt.executeQuery("select * from fish"); //only connects to fish table
){
List<Data> dataList = new ArrayList<>();
while (rs.next()) {
String museum = rs.getString("MuseumID");
String name = rs.getString("FishID");
String location = rs.getString("Location");
String date_found = rs.getString("DateFound");
Data dataset = new Data(museum, name, location, date_found);
dataList.add(dataset);
}
return dataList ;
}
}
}
This is the FXML script
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.text.Font?>
<?import javafx.scene.text.Text?>
<Pane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="500.0" xmlns="http://javafx.com/javafx/20.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.example.nookipediademo.NookController">
<children>
<AnchorPane prefHeight="414.0" prefWidth="500.0" style="-fx-background-color: #ece5ce;">
<children>
<Button fx:id="btn_insects" layoutX="28.0" layoutY="90.0" mnemonicParsing="false" prefHeight="25.0" prefWidth="89.0" style="-fx-background-color: #c8c8a9;" text="Insects" textFill="#774f38" />
<Button fx:id="btn_seacreatures" layoutX="29.0" layoutY="55.0" mnemonicParsing="false" style="-fx-background-color: #c8c8a9;" text="Sea Creatures" textFill="#774f38" />
<Button fx:id="btn_fish" layoutX="28.0" layoutY="22.0" mnemonicParsing="false" prefHeight="25.0" prefWidth="89.0" style="-fx-background-color: #c8c8a9;" text="Fish" textFill="#774f38" />
<Text fill="#774f38" layoutX="139.0" layoutY="63.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Nook Pack" textAlignment="CENTER" wrappingWidth="334.0000305175782">
<font>
<Font name="Britannic Bold" size="48.0" />
</font>
</Text>
<Button fx:id="btn_search" layoutX="414.0" layoutY="90.0" mnemonicParsing="false" style="-fx-background-color: #c8c8a9;" text="SEARCH" textFill="#774f38" />
<TextField fx:id="search_input" layoutX="139.0" layoutY="90.0" prefHeight="25.0" prefWidth="263.0" promptText="Search Museum Catalog" />
<BorderPane layoutX="25.0" layoutY="150.0" prefHeight="250.0" prefWidth="450.0">
<center>
<TableView fx:id="table_display" editable="true" prefHeight="200.0" prefWidth="200.0" style="-fx-background-color: #83af9b;" BorderPane.alignment="CENTER">
<columns>
<TableColumn id="museum_display" fx:id="museum_display" prefWidth="90.0" style="-fx-background-color: #c8c8a9;" text="Museum" />
<TableColumn id="name_display" fx:id="name_display" prefWidth="150.0" style="-fx-background-color: #c8c8a9; -fx-text-color: #774f38;" text="Name" />
<TableColumn id="location_display" fx:id="location_display" prefWidth="90.0" style="-fx-background-color: #c8c8a9;" text="Location" />
<TableColumn id="datefound_display" fx:id="datefound_display" prefWidth="117.0" style="-fx-background-color: #c8c8a9;" text="Date Found" />
</columns>
</TableView>
</center>
</BorderPane>
</children>
</AnchorPane>
</children>
</Pane>
This is the data information class
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
public class Data {
private final StringProperty museum = new SimpleStringProperty();
private final StringProperty name = new SimpleStringProperty();
private final StringProperty location = new SimpleStringProperty();
private final StringProperty date_found = new SimpleStringProperty();
public StringProperty getMuseum() { return museum; }
public void setMuseum(String museum) { this.museum.set(museum); }
public StringProperty getName() {
return name;
}
public void setName(String name) {
this.name.set(name);
}
public StringProperty getLocation() {
return location;
}
public void setLocation(String location) { this.location.set(location);}
public StringProperty getDate_found() {
return date_found;
}
public void setDate_found(String date_found) { this.date_found.set(date_found); }
public Data(String museumID, String name, String place, String found_date){
setMuseum(museumID);
setName(name);
setLocation(place);
setDate_found(found_date);
}
public Data(String museumID, String name, String found_date){
setMuseum(museumID);
setName(name);
setDate_found(found_date);
}
}
the controller currently only has the gui names
import javafx.fxml.FXML;
import javafx.scene.control.TableView;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TextField;
public class NookController {
@FXML
private Button btn_fish;
@FXML
private Button btn_insects;
@FXML
private Button btn_seacreatures;
@FXML
private TextField search_input;
@FXML
private Button btn_search;
@FXML
private TableView<Data> table_display;
@FXML
private TableColumn<Data, String> datefound_display;
@FXML
private TableColumn<Data, String> location_display;
@FXML
private TableColumn<Data, String> museum_display;
@FXML
private TableColumn<Data, String> name_display;
}
finally this is my application that also pulls up the error
java: incompatible types: cannot infer type arguments for javafx.scene.control.cell.PropertyValueFactory<>
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class NookApplication extends Application {
private DBConnect connection;
@Override
public void start(Stage primaryStage) throws Exception {
connection = new DBConnect("com.mysql.jdbc.Driver","jdbc:mysql://localhost:3306/Nookipedia","tsc","");
TableView<Data> dataTable = new TableView<>();
TableColumn<Data, String> museumCol = new TableColumn<>("Musuem");
museumCol.setCellFactory(new PropertyValueFactory<>("MuseumID"));
TableColumn<Data, String> nameCol = new TableColumn<>("Name");
museumCol.setCellFactory(new PropertyValueFactory<>("FishID"));
TableColumn<Data, String> locationCol = new TableColumn<>("Location");
museumCol.setCellFactory(new PropertyValueFactory<>("Location"));
TableColumn<Data, String> dfCol = new TableColumn<>("Date Found");
museumCol.setCellFactory(new PropertyValueFactory<>("DateFound"));
dataTable.getColumns().addAll(museumCol, nameCol, locationCol,dfCol);
dataTable.getItems().addAll(connection.getDataList());
BorderPane root = new BorderPane();
root.setCenter(dataTable);
Scene scene = new Scene(root, 600, 400);
primaryStage.setScene(scene);
primaryStage.show();
/*FXMLLoader fxmlLoader = new FXMLLoader(NookApplication.class.getResource("NookPack.fxml"));
Scene scene = new Scene(fxmlLoader.load(), 320, 240);
stage.setTitle("Nookpedia Backpack");
stage.setScene(scene);
stage.show();*/
}
@Override
public void stop() throws Exception {
if (connection != null){
connection.shutdown();
}
}
public static void main(String[] args){
launch(args);
}
}
I’ve been reading up on all the tableview and database connections enough to know I’m on the right track but everyone seems to make the table within the application .java meanwhile, I’ve created it already in the FXML. Wouldnt it need to be in the controller somehow? and why do I get an error for using PropertyValueFactory? when I know I need it to go into an observable list? My knowledge is a little jumbled together right now.
If you’re going to use
PropertyValueFactory
(which you shouldn’t), then the [string] parameter that you send to thePropertyValueFactory
constructor must match the name of the field (in classData
) and you need to use the same case, e.g.new PropertyValueFactory("museum")
PropertyValueFactory is an anachronism. Just delete everything to do with PropertyValueFactory, forget you ever heard of it, and use lambdas instead. There are other issues with your code and other questions you have but it is best to focus, split your problem apart and ask one question per question.