Display SQL Server data in a JavaFX Tableview - java

I need to display some database values from our db. I have the connection and everything working just fine, just once I set the query to something that actually has data in it, it breaks. It throws multiple NPEs on lines 63 and 65 of main.java, but I have no idea how to debug this because of how complex the line its on is. If anyone could offer some help it would be greatly appreciated.
Line 63:col.setCellValueFactory(new Callback<CellDataFeatures<ObservableList, String>, ObservableValue>() {
Line 65: return new SimpleStringProperty(param.getValue().get(j).toString());
Main.java
import java.sql.Connection;
import java.sql.ResultSet;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
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.stage.WindowEvent;
import javafx.util.Callback;
public class main extends Application {
private ObservableList<ObservableList> data;
private TableView tableview;
public static void main(String[] args) {
launch(args);
}
public void buildData() {
Connection c;
data = FXCollections.observableArrayList();
try {
c = dbConnector.connect();
String SQL = "SELECT dbo.tbHardwareSite.SerialNo, dbo.tbHardwareSite.Hostname, dbo.tbHardwareSite.WinDomain, dbo.tbHardwareSite.Memory, dbo.tbHardwareSite.SwitchRouterConfig, dbo.tbHardwareSite.PurchaseDate, \n" +
" dbo.tbHardwareSite.InstallDate, dbo.tbHardwareSite.Notes, dbo.tbHardwareSite.IDTag AS Expr1, dbo.tbHardwareSite.ExpDate, dbo.tbHardware.HardwareName, dbo.tbHardware.HardwareDesc, dbo.tbHardware.ModelNo, \n" +
" dbo.tbManufacturers.MftrName, dbo.tbCustomers.CustomerID, dbo.tbSites.SiteName\n" +
"FROM dbo.tbHardwareSite INNER JOIN\n" +
" dbo.tbHardware ON dbo.tbHardwareSite.HardwareID_FK = dbo.tbHardware.HardwareID INNER JOIN\n" +
" dbo.tbSites ON dbo.tbHardwareSite.SiteID_FK = dbo.tbSites.SiteID INNER JOIN\n" +
" dbo.tbCustomers ON dbo.tbSites.CustomerID_FK = dbo.tbCustomers.CustomerID INNER JOIN\n" +
" dbo.tbManufacturers ON dbo.tbHardware.ManufacturerID_FK = dbo.tbManufacturers.MftrID INNER JOIN\n" +
" dbo.tbContacts ON dbo.tbSites.LocationContactID_FK = dbo.tbContacts.ContactID\n" +
"WHERE (dbo.tbCustomers.CustomerID = 247)";
ResultSet rs = c.createStatement().executeQuery(SQL);
/**
* ********************************
* TABLE COLUMN ADDED DYNAMICALLY *
*********************************
*/
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<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 + "] ");
}
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));
}
data.add(row);
}
//FINALLY ADDED TO TableView
tableview.setItems(data);
System.out.println(data);
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void start(Stage stage) throws Exception {
//TableView
tableview = new TableView();
buildData();
//Main Scene
Scene scene = new Scene(tableview);
stage.setScene(scene);
stage.setOnCloseRequest(new EventHandler<WindowEvent>() {
#Override
public void handle(WindowEvent event) {
Platform.exit();
System.exit(0);
}
});
stage.show();
}
}
Here is dbConnector.java, which only handles the database connection
public class dbConnector {
private static Connection conn;
private static String url = "jdbc:sqlserver://10.9.32.46:1433;database=TechTracker;integratedSecurity=true";
String driver = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
public static Connection connect() throws SQLException {
try{
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver").newInstance();
}catch(ClassNotFoundException cnfe){
System.err.println("Error: "+cnfe.getMessage());
}catch(InstantiationException ie){
System.err.println("Error: "+ie.getMessage());
}catch(IllegalAccessException iae){
System.err.println("Error: "+iae.getMessage());
}
conn = DriverManager.getConnection(url);
return conn;
}
public static Connection getConnection() throws SQLException, ClassNotFoundException{
if(conn !=null && !conn.isClosed())
return conn;
connect();
return conn;
}
}
I was unable to enter the error log as it was over the character limit. Its a bunch of NullPointerExceptions on line 63 and 65 as I said.

Related

How do i write to a database by taking user input from a GUI and storing that user input into a database in java?

