This JDBC query does not return anything despite it working on my SQLite Database Browser, no matter what I tried. The snippet is pretty self-explanatory of the results I'm looking for.
public void getCountryIdLocationIdDepartmentIdParEmploye(Employe employe) {
String query = "SELECT countries.country_id AS idc, locations.location_id AS idl, departments.department_id AS idd
FROM countries
INNER JOIN locations ON countries.country_id = locations.country_id
INNER JOIN departments ON locations.location_id = departments.location_id
INNER JOIN employees ON departments.department_id = employees.department_id
AND employees.employee_id = ?";
try {
PreparedStatement ps = maConnexion.prepareStatement(query);
ResultSet rs = ps.executeQuery();
ps.setInt(1, employe.getId());
setCountry_id(rs.getString("idc"));
setLocation_id(rs.getInt("idl"));
setDepartment_id(rs.getInt("idd"));
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
I've tried to replace setCountry_id(rs.getString("idc")); with setCountry_id(rs.getString(1)); etc. already but no good, my attributes stay unchanged.
Regards,
PS: country_id is indeed a string
In a compliant JDBC driver this should throw a SQLException because you set the parameter after executing the query (which means it should not be possible to execute the statement). It sounds like the SQLite JDBC driver has a bug in that regard.
You need to set the parameter before executing:
try (PreparedStatement ps = maConnexion.prepareStatement(query)) {
ps.setInt(1, employe.getId());
try (ResultSet rs = ps.executeQuery()) {
setCountry_id(rs.getString("idc"));
setLocation_id(rs.getInt("idl"));
setDepartment_id(rs.getInt("idd"));
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
Also observe the use of try-with-resources, which ensures you don't leak the prepared statement and result set.
Related
This question already has answers here:
Java MYSQL Prepared Statement Error: Check syntax to use near '?' at line 1
(2 answers)
Closed 1 year ago.
I faced this problem today with my select SQL. This method is supposed to show data from database in tex tfields. I changed it from statement to preparedStatement, but I faced a problem.
public Entreprise loadDataModify(String id) {
Entreprise e = new Entreprise();
PreparedStatement stmt;
try {
String sql = "SELECT * FROM user WHERE mail=?";
stmt = cnx.prepareStatement(sql);
stmt.setString(1, id);
ResultSet rst = stmt.executeQuery(sql);
while (rst.next()) {
stmt.setString(2, e.getNom());
stmt.setString(3, e.getEmail());
stmt.setString(4, e.getTel());
stmt.setString(5, e.getOffre());
}
} catch (SQLException ex) {
System.out.println(ex.getMessage());
}
return e;
}
It shows i have problem with syntax and the output is " nu
You're calling the wrong method. Unlike Statement, when you're using a PreperedStatement you should first set the values for the parameters, and after you can call on that instance executeQuery() method.
Also, it's a best practice to use try-with-resources, because a Statement or PreparedStament object is a Resource (a resource is a class that implements AutoCloseable interface) and you have to close it. Using try-with-resources, it's done automatically.
The ResultSet instance is also a resource, but it's closed when the statement object is closed, so you don't have to close it explicitly.
So, the best way to solve your problem will be:
String selectAllByMail = "SELECT * FROM user WHERE mail=?";
try (PreparedStatement prpStatement = connection.prepareStatement(selectAllByMail)) {
// use prpStatement
prpStatement.setString(1, id);
ResultSet resultSet = prpStatement.executeQuery();
while (resultSet.next()) {
// process resultSet
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
You are not filling your Enterprise object. And you are not using executeQuery() function correctly. As seen below, the parameter inside the brackets has been removed. PreparedStatements first of all need the values of the parameters (your ? in the query) and then the formed query has to be executed. If you give a String parameter to executeQuery() then the query in the brackets will be executed.
And the part where Enterprise is being filled could be seen below.
This would be the correct way:
public Entreprise loadDataModify(String id) {
Entreprise e = new Entreprise();
PreparedStatement stmt;
try {
String sql = "SELECT * FROM user WHERE mail=?";
stmt = cnx.prepareStatement(sql);
stmt.setString(1, id);
ResultSet rst = stmt.executeQuery();
while (rst.next())
{
// rst keeps the data, so you have to traverse it and get the data from it in this way.
e.setNom( rst.getString("HERE EITHER THE COLUMN NAME OR INDEX"));
e.setEmail( rst.getString("HERE EITHER THE COLUMN NAME OR INDEX"));
e.setTel( rst.getString("HERE EITHER THE COLUMN NAME OR INDEX"));
e.setOffre( rst.getString("HERE EITHER THE COLUMN NAME OR INDEX"));
}
} catch (SQLException ex) {
System.out.println(ex.getMessage());
}
return e;
}
Your call to executeQuery() should not be passing the query string. Use this version:
String sql = "SELECT * FROM user WHERE mail=?";
stmt = cnx.prepareStatement(sql);
stmt.setString(1, id);
ResultSet rst = stmt.executeQuery();
while (rst.next()) {
// process result set
}
Your current code is actually calling some overloaded Statement#executeQuery() method, which is not the version of the method which you want to be calling.
in my small test program I have some SQL Queries. The first SELECT * FROM kilometer; works properly and returns all the columns in the table. So in Java embedded, ResultSet rs = stmt.executeQuery("SELECT * FROM kilometer;"); returns an ResultSet which is not empty.
Now I wanted to get only the rows within a specific date. But my embedded query ResultSet rs = stmt.executeQuery("SELECT * FROM kilometer WHERE datum BETWEEN '2016-01-01' AND '2016-12-31';"); returns an empty ResultSet. But I've tested it online and it worked properly. Where is my mistake? I've consulted already some pages like this, but I can't find the mistake.
I am using SQLite 3.15.1 and Java SE 8.
Full java code:
public ArrayList<Strecke> getErgebnisse(final String startzeitpunkt, final String zielzeitpunkt) {
ArrayList<Strecke> strecken = new ArrayList<>();
try {
try {
if (connection != null) {
}
connection = DriverManager.getConnection("jdbc:sqlite:" + DB_PATH);
if (!connection.isClosed())
} catch (SQLException e) {
throw new RuntimeException(e);
}
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM kilometer WHERE datum BETWEEN '2016-01-01' AND '2016-12-31';");
while (rs.next()) {
strecken.add(new Strecke(Instant.ofEpochMilli(rs.getDate("datum").getTime()).atZone(ZoneId.systemDefault()).toLocalDate(), rs.getString("startort"), rs.getString("zielort"), rs.getDouble("kilometer")));
}
rs.close();
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
return strecken;
}
First of all I would recommend that you use prepared statements while executing your queries instead of passing the query directly as a string......secondly I believe the problem here is that you are passing the date as a string in quotes and not a date.....I think that is the issue here. You would need to use sqllites datetime functions for this....
I've been looking around and can't seem to find a solid answer to this. I was wondering if putting a string literal in executeQuery() is still prone to SQL injection.
So lets say I have this code:
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/","root","password");
Statement stmt = conn.createStatement();
ResultSet res = stmt.executeQuery("SELECT * from users where uid = "+uid);
Is this prone to a SQL injection?
Another question is, is just making the method that uses this code only throw an SQLException, and then trying and catching in main acceptable?
For example:
public void execMethod(String uid) throws SQLException {
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/","root","password");
Statement stmt = conn.createStatement();
ResultSet res = stmt.executeQuery("SELECT * from users where uid = "+uid);
// execute some other code
res.close();
}
public static void main(String[] args) {
try {
execMethod("123");
execMethod("456");
} catch(Exception ex) {
ex.printStackTrace();
}
}
Is this the standard or correct way of using SQL exceptions? I've never really worked with SQL and especially not Java and SQL. The tutorials I've read seem to only lay it out one way, so I'm pretty unsure of myself.
Is this prone to a SQL injection?"
Yes, you have no control over what uid might actually contain.
See Using Prepared Statements for more details
Another question is, is just making the method that uses this code only throw an SQLException, and then trying and catching in main acceptable?"
Yes, but you should at least wrap the contends of execMethod in try-finally to ensure that you are closing the resources you open (or use a try-with-resources for Java 7)
public void execMethod(String uid) throws SQLException {
try (Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/", "root", "password")) {
try (PreparedStatement stmt = conn.prepareStatement("SELECT * from users where uid = ?")) {
stmt.setString(1, uid);
try (ResultSet res = stmt.executeQuery()) {
// Process ressult set
}
}
}
}
See The try-with-resources Statement for more details
But, I would only catch the SQLException for EACH call, not batch them together, as you won't know what failed and what succeeded
try {
execMethod("123");
try {
execMethod("456");
} catch (Exception ex) {
// Maybe undo 123
System.out.println("Failed 456");
ex.printStackTrace();
}
} catch (Exception ex) {
System.out.println("Failed 123");
ex.printStackTrace();
}
(assuming that 456 is dependent on the success of 123)
Short answer : yes.
You do not appear to be doing any kind of input validation so there isn't anything stopping uid from being something like "105 or 1=1"
You should probably use PreparedStatements tutorial here
PreparedStatement stmt = conn.prepareStatement("SELECT * from users where uid = ?")
stmt.setString(1, uid);
..same as before
Also you don't close the statement or the connection which should be done in a finally block incase an exception is thrown
Yes. If uid can be entered by a user (it's not a String literal). I suggest you use a PreparedStatement, and a try-with-resources like
final String sql = "SELECT * from users where uid = ?";
try (PreparedStatement ps = conn.prepareStatement(sql)) {
ps.setString(1, uid);
try (ResultSet res = ps.executeQuery()) {
while (res.next()) {
// ...
}
}
}
The PreparedStatement (with bind variable) has at least these advantages
It can use the Statement cache on the server
It is not prone to SQL Injection
I'm want to delete a person from the database "person" on a given id. It works if I don't use Prepared Statement (the first 5 unmarked lines of code in the try-statement).
But when I try to do it using Prepared Statement it does not work, and I canĀ“t figure out why?
The application gets stuck on prepStatement.executeUpdate();
Therefore I can't even see the value of executeUpdate (if I want to se how many Changes that are made).
I have a similar method, addPerson, where Prepered Statement works perfect. This really confuses me...
I appreciate your help.
private void removePerson() {
int id = Integer.parseInt(idField.getText());
PreparedStatement prepStatement = null;
try {
*/* Statement statement = connection.createStatement();
String sql = "DELETE FROM person WHERE id = '"+id+"'";
statement.executeUpdate(sql);
System.out.println("Person removed from database...");
ResultSet result = statement.executeQuery(sql);
*/*
String sql = "DELETE FROM person WHREE id = ?";
prepStatement = connection.prepareStatement(sql);
prepStatement.setInt(1, id);
prepStatement.executeUpdate();
System.out.println("Person removed from database...");
}
catch (SQLException se) {
se.toString();
}
finally {
try {
prepStatement.close();
}
catch (SQLException ex) {
ex.toString();
}
}
}
Is there a way to retrieve the auto generated key from a DB query when using a java query with prepared statements.
For example, I know AutoGeneratedKeys can work as follows.
stmt = conn.createStatement();
stmt.executeUpdate(sql, Statement.RETURN_GENERATED_KEYS);
if(returnLastInsertId) {
ResultSet rs = stmt.getGeneratedKeys();
rs.next();
auto_id = rs.getInt(1);
}
However. What if I want to do an insert with a prepared Statement.
String sql = "INSERT INTO table (column1, column2) values(?, ?)";
stmt = conn.prepareStatement(sql);
//this is an error
stmt.executeUpdate(Statement.RETURN_GENERATED_KEYS);
if(returnLastInsertId) {
//this is an error since the above is an error
ResultSet rs = stmt.getGeneratedKeys();
rs.next();
auto_id = rs.getInt(1);
}
Is there a way to do this that I don't know about. It seems from the javadoc that PreparedStatements can't return the Auto Generated ID.
Yes. See here. Section 7.1.9. Change your code to:
String sql = "INSERT INTO table (column1, column2) values(?, ?)";
stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
stmt.executeUpdate();
if(returnLastInsertId) {
ResultSet rs = stmt.getGeneratedKeys();
rs.next();
auto_id = rs.getInt(1);
}
There's a couple of ways, and it seems different jdbc drivers handles things a bit different, or not at all in some cases(some will only give you autogenerated primary keys, not other columns) but the basic forms are
stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
Or use this form:
String autogenColumns[] = {"column1","column2"};
stmt = conn.prepareStatement(sql, autogenColumns)
Yes, There is a way. I just found this hiding in the java doc.
They way is to pass the AutoGeneratedKeys id as follows
String sql = "INSERT INTO table (column1, column2) values(?, ?)";
stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
I'm one of those that surfed through a few threads looking for solution of this issue ... and finally get it to work. FOR THOSE USING jdbc:oracle:thin: with ojdbc6.jar PLEASE TAKE NOTE:
You can use either methods:
(Method 1)
Try{
String yourSQL="insert into Table1(Id,Col2,Col3) values(SEQ.nextval,?,?)";
myPrepStatement = <Connection>.prepareStatement(yourSQL, Statement.RETURN_GENERATED_KEYS);
myPrepStatement.setInt(1, 123);
myPrepStatement.setInt(2, 123);
myPrepStatement.executeUpdate();
ResultSet rs = getGeneratedKeys;
if(rs.next()) {
java.sql.RowId rid=rs.getRowId(1);
//what you get is only a RowId ref, try make use of it anyway U could think of
System.out.println(rid);
}
} catch (SQLException e) {
//
}
(Method 2)
Try{
String yourSQL="insert into Table1(Id,Col2,Col3) values(SEQ.nextval,?,?)";
//IMPORTANT: here's where other threads don tell U, you need to list ALL cols
//mentioned in your query in the array
myPrepStatement = <Connection>.prepareStatement(yourSQL, new String[]{"Id","Col2","Col3"});
myPrepStatement.setInt(1, 123);
myPrepStatement.setInt(2, 123);
myPrepStatement.executeUpdate();
ResultSet rs = getGeneratedKeys;
if(rs.next()) {
//In this exp, the autoKey val is in 1st col
int id=rs.getLong(1);
//now this's a real value of col Id
System.out.println(id);
}
} catch (SQLException e) {
//
}
Basically, try not used Method1 if you just want the value of SEQ.Nextval, b'cse it just return the RowID ref that you may cracked your head finding way to make use of it, which also don fit all data type you tried casting it to! This may works fine (return actual val) in MySQL, DB2 but not in Oracle.
AND, turn off your SQL Developer, Toad or any client which use the same login session to do INSERT when you're debugging. It MAY not affect you every time (debugging call) ... until you find your apps freeze without exception for some time. Yes ... halt without exception!
Connection connection=null;
int generatedkey=0;
PreparedStatement pstmt=connection.prepareStatement("Your insert query");
ResultSet rs=pstmt.getGeneratedKeys();
if (rs.next()) {
generatedkey=rs.getInt(1);
System.out.println("Auto Generated Primary Key " + generatedkey);
}