How to execute a SQL statement in Java with variables - java

I have the following mysql statement to delete records from a DB that is working.
SET #email = 'delete#mailinator.com';
SET #userID = (SELECT id FROM USER WHERE email = #email);
DELETE FROM user_role_group WHERE user_id = #userID;
DELETE FROM user_client_setup WHERE user_id = #userID;
DELETE FROM USER WHERE id = #userID;
I want to run this same query in Java with a jdbc mysql connection. I have tried the following
public void deleteCoreUser(String email) {
try{
Class.forName("com.mysql.cj.jdbc.Driver");
Connection con=DriverManager.getConnection(
"jdbc:mysql://db.com:3306/core","username","password");
Statement stmt=con.createStatement();
ResultSet rs=stmt.executeQuery("SET #email = '"+email+"';\n" +
"SET #userID = (SELECT id FROM user WHERE email = #email);\n" +
"DELETE FROM user_role_group WHERE user_id = #userID;\n" +
"DELETE FROM user_client_setup WHERE user_id = #userID;\n" +
"DELETE FROM user WHERE id = #userID;");
con.close();
System.out.println("Deleting user "+email+" from the Core DB");
}catch(Exception e){ System.out.println(e);}
}
I am getting this error when running
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 'SET #userID = (SELECT id
FROM user WHERE email = #email); DELETE FROM user_role_' at line 2

Use execute() instead of executeQuery() since it returns multiple ResultSet. See answer (Statement.execute(sql) vs executeUpdate(sql) and executeQuery(sql)) and add ?allowMultiQueries=true to the database url
"jdbc:mysql://db.com:3306/core?allowMultiQueries=true"

If the MySQL queries are running correctly in MySQL console, then there is no reason that same query will show syntax error when handling it with jdbc. You are making mistakes in implementing the queries with java and how java handles it.
public void deleteCoreUser(String email) {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql://db.com:3306/core","username","password");
Statement stmt = con.createStatement();
String sql = "SET #email = '" + email + "'";
stmt.execute(sql);
sql = "SET #userID = (SELECT id FROM USER WHERE email = #email)";
stmt.execute(sql);
sql = "DELETE FROM user_role_group WHERE user_id = #userID";
stmt.execute(sql);
sql = "DELETE FROM user_client_setup WHERE user_id = #userID";
stmt.execute(sql);
sql = "DELETE FROM USER WHERE id = #userID";
stmt.execute(sql);
con.close();
System.out.println("Deleting user " + email + " from the Core DB");
} catch(Exception e){ System.out.println(e);}
}
stmt.executeQuery is used when you try to get resultset from the queries. But in this case you are not asking for resultset. That's why no Resultset is necessary and only stmt.execute should work.

I suspect the issue is due to the allowMultiQueries flag in MariaDB. This defaults to false, meaning each query is essentially run in a vacuum and your SET #userID = (SELECT id FROM user WHERE email = #email); query doesn't know what #email is. To resolve this with you current code, set the database allowMultiQueries=true.

Related

Alter login password with SQL statement doesn't work using Java PreparedStatement

I want to change the password of a Microsoft SQL Server User with the following SQL statement over JDBC (documentation):
ALTER LOGIN username WITH PASSWORD = '<newpassword>'
Constructing this statement with Java String concatenation is no option, because SQL injection would be possible:
String statement = "ALTER LOGIN username WITH PASSWORD = '" + newPassword + "'";
To circumvent this problem, I want to use a Java PreparedStatement:
// ... open JDBC connection "connection" ...
String sql = "ALTER LOGIN username WITH PASSWORD = ?";
try (PreparedStatement statement = connection.prepareStatement(sql))
{
statement.setString(1, newPassword);
statement.execute();
}
When this code is executed, the following Exception occurs:
com.microsoft.sqlserver.jdbc.SQLServerException: Incorrect syntax near '#P0'.
Is there a way to make this work, or are there any alternatives to change a user's password?
I solved the problem by first generating the hash of the password and then altering the login by passing the hash instead of the plaintext password:
// ... open JDBC connection "connection" ...
String sql = "SELECT PWDENCRYPT(?)";
String hash;
try (PreparedStatement statement = connection.prepareStatement(sql))
{
statement.setString(1, newPassword);
ResultSet rs = statement.executeQuery();
rs.next();
hash = rs.getString(1);
}
try (Statement statement = connection.createStatement())
{
sql = "ALTER LOGIN username WITH PASSWORD = 0x" + hash + " HASHED";
statement.execute(sql);
}

inserting new user object into JDBC through the servlet