I've recently been trying to write to a Database by taking user input from a GUI and I would like to store that user input from the GUI in a derby database on netbeans. At the moment, I have got some code but it does not seem to be functional as when i run the GUI and start inputting the data that is supposed to be stored in the back end of my program in the database, it does not store that data which is being inputted in the GUI. It does not load any data onto the database!
Here is the code for writing to the Database:
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
*
* #author Hammad
*/
public class WritePlayerDB
{
private final DBConnection dbc;
private final Connection conn;
private Statement stmt;
String insertQuery;
public WritePlayerDB()
{
dbc = new DBConnection();
conn = dbc.getConnection();
}
public void writeToPlayerDB()
{
try {
int playerID = 0;
insertQuery = "INSERT INTO 'PLAYERINFO' ('PLAYER_ID', 'PLAYER_NAME', 'PRIZE_WON', 'CORRECT_ANSWERS')" + "VALUES(1,2,3,4)";
this.stmt = conn.createStatement();
this.checkExistedTable("PLAYERS");
PreparedStatement ps = conn.prepareStatement(insertQuery);
CorrectAnswers.correctAnswers[MillionaireGui.moneyCounter] = PrizeMoney.prizeLadder[MillionaireGui.moneyCounter];
ps.setInt(1, playerID++);
ps.setString(2, MillionaireGui.nameField.getText());
ps.setInt(3, PrizeMoney.prizeLadder[MillionaireGui.moneyCounter]);
ps.setInt(4, CorrectAnswers.correctAnswers[MillionaireGui.moneyCounter]);
ps.executeUpdate();
ps.close();
}
catch (SQLException ex)
{
System.out.println(ex.getMessage());
}
}
public void checkExistedTable(String name)
{
try {
DatabaseMetaData dbmd = this.conn.getMetaData();
String[] types = {"TABLE"};
stmt = this.conn.createStatement();
ResultSet rs = dbmd.getTables(null, null, null, types);
while (rs.next()) {
String table_name = rs.getString("TABLE_NAME");
System.out.println(table_name);
if (table_name.equalsIgnoreCase(name)) {
stmt.executeUpdate("Drop table " + name);
System.out.println("Table " + name + " has been deleted.");
break;
}
}
rs.close();
} catch (SQLException ex) {
System.out.println(ex.getMessage());
}
}
}
and I am calling the writeToPlayerDB() method in the actionListener for my GUI's JTextField as shown below:
nameField.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
if (nameField.getText().equals(""))
{
blankName.setVisible(true);
blankName.setText("PLEASE DON'T LEAVE NAME BLANK");
}
else
{
playerName.setPlayerName(nameField.getText().toUpperCase());
WritePlayerDB wdb = new WritePlayerDB();
wdb.writeToPlayerDB();
blankNamePanel.setVisible(false);
introRuleScreen();
}
}
});
Would appreciate if i could get a hand with this as I have been stuck on it for a long time!
There's not enough information to go by to truely understand what your core problem is, how ever...
static is not a good idea, especially when you're dealing with UI elements, as you might have more then one instance of the UI and then you can no longer determine which instance of the element you're actually referencing. Better to make use of dependency injection and pass the information to the method directly.
+ "VALUES(1,2,3,4)" s not how you use PreparedStatement, see Using Prepared Statements for more details
Also...
int playerID = 0;
//...
ps.setInt(1, playerID++);
means that the player id is ALWAYS 0 (the ++ is a postfix operation; assignment first, addition second). In fact, you should avoid at all costs, manually creating record ids like this and the database should be making use of "auto incrementing" values internally. See Autogenerated keys for more details.
For simplicty, I use the H2 Database Engine for the following example. It should otherwise work with Derby, but you'll want to remove the createTables method
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.StringJoiner;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.JTextField;
import javax.swing.SpinnerNumberModel;
import javax.swing.border.EmptyBorder;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
DatabaseManager db = new DatabaseManager();
db.open();
JFrame frame = new JFrame();
frame.add(new MainPane(db));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (SQLException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
public class MainPane extends JPanel {
private JTextField nameField;
private JSpinner moneyCounter;
public MainPane(DatabaseManager database) {
setBorder(new EmptyBorder(32, 32, 32, 32));
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.anchor = GridBagConstraints.LINE_END;
gbc.insets = new Insets(4, 4, 4, 4);
add(new JLabel("Name: "), gbc);
gbc.gridy++;
add(new JLabel("Counter: "), gbc);
gbc.gridx = 1;
gbc.gridy = 0;
gbc.anchor = GridBagConstraints.LINE_START;
nameField = new JTextField(10);
moneyCounter = new JSpinner(new SpinnerNumberModel(0, 0, 100, 10));
add(nameField, gbc);
gbc.gridy++;
add(moneyCounter, gbc);
JButton btnSave = new JButton("Save");
btnSave.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
String name = nameField.getText();
if (name.isBlank()) {
JOptionPane.showMessageDialog(MainPane.this, "Name can not be blank", "Error", JOptionPane.ERROR_MESSAGE);
return;
}
try {
int playerId = database.savePlayer(name, (int) moneyCounter.getValue());
List<String> results = database.getPlayerById(playerId);
StringJoiner sj = new StringJoiner("<br>", "<html>", "</html>");
for (String text : results) {
sj.add(text);
}
JOptionPane.showMessageDialog(MainPane.this, sj.toString(), "Success", JOptionPane.PLAIN_MESSAGE);
} catch (SQLException ex) {
ex.printStackTrace();
JOptionPane.showMessageDialog(MainPane.this, "Failed to create player record", "Error", JOptionPane.ERROR_MESSAGE);
}
}
});
gbc.gridy++;
gbc.gridx = 0;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.anchor = GridBagConstraints.CENTER;
add(btnSave, gbc);
}
}
public class DatabaseManager {
private Connection connection;
protected void createTables() throws SQLException {
String cmd = "create table IF NOT EXISTS PLAYERINFO ("
+ "PLAYER_ID bigint GENERATED BY DEFAULT AS IDENTITY(START WITH 0) PRIMARY KEY,"
+ "PLAYER_NAME varchar(255) not null,"
+ "PRIZE_WON int not null,"
+ "CORRECT_ANSWERS int not null"
+ ")";
try (Statement stmt = connection.createStatement()) {
stmt.execute(cmd);
}
}
public void open() throws SQLException {
if (connection != null && !connection.isClosed()) {
try {
connection.close();
} catch (SQLException ex) {
Logger.getLogger(Main.class.getName()).log(Level.WARNING, null, ex);
}
}
connection = DriverManager.getConnection("jdbc:h2:~/test");
createTables();
}
public void close() throws SQLException {
if (connection == null) {
return;
}
try {
if (connection.isClosed()) {
connection = null;
}
connection.close();
} finally {
connection = null;
}
}
public int savePlayer(String name, int counter) throws SQLException {
String cmd = "insert into PLAYERINFO (PLAYER_NAME, PRIZE_WON, CORRECT_ANSWERS) values (?, ?, ?)";
try (PreparedStatement stmt = connection.prepareStatement(cmd, Statement.RETURN_GENERATED_KEYS)) {
Random rnd = new Random();
stmt.setString(1, name);
stmt.setInt(2, rnd.nextInt(100) + 1);
stmt.setInt(3, counter);
if (stmt.executeUpdate() != 1) {
throw new SQLException("Unexpectedly modified more then one row");
}
try (ResultSet rs = stmt.getGeneratedKeys()) {
if (rs.next()) {
return rs.getInt(1);
}
}
}
throw new SQLException("Failed to create player record");
}
public List<String> getPlayerById(int id) throws SQLException {
String cmd = "select * from playerinfo where PLAYER_ID = ?";
List<String> results = new ArrayList<>(8);
try (PreparedStatement stmt = connection.prepareStatement(cmd)) {
stmt.setInt(1, id);
try (ResultSet rs = stmt.executeQuery()) {
while (rs.next()) {
String name = rs.getString("PLAYER_NAME");
int prizeWon = rs.getInt("PRIZE_WON");
int correctAnswer = rs.getInt("CORRECT_ANSWERS");
results.add(name + " won " + prizeWon + " with " + correctAnswer + " correct answers");
}
}
}
return results;
}
}
}

