prepared SQL statements in java - java

I'm trying to connect to a database and update a table in it using prepared statements in a java program -- the database is called "database" and in that there is another folder called Views in which the table ("TABLE") that I'm trying to update is. Here is my code:
public void updateTable(Map<String, String> mp) throws SQLException {
String URL = "jdbc:oracle:thin:#localhost:1500:orcl";
String USER = "user";
String PASS = "password";
Connection con = DriverManager.getConnection(URL, USER, PASS);
PreparedStatement updateTableName = null;
String updateString =
"update database.Views.TABLE " +
"set TABLENAME = ? " +
"where TABLENAME = ?";
try {
con.setAutoCommit(false);
updateTableName = con.prepareStatement(updateString);
for (Map.Entry<String, String> e : mp.entrySet())
{
updateTableName.setString(1, e.getValue());
updateTableName.setString(2, e.getKey());
updateTableName.executeUpdate();
con.commit();
}
} catch (SQLException e) {
if (con != null)
{
try {
System.err.print("Transaction is being rolled back");
con.rollback();
} catch (SQLException excep) {
}
}
} finally {
if (updateTableName != null)
{
updateTableName.close();
}
con.setAutoCommit(true);
}
con.close();
}
Whenever I run the code it displays "transaction is being rolled back." Any idea what errors I have in the try statement? Thanks in advance!
EDIT: when I change it to print the exception, it reads ORA-00971: missing SET keyword.

"update database.Views.TABLE" +
"set TABLENAME = ?" +
"where TABLENAME = ?";
The value of this string is
update database.Views.TABLEset TABLENAME = ?where TABLENAME = ?
That is not valid SQL.

You should try logging the SQLException you catch in the 1st catch block, that would give you a clear indication of what the problem is.
In any case, TABLE is a SQL-reserved keyword and you should not be allowed to name a table like that - at least try renaming it to TABLE1 for lack of a better name.

Ok I figured it out, #Spiff I did change it to the simplest query with just update TABLE1, but I also took out the :
String updateString =
"update database.Views.TABLE " +
"set TABLENAME = ? " +
"where TABLENAME = ?";
and combined it into one line with the
updateTableName = con.prepareStatement(updateString)
to make :
updateTableName = con.prepareStatement(update TABLE1 set TABLENAME = ? where TABLENAME = ?);

Related

Java & SQL prepareStatement error (Parameter index out of range)

I've been trying to fix a part of my code that throws a
java.sql.SQLException: Parameter index out of range (2 > number of parameters, which is 1).
I already searched stackoverflow and other parts of the internet but couldnt find the solution, that corrected the error.
This is the start of the class file:
PreparedStatement stmt;
And this is my constructer:
public DataAccessObjectImpl() throws Exception {
this.conn = new DBConnector();
}
This is the method thats cause the problem:
#Override
public boolean addAlbum(int UID, String artist, String album) {
String sql = "";
try {
stmt = conn.getConnection().prepareStatement("INSERT INTO music (identifier, UID, artist, album) VALUES (?,?,?,?);");
stmt.setString(1, getNewIdentifier());
stmt.setInt(2, UID);
stmt.setString(3, artist);
stmt.setString(4, album);
stmt.executeUpdate();
} catch (Exception ex) {
System.out.println("nugget 1 : " + ex);
} finally {
try {
if (stmt != null) {
stmt.close();
return true;
}
} catch (Exception e) {
System.out.println("Nugget 2 : " + e);
}
}
return false;
}
(the word "nugget" is just so its easy for myself to find in the log / console)
From what i could gather on stackoverflow its probably my question marks thats the problem, but I can't seem to figure out how. I used prepareStatement for other methods thats working just fine in the same class.
I have some working code I provided down below, I want to replace this code with preparestatement to patch SQL Injection:
try {
stmtb = conn.getConnection().createStatement();
sql = "INSERT INTO music VALUES ('" + getNewIdentifier() + "','" + UID + "','" + artist + "','" + album + "')";
} catch (SQLException ex) {
}
try {
stmt.executeUpdate(sql);
return true;
} catch (Exception e) {
System.out.println(e);
}
return false;
Thank you in advanced!
Fixed by changing this line:
stmt = conn.getConnection().prepareStatement("INSERT INTO music (identifier, UID, artist, album) VALUES (?,?,?,?);");
and i changed it to this:
PreparedStatement stmt = conn.getConnection().prepareStatement("SELECT * FROM user WHERE username = (?);");
and deleted this line:
PreparedStatement stmt;
Thank you Kayaman for the help!
Since the query is correct, but the exception occurs, the only possible explanation is that the stmt gets corrupted somehow. The only realistic situation would be in a multi-threaded environment with multiple threads using the same stmt to perform queries.
Since you're using prepareStatement() to create a new PreparedStatement object, there's no reason to share a "global" reference. In most cases the best practice is to define and use variables in the smallest scope possible.
Therefore remove the stmt variable from the outer scope, and instead just write
PreparedStatement stmt = conn.getConnection().prepareStatement(query);
where ever you need to.
In the query, which works, UID is passed like a VARCHAR, because it is surrounded with ''
sql = "INSERT INTO music VALUES ('" + getNewIdentifier() + "','" + UID + "','" + artist + "','" + album + "')";
Please, re-check database schema and ensure that UID is INTEGER. Also you may try to replace
stmt.setInt(2, UID);
with
stmt.setString(2, Integer.toString(UID));
to replicate simple Statement behaviour.

