JDBC and MySQL Statement and ResultSet error - java

I am trying to run the following code:
Scanner input = new Scanner(System.in);
ResultSet rs = null;
System.out.print("Username: ");
String username = input.next();
System.out.print("\nPassword: ");
String pword = input.next();
String stmt = "SELECT * FROM accounts WHERE username = '"+username+"' AND password = '"+pword+"' ";
Statement s = con.createStatement(); // con = Connection object
rs = s.executeQuery(stmt);
if(rs.absolute(1)) {
System.out.println("LOGIN SUCCESSFUL");
}
else {
System.out.println("INVALID LOGIN");
}
However, I end up with the following error:
java.sql.SQLException: Operation not allowed for a result set of type ResultSet.TYPE_FORWARD_ONLY.
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:129)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97)
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
at com.mysql.cj.jdbc.result.ResultSetImpl.absolute(ResultSetImpl.java:391)
at practice.JDBCtester.login(JDBCtester.java:36)
at practice.JDBCtester.main(JDBCtester.java:17)
Could someone explain the problem with my code?

Instead of using absolute() you can just verify at least one row was returned. For example you can do:
rs = s.executeQuery(stmt);
if (rs.next()) {
System.out.println("LOGIN SUCCESSFUL");
}
else {
System.out.println("INVALID LOGIN");
}
absolute() is an advanced method useful for reading, re-reading, and updating special types of result sets. Your result set is a simple one.

As documented in the ResultSet.absolute(int):
Throws:
  SQLException - if a database access error occurs; this method is called on a closed result set or the result set type is TYPE_FORWARD_ONLY
In most situations, the default result set type is TYPE_FORWARD_ONLY, so the absolute method is not supported.
Instead use ResultSet.next() to check if there is at least one row.
As I also commented, your current code is highly insecure. Don't concatenate values into a query string (especially not values obtained from a user), as this makes your code vulnerable to SQL injection. Instead use a prepared statement with parameter placeholders. Also don't store plaintext passwords, but use an appropriate password hashing algorithm.

Related

JDBC login that asks user to re-enter username and password if not found in database

So I am trying to practice working with databases and I decided to make a Banking System. I am using MariaDB. I wanted to make it so the user can login and if the info doesnt match anything in the database, they have to re-enter the username and password until it matches but I cannot figure it out. This is my first time implementing sql into java so I apologize if i made any mistakes. I have researched, but the solutions I could find were using swing or javafx but i am not looking to make a gui right now. Anyway, I am not really sure what I am doing in this part.
public void loginAccount(Connection conn) throws SQLException {
String login;
ResultSet rs;
do {
System.out.print("Enter Username: ");
Username = in.nextLine();
System.out.print("Enter Password: ");
Password = in.nextLine();
login = "SELECT * FROM Person WHERE Username = ? AND AccPassword = ?";
PreparedStatement ps = conn.prepareStatement(login);
ps.setString(1, Username);
ps.setString(2, Password);
rs = ps.executeQuery(login);
} while (!rs.next());
}
I keep getting java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '? AND AccPassword = ?' at line 1
Also, I originally had
login = "SELECT * FROM Person WHERE Username = " +Username+ " AND AccPassword = " + Password;
But i read somewhere that it is bad practice to use +. Not sure if that is true or not.
You intended to call PreparedStatement.executeQuery()
rs = ps.executeQuery();
but instead you called a static method Statement.executeQuery(String sql)
rs = ps.executeQuery(login);
You are using the wrong method of PreparedStatement.
You should use
rs = ps.executeQuery();
so that your statement gets executed where the placeholders actually have values.

Getting "java.sql.SQLException: Values not bound to statement" exception

I was trying to make a program which consists of connecting an user by a login system with SQL, then if the credentials are good the user is redirected to an another frame.
But I had a problem, I want to have some information in the SQL base, so I have tried to use while loop and it was working, but after I encountered an error :
java.sql.SQLException: Values not bound to statement
See the following code :
String pseudo2 = null;
String rank2 = null;
try {
String searchname2 = "select * from AdminsInfos where pseudo=?";
PreparedStatement name2 = connection.prepareStatement(searchname2);
ResultSet rspseudo2 = name2.executeQuery();;
while (rspseudo2.next())
{
pseudo2 = rspseudo2.getString("Pseudo");
rank2 = rspseudo2.getString("Rank");
}
} catch (Exception e2) {
e2.printStackTrace();
}
JOptionPane.showMessageDialog(null, "Username and password are correct, connection Admin !");
frame.setVisible(false);
new LoginMain().setVisible(true);
LoginMain.usernameField.setText(pseudo2);
LoginMain.ranklabel.setText("Rank : " + rank2);
and you can check the SQL base too by the following picture :
sql base
Can someone help me?
Since you have a bound variable you need to set the value before executing the statement.
for example , if psuedo is of type String then you will be doing something like below.
String searchname2 = "select * from AdminsInfos where pseudo=?";
PreparedStatement name2 = connection.prepareStatement(searchname2);
name2.setString(1,"value");
ResultSet rspseudo2 = name2.executeQuery();
where first parameter in the setString means you want to set the first value for the bound variable.