How to display Column Headers from a Mysql database in JavaFX TableView?

Let me clarify the question. So I decided to create a TreeView just like in PhpMyAdmin (xampp) that shows all Databases. I successfully managed to get the Databases and Tables in the Treeview, but not the content of the Tables in the TableView. So basically the first thing I want to do is, that if I click on a Table, the column headers should show up in the Table next to the Treeview. I managed to write some code, but it does not do what it is supposed to do. Please help me I am trying to learn this programming language (JavaFX).
This is the Controller class
package sample;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.control.cell.PropertyValueFactory;
import java.net.URL;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ResourceBundle;
public class Controller implements Initializable {
Statement statement;
Statement statementDatabase;
Statement stmntTables;
Statement stmntUse;
Statement stmntCols;
ResultSet resultDatabase;
ResultSet resultTables;
ResultSet resultUse;
ResultSet resultCols;
#FXML
TreeView <String> treeView;
#FXML
TableView<String> tableView;
#Override
public void initialize(URL url, ResourceBundle resourceBundle) {
try {
statement = DatabaseConnection.getInstance().getConnection().createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
ResultSet result = statement.executeQuery("SHOW DATABASES");
TreeItem<String> root = new TreeItem<>("Datenbanken");
while(result.next()) {
TreeItem<String> node = new TreeItem<>(result.getString(1));
root.getChildren().add(node);
Statement statement2 = DatabaseConnection.getInstance().getConnection().createStatement();
ResultSet subResult = statement2.executeQuery("SHOW TABLES FROM " + result.getString(1));
while(subResult.next())
{
TreeItem<String> node2 = new TreeItem<>(subResult.getString(1));
node.getChildren().add(node2);
}
}
result.beforeFirst();
treeView.setRoot(root);
root.setExpanded(true);
ShowDatabase();
UseDatabase();
} catch (Exception e){
e.printStackTrace();
}
}
public void ShowDatabase() {
try {
statementDatabase = DatabaseConnection.getInstance().getConnection().createStatement();
resultDatabase = statementDatabase.executeQuery("SHOW DATABASES");
System.out.println("All Databases displayed!");
} catch (SQLException e) {
System.out.println("Databases could not be displayed!");
e.printStackTrace();
}
}
public void UseDatabase() {
try {
while (resultDatabase.next()) {
stmntUse = DatabaseConnection.getInstance().getConnection().createStatement();
resultUse = stmntUse.executeQuery("USE " + resultDatabase.getString(1));
//System.out.println(resultDatabase.getString(1));
ShowTables();
//System.out.println(resultTables.getString(1));
ShowColumns();
}
System.out.println("Database injected!");
System.out.println("All Tables displayed!");
System.out.println("All Columns displayed!");
} catch (SQLException e) {
System.out.println("Database ejected!");
e.printStackTrace();
}
}
public void ShowTables() {
try {
while (resultDatabase.next()) {
stmntTables = DatabaseConnection.getInstance().getConnection().createStatement();
// System.out.println(resultDatabase);
resultTables = stmntTables.executeQuery("SHOW TABLES FROM " + resultDatabase.getString(1));
// System.out.println(resultTables.getString(1));
}
} catch (SQLException e) {
System.out.println("Tables could not be displayed!");
e.printStackTrace();
}
}
public void ShowColumns() {
try {
while (resultTables.next()) {
stmntCols = DatabaseConnection.getInstance().getConnection().createStatement();
resultCols = stmntCols.executeQuery("SHOW COLUMNS FROM " + resultTables.getString(1));
System.out.println(resultCols);
FillTable(resultCols);
}
} catch (SQLException e) {
System.out.println("Columns could not be displayed!");
e.printStackTrace();
}
}
public void FillTable(ResultSet res) {
TableColumn<String, String>col = new TableColumn<String, String>();
try {
col.setCellValueFactory(new PropertyValueFactory<>(res.getString(1)));
} catch (SQLException e) {
e.printStackTrace();
}
tableView.getColumns().add(col);
}
}
and this is the Database Connection
package sample;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class DatabaseConnection {
private static DatabaseConnection instance;
private Connection connection;
private static String ip = "localhost";
public static void setIp(String ip) {
DatabaseConnection.ip = ip;
}
private DatabaseConnection() throws SQLException
{
try {
Class.forName("com.mysql.cj.jdbc.Driver");
connection = DriverManager.getConnection("jdbc:mysql://" + ip + ":" + 3306, "root", "");
System.out.println("Successfully connected to " + ip + "!");
} catch (Exception exc) {
//exc.printStackTrace();
System.out.println("Connection failed to " + ip + "!");
getConnection().close();
}
}
public Connection getConnection() {
return connection;
}
public static DatabaseConnection getInstance() throws SQLException {
if (instance == null) {
instance = new DatabaseConnection();
} else if (instance.getConnection().isClosed()) {
instance = new DatabaseConnection();
}
return instance;
}
}
Here is some code that should get you going. You will probably need a listener on the TreeView to change the table data and headers as you click on different items in the TreeView. This code simulates getting the headers from the database as List<String> and get the data from the database as List<List<String>>.
import java.util.ArrayList;
import java.util.List;
import javafx.application.Application;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
/**
* JavaFX App
*/
public class App extends Application {
#Override
public void start(Stage primaryStage) {
ObservableList<ObservableList<String>> data = FXCollections.observableArrayList();
final List<List<String>> databaseData = getTableDataFromDBAsListOfList();//Get data from excel file
//Add database data to an observable list
for(int i = 0; i < databaseData.size(); i++)
{
data.add(FXCollections.observableArrayList(databaseData.get(i)));
}
TableView<ObservableList<String>> tableView = new TableView();
tableView.setItems(data);
//Create the table columns, set the cell value factory and add the column to the tableview.
List<String> tableHeaders = getTableHeadersFromDBAsList();
for (int i = 0; i < tableHeaders.size(); i++) {
final int curCol = i;
final TableColumn<ObservableList<String>, String> column = new TableColumn<>(tableHeaders.get(i));
column.setCellValueFactory(param -> new ReadOnlyObjectWrapper<>(param.getValue().get(curCol)));
tableView.getColumns().add(column);
}
StackPane root = new StackPane(tableView);
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch();
}
public List<String> getTableHeadersFromDBAsList()
{
List<String> returnList = new ArrayList();
returnList.add("Header1");
returnList.add("Header2");
returnList.add("Header3");
returnList.add("Header4");
return returnList;
}
public List<List<String>> getTableDataFromDBAsListOfList()
{
List<List<String>> returnList = new ArrayList();
List<String> dataRow1 = new ArrayList();
dataRow1.add("Data 1 1");
dataRow1.add("Data 1 2");
dataRow1.add("Data 1 3");
dataRow1.add("Data 1 4");
List<String> dataRow2 = new ArrayList();
dataRow2.add("Data 2 1");
dataRow2.add("Data 2 2");
dataRow2.add("Data 2 3");
dataRow2.add("Data 2 4");
returnList.add(dataRow1);
returnList.add(dataRow2);
return returnList;
}
}