Delete from SQLite Database

I have an SQLite database linked up to my Java project within Eclipse. I'm able to delete entries from the database when I give a hardcoded, specified ID such as '3'. I'm trying to alter the code in order to enable the user the manually pass any number and have it delete that entry.
public static String deleteRecords(String NumberDelete){
Connection dbConnection = null;
Statement statement = null;
try{
dbConnection = getDBConnection();
dbConnection.setAutoCommit(false);
statement = dbConnection.createStatement();
String sql = "DELETE from employees where ID='NumberDelete';";
statement.executeUpdate(sql);
dbConnection.commit();
statement.close();
dbConnection.close();
} catch(Exception e) {
System.err.println(e.getClass().getName() + ": " + e.getMessage());
System.exit(0);
}
return NumberDelete;
}
You need to use PreparedStatement to pass the parameters to query and execute it, the method will look like this:
public static String deleteRecords(String NumberDelete) {
Connection dbConnection = null;
PreparedStatement statement = null;
String sql = "DELETE from employees where ID= ? ;";
try {
dbConnection = getDBConnection();
dbConnection.setAutoCommit(false);
statement = dbConnection.prepareStatement(sql);
statement.setString(1, NumberDelete);
statement.executeUpdate(sql);
dbConnection.commit();
statement.close();
dbConnection.close();
} catch (Exception e) {
System.err.println(e.getClass().getName() + ": " + e.getMessage());
System.exit(0);
}
return NumberDelete;
}
This will set the number in the query and execute it. If the number is of type int then you need to use setInt to set the value. Here is the javadoc for PreparedStatement.
For user input, you might want to check out the Scanner class: https://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html
Once you get an integer from the user, parse it, and store it in a variable, you can simply use String concatenation:
String sql = "DELETE from employees where ID='" + userInput + "';";

SQL error in java code "Column count doesn't match value count at row 1"

