What i'm trying do here is that when i select a row in my table , after loading data , it should display the selected row's value in a text field (selectedRowTF). But as soon as i click on the jButton the following error generates -
java.lang.ArrayIndexOutOfBoundsException: -1
Since the error occurs even before the data is loaded , it leaves no chance for me to even select a row.
Also do you think I'm using the correct code to get the row's value?
Stack Trace
DefaultTableModel model;
model=(DefaultTableModel)tbl.getModel();
try {
Class.forName("java.sql.Driver");
Connection con= DriverManager.getConnection("jdbc:mysql://localhost:3306/divign","root","password");
Statement stmt=con.createStatement();
int row=tbl.getSelectedRow();
String rowSelected=(tbl.getModel().getValueAt(row, 0).toString());
String query="SELECT * FROM CUSTOMER WHERE CUSTOMER_ID = '"+customerIdTF.getText()+"' ;";
ResultSet rs=stmt.executeQuery(query);
if(rs.next()) {
model.addRow (new Object[ ] {
rs.getInt(1),rs.getString(2),rs.getString(3)
});
selectedRowTF.setText(""+rowSelected);
}
rs.close();
stmt.close();
con.close();
}
catch(Exception e){
JOptionPane.showMessageDialog(null,e.toString());
}
If you just load your data, the tbl.getSelectedRow() returns -1.
After that you try to get the string value of the first column of your invalid row.
String rowSelected=(tbl.getModel().getValueAt(row, 0).toString());
=> that getValueAt leads to your exception.
Try the following:
String rowSelected = "";
if(row != -1)
{
rowSelected = tbl.getModel().getValueAt(row, 0).toString();
}
EDIT
As you said you just want to get the selected value, the position of your code is wrong.
You are trying to get the value of the selected row at the time you are loading your data. But at that time you don't select a row.
I think you need something like that (Value is printed out on a mouse click at the table):
tbl.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent evt) {
int row = table.getSelectedRow();
if (row > -1) {
String value = (table.getModel().getValueAt(row, 0).toString());
System.out.println("Value of row " + row + " col 0: '" + value + "'");
selectedRowTF.setText(value);
} else {
System.out.println("Invalid selection");
}
}
});
Or you can react on the selection with a button click:
private void btClickActionPerformed(java.awt.event.ActionEvent evt) {
int row = table.getSelectedRow();
if (row > -1) {
String value = (table.getModel().getValueAt(row, 0).toString());
System.out.println("Value of row " + row + " col 0: '" + value + "'");
selectedRowTF.setText(value);
} else {
System.out.println("Invalid selection");
}
}
Your situation is that when you called tbl.getSelectedRow(), it returned -1. That is a sentinel value to indicate that no row is selected. A row is selected when the mouse clicks on it, or when the keyboard moves the selection to it. You will need to handle the situation when no row is selected. I don't know your requirements and goals, so I can't advise on how to do that. You can register a selection listener with the JTable if you want to be notified when the selection changes and react to it. (See getSelectionModel, addListSelectionListener, and ListSelectionListener)
You may get away without handling it if you didn't enable sorting or filtering on your JTable, however it is worth knowing that the row indexes in the view (JTable) are not the same indexes in the model (DefaultTableModel). Use the convertRowIndexToModel method to convert from the view's index (as reported by getSelectedRow()) to the model's index (required by getValueAt()).
The code you posted also contains SQL Injection issues. I recommend researching that topic, and fix it using a PreparedStatement and setString().
Related
In my JTable it displays all the names of people, and then when I type a name or any related info to them, then it will show until only one person is shown in the table. When I click that one row of the table and then click the button delete but it won't delete that specific data instead it deletes the first row in the table "before searching in the table."
This is the output:
Before seaching
When Searching and after hitting the delete button above. That data is not been deleted.
Searching
But instead, it deleted who is in the first row
After
This is the code for the delete that is connected to the button delete.
private void officialsDelete() {
DefaultTableModel RecordTable = (DefaultTableModel)officialTable.getModel();
int SelectedRows = officialTable.getSelectedRow();
try{
if(officialTable.getSelectedRowCount() == 1){
id = Integer.parseInt(RecordTable.getValueAt(SelectedRows, 0).toString());
deleteItem = JOptionPane.showConfirmDialog(null, "Confirm if you want to delete item",
"Warning",JOptionPane.YES_NO_OPTION);
if(deleteItem == JOptionPane.YES_OPTION){
Class.forName("com.mysql.cj.jdbc.Driver");
sqlConn = DriverManager.getConnection(dataConn,username,password);
pst = sqlConn.prepareStatement("delete from officials where id =?");
RecordTable.removeRow(officialTable.getSelectedRow());
pst.setInt(1, id);
pst.executeUpdate();
JOptionPane.showMessageDialog(this,"Recorded Updated");
upDateDBOfficials();
}
}else{
if(officialTable.getRowCount()==0){
JOptionPane.showMessageDialog(this,"Table is Empty!");
}else{
JOptionPane.showMessageDialog(this,"Please select Single row for Deleting");
}
}
}catch(ClassNotFoundException ex){
java.util.logging.Logger.getLogger(InformationSystem.class.getName()).log(java.util.logging.Level.SEVERE,
null, ex);
}catch(SQLException ex){
java.util.logging.Logger.getLogger(InformationSystem.class.getName()).log(java.util.logging.Level.SEVERE,
null, ex);
}
}
And then this is the code for the keyReleased of the textfield for search.
private void officialsSearch() {
String search = officialSearchTxt.getText();
DefaultTableModel model = (DefaultTableModel)officialTable.getModel();
TableRowSorter<DefaultTableModel> sorter = new TableRowSorter<>(model);
officialTable.setRowSorter(sorter);
sorter.setRowFilter(RowFilter.regexFilter("(?i)" + search));
}
My problem in here is need to delete the data in the table when i search in the textfield and it will appear in the JTable and click it to delete it. After clicking it in the table, i will now click the button delete for it to delete.
I hope you can help me.
I am trying to select values from a row in my MySQL table.
SELECT fortnite,psn,steam,twitch,xbox,youtube
FROM `social_media`
WHERE id = '16483378715464928'
When I try to convert the result into a string, the ResultSet only receives the first "fortnite" row. My question is, how do I retrieve the following columns and put them all into one string to return.
Here is my example code:
public static String getSocialMedia(String id) {
String ret = "";
int i = 1;
try {
Statement stmt = null;
ResultSet resultSet = null;
getConnection();
stmt = con.createStatement();
resultSet = stmt.executeQuery("SELECT fortnite,psn,steam,twitch,xbox,youtube FROM `social_media` WHERE id ='" + id + "'");
while(resultSet.next()) {
ret += resultSet.getString(i) + " ";
i++;
}
if(resultSet != null) {
resultSet.close();
}
if(stmt != null) {
stmt.close();
}
} catch (Exception e) {
e.printStackTrace();
}
return ret;
}
This is happening due to this.
while(resultSet.next()) {
ret += resultSet.getString(i) + " ";
i++;
}
In the above code inside while you need to fetch all the values either by name or index. next() function gives you the complete row not a single column.
You should change it to:
while(resultSet.next()) {
for(i = 1, i <=6, i++){
ret += resultSet.getString(i) + " ";
}
}
When i try to convert the result into a string, the ResultSet only
receives the first "fortnite" row. My question is, how do i retrieve
the following columns and put them all into one string to return.
Terminology is important here, because misunderstanding terminology may lead you to misinterpret documentation. In this case, the important terminology distinction is "row" vs. "column".
Your query SELECTs fortnite,psn,steam,twitch,xbox,youtube. Those six identifiers define six columns that each row in your result set will have. It looks like your particular query is selecting by the table's primary key, so you'll only ever have zero or one row, but other queries can return multiple rows.
You want to extract the values of all six columns of one row, but you iterate while(resultSet.next()), and ResultSet.next() moves the result set to the next row, if any, not the next column. Since you have only one row, the loop terminates after only one iteration.
It looks like you want something more like this:
if (resultSet.next()) {
for (i = 1; i <= 6; i++) {
ret += resultSet.getString(i) + " ";
}
}
The if (resultSet.next()) is necessary to move the result set to the first row, and to detect when there isn't any. Then you iterate over the columns of the result, whose number you know statically, based on the query.
So in application I've created a search for name page where the user will enter there the name and as the user types ( Every time a key is pressed) an SQL statement is ran that will get the records like 'name%'.
This works fine but when it comes to putting the values into the table everytime the user presses a key it append the found results to the table instead of replace the values. Meaning everytime a key is pressed...duplicate rows are generated.
So I was wondering if anyone had a solution to stop the rows being duplicated and instead replaced with the new values? Im using a default table model:
private DefaultTableModel tModel = new DefaultTableModel(0, 0);
My code:
#Override
public void keyReleased(KeyEvent e) {
updateTable();
table.setModel(tModel);
formPanel.add(table);
tModel.fireTableDataChanged();
}
public void updateTable(){
System.out.println("Save member 1");
try{
//CHANGE THE VALUES SO WHEN CLICKS SAVE MEM
/*-------------------------------------*/
//Connection + Statement
conDB = getConnection();
stmt = conDB.createStatement();
String searchSql = "select * from members where name "
+ " LIKE '" + txtName.getText() +"%'";
if(!txtName.getText().equals(""))
{
r = stmt.executeQuery(searchSql);
}
System.out.println("searching");
tModel.setColumnIdentifiers(columnNames);
while(r.next()){
tModel.addRow(new Object[] {
r.getString("name")
});
}
}
catch(SQLException er){
System.out.println("Error was: " + er);
}
}
public searchBoth(){
super("Search");
this.setBounds(400, 500, 854,400);
this.setVisible(true);
mainCon.add(formPanel);
formPanel.add(lblName);
formPanel.add(txtName);
txtName.addActionListener(this);
addKeyListener(this);
txtName.addKeyListener(this);
}
set rowCount to 0 and add rows .this will remove existing rows and add new rows
tModel.setRowCount(0);
code
System.out.println("searching");
tModel.setRowCount(0);// *********************remove current rows to replace
tModel.setColumnIdentifiers(columnNames);
while(r.next()){
tModel.addRow(new Object[] {
r.getString("name")
});
}
Here is a try block which serves the purpose of filtering through table_job to find rows which match keyword. However, when the table model changes, I am struggling to obtain the correct row index. It always picks the the first row, even though the filtered result shows a row which is not first.
I understand you can do something with fireTableDataChanged(), but I am not sure HOW and WHERE to do this, in the try and catch block OR in the setLabelText() method which displays the content of the table as . JLabel
try
{
sql = "SELECT Job.jobID as 'Job ID', Employer.name as'Company', Job.title as 'Role', Job.description as 'Description', Job.type as 'Type', Job.benefits as 'Benefits', Job.closing as 'Closing Date' FROM Job INNER JOIN Employer ON Job.employerID=Employer.employerID ORDER BY Employer.name";
pst = conn.prepareStatement(sql);
rs = pst.executeQuery();
TableModel model = DbUtils.resultSetToTableModel(rs);
table_job.setModel(model);
final TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(model);
table_job.setRowSorter(sorter);
searchJob.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
String text = keyword.getText();
if (text.length() == 0)
{
sorter.setRowFilter(null);
}
else
{
sorter.setRowFilter(RowFilter.regexFilter(text));
}
}
});
}
catch (Exception e)
{
e.printStackTrace();
}
private void setLabelText()
{
try
{
String table_click0 = (table_job.getModel().getValueAt(
row, 0).toString());
String sqlSt = "SELECT Employer.name, * FROM Job INNER JOIN Employer ON Job.employerID = Employer.employerID WHERE jobID='"+table_click0+"' ";
//rest of code to Label text...
}
The String table_click0 = (table_job.getModel().getValueAt(row, 0).toString()); is picking up the wrong row, not the updated selected row. How can I take this into account?
You probably need to convert your "row" value to a model index value (if your row value is retrieved from a "view" point of view), using convertRowIndexToModel. So just replace
String table_click0 = (table_job.getModel().getValueAt(row, 0).toString());
with
String table_click0 = table_job.getModel().getValueAt(table_job.
convertRowIndexToModel(row), 0).toString());
Quick fix: how to get the actual row in a filtered list
int row=getjTable().getSelectedRow();
if (getjTable().getRowSorter()!=null) {
row = getjTable().getRowSorter().convertRowIndexToModel(row);
}
I'm creating a bank application where I can use the search text field to find customers in the database(I'm using MySQL database). When I type in a letter to search a customer by its last name, the application does fetches the data from the database and shows the results in a JList. In my case, I have a total of 5 records in my database, which 4 last names starts with the letter "S" and one starts with the letter "M". Once the rows or results are in the JList, I can click on one row and automatically fills the first name, last name, city, and etc text filds with the proper information. However, there are two issues that I'm having:
In my case, if I search a last name by the letter "S," my JList will show only 4 records from the database, which is correct. When I select one row from the JList, it should automatically fills all the text fields with the proper information. However, if I select the first row in the JList, my text fields will always fill with the information with the last row in the JList. It doesn't matter which row I select in the JList, the text fields will alway fills the information with the last row.
If I search the letter "S", I get 4 records, which is correct. However, when the application is still running, and I decided to search the letter "M," I get one record, which is also correct, but if I try to search the letter "S" again, I get only one record. Why? It should be 4.
This what I'm trying to accomplish:
Bank Application link
Here is part of my code:
// function that will search for records in the database
private void searchRecord(){
try {
connect = DriverManager.getConnection(url,user,password);
SQLStatement = connect.createStatement();
Class.forName("com.mysql.jdbc.Driver");
model.clear();
String select = "SELECT * FROM customerinfo WHERE LastName LIKE '"+ txtSearch.getText().trim() +"%'";
rows = SQLStatement.executeQuery(select);
while(rows.next()){
//model.addElement(rows.getString("LastName"));
model.addElement(rows.getString("LastName") + ", " + rows.getString("FirstName") + " " + rows.getString("MiddleInitial") + ".");
}
rows.close();
SQLStatement.close();
connect.close();
} catch (ClassNotFoundException e) {
JOptionPane.showMessageDialog(this, "Where is your Mysql JDBC Driver?");
e.printStackTrace();
} catch (SQLException e){
JOptionPane.showMessageDialog(this, "SQLException: " + e.getMessage());
JOptionPane.showMessageDialog(this, "VendorError: " + e.getErrorCode());
}
}
// Implement Action Listener
private class handler implements ActionListener{
#Override
public void actionPerformed(ActionEvent event) {
// if user clicks on New Customer Button, do the following...
if(event.getSource() == newCustomer){
checkForEmptyFields();
insertDatabase();
clearFields();
} else if(event.getSource() == update){
checkForEmptyFields();
updateDatabase();
clearFields();
} else if(event.getSource() == remove){
checkForEmptyFields();
deleteRecord();
clearFields();
} else if(event.getSource() == cancel){
clearFields();
} else if(event.getSource() == open){
} else if(event.getSource() == search){
searchRecord();
}
}
}
// function that will set the text fields
private void setTextFields(int customerID, String firstName, String lastName, String middleInitial, String street, String city, String state, int zipCode, int phone, String email){
String convertCustomerID = Integer.toString(customerID);
txtCustomerID.setText(convertCustomerID);
txtFirstName.setText(firstName);
txtLastName.setText(lastName);
txtMiddleInitial.setText(middleInitial);
txtStreet.setText(street);
txtCity.setText(city);
txtState.setText(state);
String convertZipCode = Integer.toString(zipCode);
txtZip.setText(convertZipCode);
String convertPhone = Integer.toString(phone);
txtPhone.setText(convertPhone);
txtEmail.setText(email);
}
// Implement List Selection Listener
private class listener implements ListSelectionListener{
#Override
public void valueChanged(ListSelectionEvent event) {
try {
connect = DriverManager.getConnection(url,user,password);
SQLStatement = connect.createStatement();
String select = "SELECT * FROM customerinfo WHERE LastName LIKE '"+ txtSearch.getText().trim() + "%'";
rows = SQLStatement.executeQuery(select);
if(!event.getValueIsAdjusting()){
while(rows.next()){
setTextFields(rows.getInt("CustomerID"), rows.getString("FirstName"), rows.getString("LastName"), rows.getString("MiddleInitial"),
rows.getString("Street"), rows.getString("City"), rows.getString("State"), rows.getInt("ZipCode"), rows.getInt("Phone"),
rows.getString("Email"));
}
}
} catch(Exception ex) {
JOptionPane.showMessageDialog(null, "Cannot get field values");
}
}
}
It has to be the rows.next() that's giving me issue number 1. The rows.next() goes through all the records in the database, and after it is done going through all the records, it seems it stays at the last record. Somehow, I need to reset the position, and when I click on a row in the JList, it should be equal to the row that has the same values and fill all the text fields with the proper information.
I have tried everything, and at this point I have given up! Please help me! Thank you!
Your SELECT statement in the valueChanged method is going to select everything again. You will need to make it select only the record that you want. So you will need to have a means to identify the row you want in your list (like customer number or something) and then use that in the SELECT statement when responding to the selection event to get only the single customer.