Display ResultSet of a SQL query in a JTable (Java)

I'm working on a program with which I can search through a database and display the results.
I'm stuck at the displaying part at the moment. My SQL query already works and returns the results. I'm using a PreparedStatement to fill my ResultSet. However I don't know how I can return the data of the ResultSet to a JTable which I want to use to display the data. Can anyone explain to me in detail how to do this or if there is a better way instead of a JTable I'm not seeing?
I'm using the MVC model and the DAO pattern, but I'm still pretty new to programming.
So far from researching it I found the best solution to be to make a custom table class, but from there on I don't know how to progress.
My custom table class:
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.Vector;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
public class ResultSetTable {
public static TableModel resultSetToTableModel(ResultSet rs) {
try {
ResultSetMetaData metaData = rs.getMetaData();
int numberOfColumns = metaData.getColumnCount();
Vector columnNames = new Vector();
//Spaltennamen
for (int column = 0; column < numberOfColumns; column++) {
columnNames.addElement(metaData.getColumnLabel(column + 1));
}
//Alle Zeilen
Vector rows = new Vector();
while (rs.next()) {
Vector newRow = new Vector();
for (int i = 1; i <= numberOfColumns; i++) {
newRow.addElement(rs.getObject(i));
}
rows.addElement(newRow);
}
return new DefaultTableModel(rows, columnNames);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
And the relevant part of my View class:
import java.awt.FlowLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.JTextField;
import dbconnect.dao.impl.BTRDaoImpl;
public class View extends JFrame{
public View() {
JTable table = new JTable(new ResultSetTable(BTRDaoImpl.resultset);
this.setSize(600, 400);
setResizable(false);
}
My BTRDaoImpl class with the sql query and resultset:
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import mvc.View;
import dao.BTRbDao;
import business.BTRBean;
public class BTRDaoImpl extends AbstractDao implements BTRDao {
private Connection dbConnection = null;
private PreparedStatement preparedStatement = null;
public void sqlquery() {
try {
String btrname = View.searchbbtrname.getText();
String btrplz = View.searchbtrplz.getText();
btrname = btrname.trim().toUpperCase();
btrplz = btrplz.trim().toUpperCase();
if (btrplz.isEmpty()) {
String btrResult = "SELECT BBSTBBNR, BBSTNABE, BBSTPLZ FROM BP.TBBBST WHERE BBSTNABEG = ?";
dbConnection = AbstractDao.getConnection();
preparedStatement = dbConnection.prepareStatement(btrResult);
preparedStatement.setString(1, btrname);
} else {
String btrResult = "SELECT BBSTBBNR, BBSTNABE, BBSTPLZ FROM BP.TBBBST WHERE BBSTNABEG = ? AND BBSTPLZ = ?";
dbConnection = AbstractDao.getConnection();
preparedStatement = dbConnection.prepareStatement(btrResult);
preparedStatement.setString(1, btrname);
preparedStatement.setString(2, btrplz);
}
} catch (SQLException e1) {
System.out.println("An error with the SQL query occured: ");
e1.printStackTrace();
}
}
public Collection<BtrBean> getBTR() throws SQLException,
IOException {
sqlquery();
final Collection<BtrBean> result = new ArrayList<BtrBean>();
ResultSet resultset = null;
try {
resultset = preparedStatement.executeQuery();
// while loop to get data
while (resultset.next()) {
BtrBean btr = new BtrBean();
int btrid = resultset.getInt(1);
String btrplz = resultset.getString(3);
String btrname = resultset.getString(2);
btr.setBetriebnr(btrid);
btr.setBetriebplz(btrplz);
btr.setBetriebname(btrname);
result.add(btr);
// System.out.println("BTR-ID: " + btrid + " BTR PLZ: " + btrplz + " BTR: " + btrname);
}
} catch (SQLException e) {
e.printStackTrace();
System.out.println("An error processing the SQL occured: ");
e.printStackTrace();
} catch (NullPointerException npe) {
System.out.println("NullPointerException: ");
npe.printStackTrace();
} finally {
if (preparedStatement != null) preparedStatement.close();
closeConnection(resultset);
}
return result;
}
}
My BTRBean class:
public class BetriebBean {
private String betriebname;
private int betriebnr;
private String betriebplz;
public BetriebBean() {
}
public BetriebBean(String betriebname, int betriebnr, String betriebplz) {
super();
this.betriebname = betriebname;
this.betriebnr = betriebnr;
this.betriebplz = betriebplz;
}
public String getBetriebname() {
return betriebname;
}
public void setBetriebname(String betriebname) {
this.betriebname = betriebname;
}
public int getBetriebnr() {
return betriebnr;
}
public void setBetriebnr(int betriebnr) {
this.betriebnr = betriebnr;
}
public String getBetriebplz() {
return betriebplz;
}
public void setBetriebplz(String betriebplz) {
this.betriebplz = betriebplz;
}
}
//edit:
My whole View.class:
import java.awt.FlowLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.JTextField;
public class View extends JFrame{
private static final long serialVersionUID = 1L;
public static final String SEARCH = "SEARCH";
private JLabel searchbtrlabel = new JLabel("BTR name:");
public static JTextField searchbtrname = new JTextField(10);
private JLabel searchbtrlabel = new JLabel("PLZ:");
public static JTextField searchbtrplz = new JTextField(10);
private JButton searchbutton = new JButton();
public View() {
this.setTitle("BTR search TBBBST");
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setLayout(new FlowLayout());
this.add(searchbtrlabel);
this.add(searchbtrname);
this.add(searchbtrplzlabel);
this.add(searchbtrplz);
searchbutton.setText("Search");
searchbutton.setActionCommand(View.SEARCH);
this.add(searchbutton);
JTable table = new JTable();
this.add(table);
this.setSize(600, 400);
setResizable(false);
//this.pack();
}
public JTextField getSearchbtrname() {
return searchbetriebname;
}
public JTextField getSearchbbtrplz() {
return searchbetriebplz;
}
public JButton getSearchbutton() {
return searchbutton;
}
}
My Controller class:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Observable;
import java.util.Observer;
import mvc.Model;
import dbconnect.dao.impl.BTRDaoImpl;
public class Controller implements Observer, ActionListener{
private Model model;
#SuppressWarnings("unused")
private View view;
public Controller(Model model, View view) {
this.model = model;
this.view = view;
model.addObserver(this);
view.getSearchbutton().addActionListener(this);
view.setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {
switch (e.getActionCommand()) {
case View.SEARCH:
model.search();
view.table.setModel(ResultSetToTable.buildTableModel(BTRDaoImpl.resultset));
break;
default:
System.out.println("Error : " + e.getActionCommand());
break;
}
}
#Override
public void update(Observable o, Object arg) {
// TODO Auto-generated method stub
}
}
Firstly, include rs2xml.jar in your libraries. You can find it here
In whatever action to populate your MySQL query in your JTable use following general idea:
public void sqlquery() {
try {
String btrResult = "SELECT BBSTBBNR, BBSTNABE, BBSTPLZ FROM BP.TBBBST WHERE BBSTNABEG = ?";
preparedStatement = dbConnection.prepareStatement(btrResult);
dbConnection.setString(1, btrname);
ResultSet rs =dbConnection.executeQuery();
Ur_table_name.setModel(DbUtils.resultSetToTableModel(DbUtils.resultSetToel(rs)); //this line of code will show it in your JTable
}catch(Exception e){
}
What is your question? Try being more specific than "[...] but from there on I don't know how to progress." What do you want to do? Are the results from your query visible in the table?
Using the answer from Paul Vargas over here Most simple code to populate JTable from ResultSet, you could start with something like this (using Java 8):
import java.sql.*;
import java.util.Vector;
import javax.swing.*;
import javax.swing.table.*;
public class ResultSetToTable {
public static void main(final String[] arguments) {
SwingUtilities.invokeLater(() -> {
try {
new ResultSetToTable().createAndShowGui();
} catch (SQLException e) {
e.printStackTrace();
}
});
}
private void createAndShowGui() throws SQLException {
final JFrame frame = new JFrame("Stack Overflow");
frame.setBounds(100, 100, 800, 600);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
final JPanel panel = new JPanel();
final TableModel tableModel = buildTableModel(getData("Audi"));
final JTable table = new JTable(tableModel);
panel.add(new JScrollPane(table));
frame.getContentPane().add(panel);
frame.setVisible(true);
}
private ResultSet getData(final String btrName) throws SQLException {
final String url = "jdbc:h2:/Freek/TBBBST";
final Connection connection = DriverManager.getConnection(url, "me", "123");
final String sql = "SELECT BBSTBBNR, BBSTNABE, BBSTPLZ " +
"FROM BP.TBBBST " +
"WHERE BBSTNABEG = ?";
final PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1, btrName);
return preparedStatement.executeQuery();
}
/**
* See https://stackoverflow.com/a/10625471/1694043
*/
public static TableModel buildTableModel(final ResultSet resultSet)
throws SQLException {
int columnCount = resultSet.getMetaData().getColumnCount();
// Column names.
Vector<String> columnNames = new Vector<>();
for (int columnIndex = 1; columnIndex <= columnCount; columnIndex++) {
columnNames.add(resultSet.getMetaData().getColumnName(columnIndex));
}
// Data of the table.
Vector<Vector<Object>> dataVector = new Vector<>();
while (resultSet.next()) {
Vector<Object> rowVector = new Vector<>();
for (int columnIndex = 1; columnIndex <= columnCount; columnIndex++) {
rowVector.add(resultSet.getObject(columnIndex));
}
dataVector.add(rowVector);
}
return new DefaultTableModel(dataVector, columnNames);
}
}
For older versions of Java, you should be able to use this version of the main method:
public static void main(final String[] arguments) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
try {
new ResultSetToTable().createAndShowGui();
} catch (SQLException e) {
e.printStackTrace();
}
}
});
}
Edit: connecting controller and table
To make the table available outside the view, you need to convert the table variable in the View() constructor into a field (like you have done with searchbtrname) and create a getTable getter method for it (like you have done with getSearchbtrname). In the Controller.actionPerformed method you can now change view.table into view.getTable().

How to fill up a TableView with database data

I've been trying to load a TableView with data queried from a database, but can't seem to get it to work.
This is my first attempt at trying to populate a TableView with database query items – in case my code seems mungled and far from good.
The FXML was done via JavaFX SceneBuilder.
This is the database query class:
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
}
}
}
This is the FXML script generated via JavaFX scene builder:
<?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>
Here is the best solution for the filling data to the tableView From the database.
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();
}
}
Here is the Reference
Thanks..
If Database contains different types of data, not only String, then column type assigning is better to make dynamic:
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);
}
}
In this example 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 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;
}