Here is the code for my servlet which recieves username parameter from a registration form
String tusername=request.getParamater("un");
String dbURL="db.com";
String dbusername= "lc";
String dbpassword="lcpw";
Connection con=(Connection) DriverManager.getConnection(dbURL,dbusername,dbpassword);
Statement stmt= con.createStatement();
String query="SELECT * FROM users.username WHERE username=(tusername)";
ResultSet rs= stmt.executeQuery(query);
if(rs.next()==false){
//create new userobject with value of tusername
}
My question is how do I create a new user object with calue of tusername, would it be like so ?
if(rs.next()==false){
Statement stmt=con.createStatament();
String query="INSERT INTO user.username VALUE 'tusername'";
ResultSet rs= stmt.updateQuery(query);
}
I understand some of this might be archaic (such as not using a prepared statement) , I am just trying to better my understanding and I think I am having some small syntax issues, thanks :)
You should be using a NOT EXISTS query to do the insert, and also you should ideally be using a prepared statement:
String sql = "INSERT INTO user.username (username) ";
sql += "SELECT ? FROM dual WHERE NOT EXISTS (SELECT 1 FROM user.username WHERE username = ?)";
PreparedStatement ps = con.prepareStatement(sql);
ps.setString(1, tusername);
ps.setString(2, tusername);
int result = ps.executeUpdate();
if (result > 0) {
System.out.println("Inserted new user " + tusername + " into username table";
}
else {
System.out.println("User " + tusername + " already exists; no new record was inserted");
}
I don't know what your actual database is. The above should work out of the box for MySQL and Oracle. It might need to be modified slightly for other databases.
An alternative to the above query would be to just use your current insert, but make the username column a (unique) primary key. In that case, any attempt to insert a duplicate would fail at the database level, probably resulting in an exception in your Java code. This would also be a more database agnostic approach.

Database query works in MySQL workbench but not when I try to run them from Java

I am trying to execute a MySQL transaction from Java. This works in my Workbench, but when I execute it from Java it gives me this: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'Insert into User(username, password) values ('asd', 'asd'); set #userId = LAST' at line 1
This is my query:
public static final String CREATE_USER = "start transaction;" +
" Insert into User(username, `password`) values (?, ?);" +
" set #userId = LAST_INSERT_ID();" +
" Insert into User_Roles values (#userId, ?);" +
" commit;";
An here is the code for executing this query
public static boolean createUser(UserEntity user) {
try (Connection connection = DriverManager.getConnection(Constants.URL, Constants.DATABASE_USERNAME, Constants.DATABASE_PASSWORD)) {
System.out.println("Database connected!");
PreparedStatement st = connection.prepareStatement(DatabaseQuery.CREATE_USER);
st.setString(1, user.getUsername());
st.setString(2, user.getPassword());
if(user.getRole().equals("User"))
st.setInt(3, 1);
else
st.setInt(3, 2);
if (st.execute())
return true;
} catch (SQLException e) {
e.printStackTrace();
}
return false;
}
I looked at this question 1, but I don't have space problems.
[SOLVED]
Yes, you were right I had multiple statements on the same query.
The way I solved it was to modify my database URL so it can accept multiple query separated by semicolon, like this:
public static String URL = "jdbc:mysql://localhost/javaDb?allowMultiQueries=true";

Struts2: Save SQL query in the database

In my Struts2 Java web application users are allowed to query the database. As an example, the user needs to get the employee details whose first name is equal to 'Charles'. Then s/he can select the report columns and criteria (firstname='Charles').
Once the user gives above inputs it need to save the relevant SQL query into the database.
e.g. SQL -> SELECT * FROM employee WHERE firstname='Charles'
Here is what I am trying in my action class.
try {
connection = DriverManager.getConnection(
SelectAction.getDatabase(), SelectAction.getUser(),
SelectAction.getPassword());
if (connection != null) {
System.out.println("Database connection established!");
stmt = connection.createStatement();
String sql = "INSERT INTO reports (report_id, sql) values ('" + reportId + "', '" + sqlQ + "');";
System.out.println("sql--->" + sql);
// Executing query
stmt.executeQuery(sql);
return SUCCESS;
} else {
System.out.println("----Failed to make connection!");
return ERROR;
}
} catch (SQLException e) {
System.out.println("Connection Failed!!");
e.printStackTrace();
return SUCCESS;
}
This is my insert query.
INSERT INTO reports (report_id, sql) values ('mynewreport', 'SELECT * FROM employee WHERE firstname='Charles'');
I am getting following error in my console.
ERROR: syntax error at or near "Charles"
I think here I am using a String so that the problem is with quotes('). I am using postgreSQL as database.
Any suggestions to solve this issue ?
Never use string concatenation of user supplied values to build a SQL statement.
Never use string concatenation of any non-integer values to build a SQL statement.
You will leave yourself open to SQL Injection attacks and/or SQL statement errors.
Hackers will love you for allowing them to steal all your data, and the nefarious ones will corrupt or delete all your data, while laughing maniacally at you on their way to the bank.
Use PreparedStatement and parameter markers.
String sql = "INSERT INTO reports (report_id, sql) values (?, ?)";
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setString(1, reportId);
stmt.setString(2, sqlQ);
stmt.executeUpdate();
}

How to create and execute an SQL update statement

I have a table inside consist of variable like Username, ContactNo, Date, Name.
And i would like to do a update for Username and ContactNo only to the original record in the database.
How can i make use of update sql statement to do it?
Below is my SELECT sql statement.
public void dbData(String UName)
{
try
{
Class.forName("com.mysql.jdbc.Driver");
con = DriverManager.getConnection("jdbc:mysql://localhost/assignment","root","mysql");
ps = con.createStatement();
SQL_Str="Select username,numberOfBid from customer where username like ('" + UName +"')";
//SQL_Str="Select * from customer";
rs=ps.executeQuery(SQL_Str);
rs.next();
dbusername=rs.getString("username").toString();
dbbid=rs.getInt("numberOfBid");
//UName2 = rs.getString("username").toString();
UName2 = username;
}
catch(Exception ex)
{
ex.printStackTrace();
System.out.println("Exception Occur :" + ex);
}
}
http://dev.mysql.com/doc/refman/5.0/en/update.html
And please study...
Here is a quick and dirty solution: when you have modified your values, just add something like this
String updSQL = "udate table set numberOfBid = " + dbbid + " where user = " + UName;
ps.executeUpdate(updSQL);
There are however 1000 improvements you can make such using prepared statementsand placeholders:
String updSQL = "udate table set numberOfBid = ? where username like ?";
PreparedStatement pstmt = con.prepareStatement(updSQL);
pstmt.setInt(0, dbbid);
pstmt.setString(1, UName);
pstmt.execute();
May I suggest you to have a look at Hibernate, Spring JDBC, JPA... which are on a much higher level than JDBC is.

Categories