I am having some trouble in returning the NEXT record within the database, my code currently only returns the last record entered. I have tried creating an instance of a List/ArrayList, tried adding statements to my createStatement(); and just tried everything. I've searched the web, however, I always seem to get the last value returned. I was hoping as to whether someone could help me out. I am using .Swing and this is all executed within an ActionListener.
Essentially I want this function to get the next record in the database. As opposed to returning the last record.
nextEmployee.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Connection connection = null;
Statement statement = null;
try {
Class.forName("org.sqlite.JDBC");
connection = DriverManager.getConnection("jdbc:sqlite:employeeDatabase.sqlite");
connection.setAutoCommit(false);
System.out.println("Read operation - database successfully opened");
statement = connection.createStatement(ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_READ_ONLY);
ResultSet resultset = statement.executeQuery( "SELECT * from employees" );
while (resultset.next()) {
ArrayList<Employee> selectAllEmployees = new ArrayList<Employee>();
String id = resultset.getString("id");
String name = resultset.getString("name");
String email = resultset.getString("email");
String gender = resultset.getString("gender");
String dob = resultset.getString("dob");
String Address = resultset.getString("address");
String Postcode = resultset.getString("Postcode");
String NIN = resultset.getString("NIN");
String JobTitle = resultset.getString("JobTitle");
String StartDate = resultset.getString("StartDate");
String Salary = resultset.getString("Salary");
idTextField.setText(id);
nameTextField.setText(name);
genderTextField.setText(gender);
dobTextField.setText(dob);
addressTextField.setText(Address);
postcodeTextField.setText(Postcode);
ninTextField.setText(NIN);
jobtitleTextField.setText(JobTitle);
startdateTextField.setText(StartDate);
salaryTextField.setText(Salary);
emailTextField.setText(email);
}
resultset.close();
statement.close();
connection.close();
} catch ( Exception e1 ) {
System.err.println( e1.getClass().getName() + ": " + e1.getMessage() );
System.exit(0);
}
}});
Thank you for your time and effort.
One of two things is happening. Either:
You have a bug in the code which populates the database, so you think you have rows A, B, and C in the database, but in fact you only have row C
Or:
Your code as listed populates your controls with the contents of row A, then it repeats to populate the exact same controls with contents of row B, and then the exact same controls once more with the contents of row C. So, naturally, the values you are left with are the values of the last row.
It helps to think precisely what it is that you are trying to do, precisely what is happening, precisely what you expected to happen instead, and most importantly, what makes you believe that the code should do that which you expect it to do rather than what it actually does.
Related
I created a system in which I can run all my postgre sql queries with only one single Async Task Class in Android Studio. This was really(!!) challenging due to the big amount of limitations that I had to face. But this works actually really great!
//Used for connecting to database and executing queries.
//Index 0 of input string must be the query, Index 1 must be the tablename we demand
//We can only gather data from 1 table for each query, so if you need data from several tablecolumns, use multiple queries like:
//[0] = query, [1] = tablename, [2] = 2nd query, [3] = 2nd tablename, [4] = 3rd query, [5] = 3rd table name ... and so on (each query must come with a tablename)
public class DBHandler extends AsyncTask<String, Void, List<String>>
{
public AsyncResponse delegate;
#Override
protected List<String> doInBackground(String...query)
{
List<String> result = new ArrayList<String>();
String sql;
String tableresult = null;
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try {
Class.forName("org.postgresql.Driver");
conn = DriverManager.getConnection("jdbc:postgresql://192.168.200.300:5439/dbname?user=anonymous&password=secretpw");
st = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE); //necessary if you want to use rs.first() after rs.next(), it makes the resultset scrollable
for (int i = 0; i <= query.length-1; i = i+2) //queries are always stored in i=0 and/or in i+2, because i+1 contain the demanded tablenames for resultset handling
{
System.out.println("I is: " +i);
if (!query[i].isEmpty())
{
System.out.println(query[i]);
sql = query[i];
rs = st.executeQuery(sql);
while (rs.next())
if (!query[i + 1].isEmpty() || !rs.getString(query[i + 1]).isEmpty()) //if i+1 is empty, there is no demanded tablename. Used when we dont need any return values (ie. INSERT, UPDATE)
result.add(rs.getString(query[i + 1])); //demanded tablename is always stored in i+1
//We add an empty entry if we demand multiple tablenames so we can keep them seperate
//Might be replaced with any other char, but you will have to backtrack all usages of DBHandler and fix the filters there
if(i+2 < query.length)
result.add(" ");
}
rs.first(); //reset pointer for rs.next()
}
rs.close();
st.close();
conn.close();
System.out.println("End of AsyncTask");
}
catch (SQLException ex)
{
ex.printStackTrace();
}
catch (Exception e)
{
e.printStackTrace();
}
return result;
}
//onPostExecute returns query result in a List.
//We need to use interaces delegate feature to send the result to other classes, like "Auslieferung", which is implementing the interface
#Override
protected void onPostExecute(List<String> result)
{
super.onPostExecute(result);
System.out.println("Result: " +result.toString());
if (!result.isEmpty())
delegate.processFinish(result);
}
}
There is a for-loop in this Async Task.
for (int i = 0; i <= query.length-1; i = i+2)
And now finally I can explain my issue:
I usually use SELECT queries, sometimes I use an INSERT query (which can be done by a single query), but when I parse an Update Query, my for-loop stops iterating after the first pass, so i+2 never happens. The update queries look like this:
String updatequeries[] = {UPDATE delivery SET contactperson = 'Jon Doe' WHERE officeid = 5, " ", UPDATE delivery SET contactemail = 'abd#def.gh' WHERE officeid = 5, " "};
Why does this for loop stop running right after the first run? The debugger does not show anything unusual, everything was parsed right and there are no queries missing. Updating a table does not return any results, but nothing depends on result values here. I tried to run 20 update queries in a single string var, but the for loop stops after the first iteration anyway. No issues are displayed in the debugger or in the logs. Have I overseen something or is there anything I don't know? Might this be a bug? Please help me! This issue drives me crazy.
Hello! I am creating an app for students database. Recently I got a problem when I want to change data that is related to the specific student. Especially problems occur when I want to change the picture for the specific student. I need to check if the picture belongs to the student or not. I store my pictures to the folder if I change the picture, I delete previous one and create a new one. My question about how to check if a picture belongs to the specific student?
I check students in this way.
// get the name of the student from first table getValueTableName
// get the name of the picture from first table getValueTablePicture
getValueTableName = jTable1.getModel()
.getValueAt(jTable1.getSelectedRow(), 0).toString();
getValueTablePicture = jTable1.getModel()
.getValueAt(jTable1.getSelectedRow(), 3).toString();
File sourceFile = new File(getValueTablePicture);
setPicture = sourceFile.getName();
// GET NAME OF THE STUDENT AND THE PICTURE FROM DATABASE AND COMPARE
// THEM TO THE CURRENT USER
try {
CallableStatement statement = null;
Connection data = getmyConnection();
statement = data.prepareCall("{call editStudentByName}");
myResults = statement.executeQuery();
while (myResults.next()) {
// COPY PATH IN getEditName
getEditName = myResults.getString("Name");
// COPY PATH IN getEditPicture
getEditPicture = myResults.getString("Picture");
// add students from database to array
// mylist.add(getEditName.concat(getEditPicture));
mylist.add("\n");
}
myResults.close();
} catch (Exception c) {
c.printStackTrace();
}
// I don't know how to move from this point when I check names with loop
// I check the student with the loop
for (String person : mylist) {
if (getValueTableName.concat(sourceFile.getName()).equals(person) == true) {
}
System.out.print(getValueTableName.concat(sourceFile.getName())
.equals(person));
errors.append(
"- Please choose another picture or rename it!\n Picture ")
.append(getEditPicture)
.append(" is exist for a student " + getEditName)
.append("\n");
jTextField3.requestFocusInWindow();
jTextField3.setText("");
}
The very first thing I'd do is not using separate Strings with strange names like getEditName - this is confusing. Consider having POJO (Student.class) and working with that
So you want to replace single student picture? Why do you have to iterate some array in this case? You should get single student from database (by Id or via some unique set of attributes).
Ok, lets say you have a list of students and you iterate over it. But you still have to change picture for single person so that there is no need to check.
Simply do
String pictureFileName = person.getPicture();//assming getPicture() method returns current picture path
and then save new picture with the same name. In this case old picture will be overwritten so that no issue with checks.
UPD:
If you want to check for picture existence you can do the same:
String pictureFileName = person.getPicture();
File f = new File(pictureFileName );
if(f.exists() && !f.isDirectory()) {
// do something, say report warning
}
UPD:
If you don't require an ability for students to share same file as a picture it's better to implement this at DB level as well via this https://www.w3schools.com/sql/sql_unique.asp - so that you simply won't be able to write two different student records with the same picture path field. In this case checks won't matter anymore and you can simply overwrite the picture file because it belongs to single student only
Finally, I got my things done. It was a very painful moment, but I got what I wanted. The problem was hidden in a column "Picture" in the table "Student" of my database. First, I add UNIQUE constraint ensures to my column that all values in a column are different. Second, I created two stored procedures:
CREATE DEFINER=`root`#`localhost` PROCEDURE `checkStudentByPicture`(
in picture_name varchar(100)
)
BEGIN
SELECT COUNT(*) FROM students_center.Student st WHERE st.Picture = picture_name;
END
The first procedure checks if my column has unique names and doesn't allow to add the same name to the column.
And I created a second one:
CREATE DEFINER=`root`#`localhost` PROCEDURE `getStudentNameByPicture`(
in name varchar(45),
in pic_name varchar(100)
)
BEGIN
SELECT COUNT(*) FROM students_center.Student st WHERE st.Name = name and st.Picture=pic_name;
END
The second procedure checks if the column "Picture" is related to the column "Name". If the column "Picture" is not related, the user doesn't allow to change the name.
Here is the code about checking if my data related to context:
private boolean validateFieldEditStudent() {
StringBuilder errors = new StringBuilder();
// call stored procedure checkStudentByPicture
File sourceFile = new File(jTextField3.getText());
String checkStudentName=jTable2.getValueAt(jTable2.getSelectedRow(), 0).toString();
try {
CallableStatement statement = null;
Connection data = getmyConnection();
statement = data.prepareCall("{call checkStudentByPicture(?)}");
statement.setString(1, sourceFile.getName());
myResults = statement.executeQuery();
while (myResults.next()) {
//COPY PATH IN pictureName
getPictureCount = myResults.getInt(1);
}
myResults.close();
} catch (Exception c) {
c.printStackTrace();
}
}
// call stored procedure checkStudentByPicture
try {
CallableStatement statement = null;
Connection data = getmyConnection();
statement = data.prepareCall("{call getStudentNameByPicture(?, ?)}");
statement.setString(1, checkStudentName);
statement.setString(2, sourceFile.getName());
myResults = statement.executeQuery();
while (myResults.next()) {
//COPY PATH IN pictureName
getStudentNameCount = myResults.getInt(1);
}
myResults.close();
} catch (Exception c) {
c.printStackTrace();
}
//check if data is related to the specific user
if(getFileChooserCount > 0) {
if(getStudentNameCount != 1) {
if(getPictureCount == 1) {
errors.append("- Picture "+sourceFile.getName()+" existed in the database!\n");
jTextField3.setText("");
jTextField3.requestFocusInWindow();
}
}
}
if (errors.length() > 0) {
JOptionPane.showMessageDialog(EditStudent, errors, "Warning!", JOptionPane.ERROR_MESSAGE);
return false;
}
return true;
}
I'm getting this error:
java.sql.SQLException: ResultSet not open. Operation 'next' not
permitted. Verify that autocommit is off.
when I'm trying to create instances from a db.
Current code:
try
{
connection.setAutoCommit(false);
stmt = connection.createStatement();
results = stmt.executeQuery("SELECT * from animalTable");
int AnimalCat = -1;
System.out.print(connection.getAutoCommit());
//getting error on line below
while(results.next())
{
int ID = results.getInt(1);
int Age = results.getInt(2);
String Name = results.getString(3);
String AType = results.getString(4);
String Breed = results.getString(5);
AnimalCat = results.getInt(6);
int Adoption = results.getInt(7);
String Gender = results.getString(8);
String Description = results.getString(9);
if(Gender == "Male"){
gen = true;
}
animal = new Animal(Age, AType, gen, Breed, Description, Name);
animalList.add(animal);
if(AnimalCat != -1){
ResultSet resultCat = stmt.executeQuery("SELECT * from CategoryTable where ID = " + AnimalCat);
//without this line below i get a cursor error
resultCat.next();
System.out.println(resultCat.getInt(1) +"\n\n " + resultCat.getString(2));
String Category = resultCat.getString(2);
if(Category == "Lost"){
Date input = resultCat.getDate(3);
LocalDate date = input.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
ResultSet personData = stmt.executeQuery("SELECT * from PersonTable where ID = " + resultCat.getInt(4));
Person person = new Person(personData.getString(2), personData.getString(3), personData.getString(4), personData.getString(5));
Category lost = new Lost(date, resultCat.getString(5), person);
animal.setAnimalCat(lost);
personList.add(person);
}
}
}
results.close();
stmt.close();
}
catch (SQLException sqlExcept)
{
sqlExcept.printStackTrace();
}
I have tried turning off auto commit like it says in the exception and also adding a finally block and closing the statement. From what I can see online that fixed others issues but no luck with mine.
I know the resultCat.next(); is behind the error somehow but I get an "Invalid cursor state - no current row" without it
You have a Statement, obtain a ResultSet from the statement, then obtain another ResultSet. This automatically closes the first ResultSet:
By default, only one ResultSet object per Statement object can be open
at the same time. Therefore, if the reading of one ResultSet object is
interleaved with the reading of another, each must have been generated
by different Statement objects. All execution methods in the Statement
interface implicitly close a statment's current ResultSet object if an
open one exists.
So when you call next on the first ResultSet an exception is raised. The Javadoc also tells you what to change: Create a second statement and use that to obtain the second ResultSet.
i have been trying a lot of syntax but i can't figured it out.
I want to display "Invoice number" from my databases to the text field (The field "invoice" from table "transaksi" is already filled with number) But it won't show anything. Here's my code :
private void InvoiceActionPerformed(java.awt.event.ActionEvent evt) {
ResultSet aa = null;
try {
koneksi objKoneksi = new koneksi();
Connection kon = objKoneksi.bukaKoneksi();
Statement stat = kon.createStatement();
String query ="select invoice from transaksii";
String res = aa.getString(query);
Invoice.setText(res);
}
catch (SQLException e) {}
}
Note : - Invoice is Former JTextField1.
- transaksii = name of my table.
- invoice = name of the field.
Thank you. English is not my native language.
You did not execute the query. The value of aa is null and you might be getting a NullPointerException.
String query ="select invoice from transaksii";
aa=stat.executeQuery(query);
if(aa.next())
String res = aa.getString("invoice");
Note: Its not a good practice to have an empty catch because you would then end up without knowing about the exception like now. You should do e.printStackTrace(); in catch block.
There is only 1 problem in your original code. The result set that has returned in the line aa = stat.executeQuery(query); is presently at the a position before the 1st result returned. So When you call aa.getString it is not going to return any thing as it is before the 1st result. Also the ResultSet.getString takes a parameter of int or a parameter of String representing the column name. But in your case you have passed the query as the parameter.
So the corrected code should be if you only want to return the 1st item of the ResultSet would be :
private void InvoiceActionPerformed(java.awt.event.ActionEvent evt) {
ResultSet aa = null;
try {
koneksi objKoneksi = new koneksi();
Connection kon = objKoneksi.bukaKoneksi();
Statement stat = kon.createStatement();
String query ="select invoice from transaksii";
aa = stat.executeQuery(query);
String res = "";
if(aa.next()){ // checks and moves it to 1st position
res = aa.getString("invoice"); //column name of the column
}
Invoice.setText(res);
}catch(SQLException e){
e.printStackTrace();
}finally{
//The closing of connection, statement and resultset.
}
}
I have Java code the successfully connects Java to MySQL.
I have two classes. One that creates the GUI with Java and another class that specifically gets information from MySQL.
I'm trying to find a good way to put a whole row of information as a String into each JLabel on MyGUI.
Here is my code in each class (excluding connecting to the database):
CLASS 1
String result = "";
contactsList()
{
//extra classes
db=new database();
result = db.getContact();
label1 =new JLabel(result);
CLASS 2
PreparedStatement pst, pst2;
ResultSet rs, rs2;
pst2 = con.prepareStatement("select LastName, FirstName from contacts");
public String getContact()
{
String result2 = "";
try {
rs2=pst2.executeQuery();
while (rs2.next())
{
result2 = rs2.getString(1);
}
return result2;
}
catch (Exception e) {
// TODO Auto-generated catch block
System.out.println("error while validating"+e);
return "";
}
}
Right now the rows in my Contacts table in MySQL has columns separated by commas
1, Rivera, Angelo, 2890 something st. ventura 93003, Null
2, Person, Random, 1223 I dunno ave. Camairllo 93001, 423-123-5313
Right now when I try to put a whole row in the "label1" the only text it shows is "Person".
How do I make it so it shows the whole Row in the JLabel?
Also how would I format the code so I can call the the function to get the next row of information and put it into another label?
Thanks.
You are only asking it to retrieve one column from your result set by the looks of things :
result2 = rs2.getString(1);
If you want to display more data, you just need to retrieve it and format it somehow :
result2 = rs2.getString(1) + " : " + rs2.getString(2);
for example.
But there are other problems with the select statement I think.
select LastName, FirstName from contacts
will retrieve the LastName and FirstName from every row in the database. The way your loop construct works means that result2 will contain the data for the last row in the table only. Is that what you are trying to achieve?
I would suggest using a JTable for this. Read the section from the Swing tutorial on How to use JTable for more information.
Then you might want to check out Table From Database. The Table From Database Example code may be the easiest way to start.