Unexpected type required variable found value

public class example
{
public ArrayList<Integer> ToFill = new ArrayList<>();
public void Alter(int Value , int Position)
{
ToFill.get(Position) = Value ; // this line has an error
}
}
For some reason this code gives compilation Error ,could anyone explain why?
ToFill.get(Position) returns a value where the left-hand side of the assignment must be a variable. Instead, use set(index, element) as follows:
ToFill.set(Position, Value);
However, what you are doing is only valid if you are using arrays, for example:
Integer[] array = ...
array[Position] = Value;
As a side note, always use Java naming convention:
toFill instead of ToFill
alter instead of Alter
position instead of Position.
value instead of Value.
#FXML
private void handleButtonAction(ActionEvent event) {
System.out.println("You clicked me!");
label.setText("Hellow Word!");
if (event.getSource() = btnInsert) { //ERROR
insertRecors();
}
package operator;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.stage.Stage;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.io.IOException;
import java.net.URL;
import java.sql.*;
import java.util.ResourceBundle;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
public class Pyti implements Initializable {
private Label label;
//внести значение
#FXML
private TextField tfId;
#FXML
private TextField tfTitle;
//таблица
#FXML
private TableView<Books> tvBooks;
#FXML
private TableColumn<Books, Integer> colId;
#FXML
private TableColumn<Books, String> colTitle;
///
#FXML
private Button behaind;
#FXML
private Button glavnaia;
///
#FXML
private Button btnInsert;
#FXML
private Button btnUpdate;
#FXML
private Button btnDelete;
#FXML
private void handleButtonAction(ActionEvent event) {
System.out.println("You clicked me!");
label.setText("Hellow Word!");
if (event.getSource() = btnInsert) {
insertRecors();
}
}
#Override
public void initialize(URL url, ResourceBundle rd) {
{
showBooks();
}
glavnaia.setOnAction(event -> {
openNewScene("/vhod.fxml");
});
behaind.setOnAction(event -> {
openNewScene("/operator.fxml");
});
}
private void openNewScene(String window) {
glavnaia.getScene().getWindow().hide();
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource(window));
try {
loader.load();
} catch (IOException e) {
e.printStackTrace();
}
Parent root = loader.getRoot();
Stage stage = new Stage();
stage.setScene(new Scene(root));
stage.show();
}
public Connection getConnection() {
Connection conn;
try {
conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mysor", "root", "12345");
return conn;
} catch (Exception ex) {
System.out.println("Error: " + ex.getMessage());
return null;
}
}
public ObservableList<Books> getBooksList() {
ObservableList<Books> bookList = FXCollections.observableArrayList();
Connection conn = getConnection();
String query = "SELECT * FROM books";
Statement st;
ResultSet rs;
try {
st = conn.createStatement();
rs = st.executeQuery(query);
Books books;
while (rs.next()) {
books = new Books(rs.getInt("id"), rs.getString("title"));
bookList.add(books);
}
} catch (Exception ex) {
ex.printStackTrace();
}
return bookList;
}
public void showBooks() {
ObservableList<Books> list = getBooksList();
colId.setCellValueFactory(new PropertyValueFactory<Books, Integer>("id"));
colTitle.setCellValueFactory(new PropertyValueFactory<Books, String>("title"));
tvBooks.setItems(list);
}
private void insertRecors() throws SQLException {
String query = "INCERT INTO books VALUES (" + tfId.getText() + "," + tfTitle.getText() + ")";
executeQuery(query);
showBooks();
}
private void executeQuery(String query) throws SQLException {
Connection conn = getConnection();
Statement st;
try {
st = conn.createStatement();
st.executeUpdate(query);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}

Categories