I have a problem with my program. When I try to write to my database (in MySQL) I get this error "Column count doesn't match value count at row 1"
This is my code:
public void registreerNieuwSpelbord(String spelnaam, String mapcode) {
try (Connection connectie = DriverManager.getConnection(Connectie.JDBC_URL)) {
Statement stmt = connectie.createStatement();
String schrijfSpelbordWeg = "INSERT INTO spelbord(Mapcode, spel_Spelnaam) values('" + mapcode + "," + spelnaam + "')";
stmt.executeUpdate(schrijfSpelbordWeg);
} catch (SQLException ex) {
throw new RuntimeException(ex);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
note: there is also a 3th column with an ID that automatically gives a number
You have two columns listed in the insert, but only one value.
Try this:
String schrijfSpelbordWeg = "INSERT INTO spelbord(Mapcode, spel_Spelnaam) values('" + mapcode + "','" + spelnaam + "')";
You should always use a PreparedStatement and bind variables when dealing with SQL that takes input parameters. This way, you're eliminating the chance of SQL injection, allowing the DB to re-use/cache your query and sparing yourself from hunting down bugs that are caused by missing a quote around a parameter.
Here's a refactored version that uses parameterized SQL:
public void registreerNieuwSpelbord(String spelnaam, String mapcode) {
String sql = "INSERT INTO spelbord(Mapcode, spel_Spelnaam) values(?, ?)";
try (Connection connectie = DriverManager.getConnection(Connectie.JDBC_URL);
PreparedStatement ps = connectie.prepareStatement(sql);) {
ps.setString(1, mapcode);
ps.setString(2, spelnaam);
ps.executeUpdate();
} catch (SQLException ex) {
throw new RuntimeException(ex);
}
}

Delete row from database

I have a database table with the following layout:
Columns:
_________________________
id | user_name | password
But I can't delete a specified row by using the username.
I am receiving the following error:
MySQLSyntaxErrorException: Unknown column 'vipin' in 'where clause'
vipin is a value within the table.
Can anyone help me?
public void deleteFclty() {
PreparedStatement stmt = null;
ResultSet rs = null;
String username = removeText.getText();
ArrayList<String> values = new ArrayList();
String qry = "SELECT user_name From users ";
try {
stmt = (PreparedStatement) connection.prepareStatement(qry);
rs = stmt.executeQuery();
while (rs.next()) {
values.add(0, rs.getString(("user_name")));
System.out.println(values);
}
} catch (SQLException ex) {
Logger.getLogger(RemoveFaculty.class.getName()).log(Level.SEVERE, null, ex);
}
if (values.contains(username)) {
username = removeText.getText();
Boolean isAdmin = false;
try {
System.out.println(username);
preparedStatement = (PreparedStatement) connection.prepareStatement("DELETE FROM users WHERE user_name=" + username + "");
preparedStatement.executeUpdate();
} catch (SQLException ex) {
Logger.getLogger(RemoveFaculty.class.getName()).log(Level.SEVERE, null, ex);
}
} else {
Util.showErrorMessageDialog(username + " is not found.Please try again.");
}
}
Since you're already using PreparedStatement, use it right and pass the username as parameter instead of just concatenating the Strings:
//no need to use a cast here
preparedStatement = connection.prepareStatement(
//note the usage of ? instead of concatenating Strings
"DELETE FROM users WHERE user_name=?");
//setting the first parameter in the query string to be username
preparedStatement.setString(1, username);
preparedStatement.executeUpdate();
Using this, you won't have any concatenation problems and what's better, your code won't be prone to SQL Injection.
Not directly related to your problem, but it would be better if you move the code to execute INSERT, UPDATE and DELETE statements to a single method.
public void executeUpdate(Connection con, String query, Object ... params)
throws SQLException {
PreparedStatement pstmt = con.prepareStatement(query);
if (params != null) {
int i = 1;
for(Object param : params) {
pstmt.setObject(i++, param);
}
}
pstmt.executeUpdate();
pstmt.close();
}
So your code would be dramatically reduced to:
String deleteSQL = "DELETE FROM users WHERE user_name=?";
executeUpdate(deleteSQL, username);
Note that you can create a new method based on this approach to execute SELECT statements.
Also, don't forget to close your resources. This also can be dramatically reduced using a method like this:
public void closeResource(AutoCloseable res) {
try {
if (res != null) {
res.close();
}
} catch (Exception e) {
//handle this exception...
//basic example, not meant to be used in production!
e.printStacktrace(System.out);
}
}
Note that Connection, Statement (and its children PreparedStatement and CallableStatement) and ResultSet interfaces already extend from AutoCloseable.
You haven't quoted the username you're inserting into the query, so it's being treated as a reference to a field name:
DELETE FROM users WHERE user_name='"+username+"'"
^-- ^--
Note: building queries like this leaves you open to SQL injection attacks. Used prepared statements and placeholders instead.
I think you might need some quotes round the username in the where clause
connection.prepareStatement("DELETE FROM users WHERE user_name='"+username+"'");
You are going to want to quote your Strings
"DELETE FROM users WHERE user_name="+username+"";
Like this:
"DELETE FROM users WHERE user_name='" + username + "'";
What would be better is just using PreparedStatement as it was intended:
"DELETE FROM users WHERE user_name = ?";
And then using:
preparedStatement.setString(1, username);
before calling executeUpdate
The query should look like this
preparedStatement = (PreparedStatement) connection.prepareStatement("DELETE FROM users WHERE user_name='"+username+"'");
Note : Mind the single quotes used for user_name='"+username+"'"

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