How to execute MySQL query, "show tables;" inside a Java Program..?

I am a newbie to Java and MySQL. Please pardon me if my question seems silly, I want to know the answer...
I have gone through many articles and questions asked in forums, but I didn't see a relevant answer for my question...
That is, I have made a switch statement in Java and I want to show the list of available tables in a database if I press 1( that is go into the case 1 and execute a query "show tables;" )
In MySQL Console, it is easy to check for available tables using the same query. But I want to know whether "show tables;" query or similar queries can be executed inside a Java Program...
Here's a sample snippet of my code,
Connection con=null;
String url = "jdbc:mysql://localhost:3306/giftson";
String dbName = "giftson";
String userName = "root";
String password = "password";
con=DriverManager.getConnection(url,userName,password);
Statement st=con.createStatement();
//String query;
Statement st=con.createStatement();
System.out.println("\tDatabase Connection for Various Operations");
System.out.println("\n1. Show list of tables\n2. Show contents of Table\n3. Create New Table\n4. Insert into table\n5. Update Table\n6. Delete From Table\n7. Exit\n");
System.out.println("Enter your option Number ");
DataInputStream dis=new DataInputStream(System.in);
int ch=Integer.parseInt(dis.readLine());
switch(ch)
{
case 1:
System.out.println(" You have selected to Show list of available tables");
//ResultSet rs=st.executeQuery("Show tables");
//while(rs.next())
//{
// System.out.println("List of Tables\n" +rs.getString("?????"));
//}
break;
}
from the above piece of code,
If I execute the query in ResultSet, How do I print the values inside the while loop..?
In rs.getString(); we can only pass either the column index or the column label as argument, but how do I get the list of tables...
what do I enter in place of "?????" inside print statement...?
please do help me, keeping in mind that you are explaining for a beginner...
Thanks in advance...!
We can use the console commands using,
DatabaseMetaData meta=getMetaData();
In the below code, it is shown that there are many ways (but I came to know two ways) of getting the list of tables
DatabaseMetaData meta = con.getMetaData();
ResultSet rs1 = meta.getTables(null, null, null,new String[] {"TABLE"});
ResultSet rs2 = meta.getTables(null, null,"%", null);
System.out.println("One way of Listing Tables");
while (rs1.next())
{
System.out.println(rs1.getString("TABLE_NAME"));
}
System.out.println("Another way of Listing Tables");
while(rs2.next())
{
System.out.println(rs2.getString(3));
}
A small example would be
String tableNamePattern = "%_Assessment_" + session + "_" + year;
DatabaseMetaData databaseMetaData = conn.getMetaData();
ResultSet rs = databaseMetaData.getTables(null, null, tableNamePattern,
null);
while(rs.next()) {
String tableName = rs.getString("TABLE_NAME");
...
}
Check the source

Operation not allowed after ResultSet Closed error Netbeans MySQL Connectivity

I am creating a program to rename databases in mysql.
I have succeeded in everything and it successfully happens. But in the end of my script, its shows an error/exception saying "Operation not allowed after ResultSet closed". I really have no idea why this error appears even after researching about this error.
Although the full operation is successfully completed and the database is renamed.
Here is my code->
String x = (String) jComboBox1.getSelectedItem(); //jComboBox1 contains the name of current database selected
String z = JOptionPane.showInputDialog("Please enter new name for Database"); //Where user enters the name for new database.
new CustComm().setVisible(false); //Frame that carries the names of tables.
try{
Class.forName("java.sql.DriverManager");
Connection con = (Connection)
DriverManager.getConnection("jdbc:mysql://localhost:"+GlobalParams.portvar+"/",""+k,""+j);
Statement stmnt = (Statement) con.createStatement();
String query = "use "+x;
stmnt.executeQuery(query);
String query2 = "show tables";
ResultSet rs = stmnt.executeQuery(query2);
while (rs.next()){
String dname = rs.getString("Tables_in_"+x);
if(CustComm.jTextArea1.getText().equals("")){
CustComm.jTextArea1.setText(CustComm.jTextArea1.getText()+dname);
}
else{
CustComm.jTextArea1.setText(CustComm.jTextArea1.getText()+"\n"+dname);
}
String y = CustComm.jTextArea1.getText();
Scanner scanner = new Scanner(y);
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
String query3 = "Create database "+z;
stmnt.executeUpdate(query3);
//alter table my_old_db.mytable rename my_new_db.mytable
String query4 = "RENAME TABLE "+x+"."+line+" TO "+z+"."+line;
stmnt.executeUpdate(query4);
String query5 = "drop database "+x;
stmnt.executeUpdate(query5);
}}}
catch(Exception e){
JOptionPane.showMessageDialog(this,e.getMessage());
}
Please help.
You shouldn't execute new queries on statement Statement stmnt = (Statement) con.createStatement(); while you use ResultSet from it, because this will close your 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.
You should create 2 different statements: first for query2 and second for queries 3-5.
Also it's better to use PreparedStatement. You can read about the difference here.
Do you have to do this work via code? Have you looked into tools like Liquibase?

If statement works but else if doesn't. why?

I am having trouble with getting my program to run properly. I was able to clear any syntax errors, but now I am having issued with my output.
I have the following statement and the ELSE IF doesn't seem to be working? it always ignores the else if codes. i can't understand the problem with the code.
Can anybody help me?
private void login_btnActionPerformed(java.awt.event.ActionEvent evt) {
Connection con;
PreparedStatement stmt;
ResultSet rs;
try {
//connect to the database
String host = "jdbc:derby://localhost:1537/LoginSystem";
String uName = "root";
String uPass = "root";
con = DriverManager.getConnection(host, uName, uPass);
String user = username_txt.getText();
String pass = passwordField_txt.getText();
String sql = "Select USERNAME,PASSWORD from LOGINSYSTEM where USERNAME = '"+user+"' AND PASSWORD = '"+pass+"'";
stmt = con.prepareStatement(sql);
rs = stmt.executeQuery();
while(rs.next()) {
String s1 = rs.getString(1);
String s2 = rs.getString(2);
if(user.equals(s1) && pass.equals(s2)) {
JOptionPane.showMessageDialog(null, "Login Successfull!");
Account obj = new Account();
obj.setVisible(true);
} else if(!user.equals(s1) && !pass.equals(s2)) {
JOptionPane.showMessageDialog(null, "Login Failed!");
} else if(!pass.equals(s2)) {
JOptionPane.showMessageDialog(null, "Please Enter A Valid Password.");
passwordField_txt.setText(null);
}
}
} catch(SQLException e) {
JOptionPane.showMessageDialog(null, e);
}
}
The query returns matching user and pass values so there is no condition where !user.equals(s1) && !pass.equals(s2) is satisified. Always use PreparedStatement placeholders rather than String concatenation to protect against SQL Injection.
Differentiating the error between an invalid usernames and passwords allows any would-be hacker an insight what information can be used to gain access to the system.
If anything the code should look like
if (rs.next()) {
String s1 = rs.getString(1);
String s2 = rs.getString(2);
// user and pass already match from SQL - no if logic necessary
} else {
// display GENERIC login failure message
}
But storing passwords in a database is a major security flaw so this whole approach is not safe. The typical approach is to store the password using a salt to guard against the use of rainbow tables. To verify the password the same hashing algorithm and salt can be used to compare against what is stored in the database,
First this is subject to a SQL injection attack. Learn about prepared statements, and use the parameter passing feature of prepared statements, to prevent user names like: Little Bobby Tables
Second, your where statement will only return back rows where the user name and password are exact matches to the inputted values. Therefore, comparing a non-null result will be guaranteed to always match, barring some incredibly bizarre database bug.
If you ask me to give you a fruit where the fruit is a red apple, then assuming that I am trusted, when I give you a red apple, checking to see if the apple is not an apple, or that red is not red will result in checking a condition that is never met.
If usernames are forced unique, you can take that matching condition for the password out of the query. Then just query for the username matching condition and get the username and password for that row. This way you can check for incorrect password OR incorrect username more easily. The way it is now the query will only return results when the username and password are correct and you will never enter your else if's.

Categories