How to pass a List of Integer value with PreparedStatement - java

I try to write a code for make a SELECT on MySql DB like this
SELECT MESE,IMPORTO,ANNO FROM VISTASTATISTICHEMENSILI WHERE ANNO in(?)
So, I would like to pass a list of Integer value like this:
PreparedStatement stmt = db.prepareStatement(queryDettaglio);
Integer[] myArr = new Integer[2];
myArr[0] = 1;
myArr[1] = 2;
stmt.setArray(1, db.createArrayOf("INTEGER", myArr));
ResultSet rs = stmt.executeQuery();
So, when I try to run this code I have this error:
DEBUG [AWT-EventQueue-0] (MyLog4J.java:45) - java.sql.SQLFeatureNotSupportedException
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at java.lang.Class.newInstance0(Class.java:357)
at java.lang.Class.newInstance(Class.java:310)
at com.mysql.jdbc.SQLError.notImplemented(SQLError.java:1332)
at com.mysql.jdbc.JDBC4Connection.createArrayOf(JDBC4Connection.java:58)
When I fix it?
Reguards

You can not pass an array to a ? in a prepared statement. The correct way to do it and avoid all chance of injection attack is like this:
StringBuilder idList = new StringBuilder()
for (int id : myArr) {
if (idList.length() > 0) {
idList.append(",");
}
idList.append("?");
}
PreparedStatement ps = con.prepareStement("SELECT MESE,IMPORTO,ANNO FROM VISTASTATISTICHEMENSILI WHERE ANNO in("+idList+");
for (int i = 0; i < myArr.length; i++) {
ps.setInt(i+1,myArr[i]);
}
Basically you are building a prepared statement with the right number of ? marks and then setting the parameters in.
Because myArr is declared as an Integer[] array, you can also just do this:
StringBuilder idList = new StringBuilder()
for (int id : myArr) {
if (idList.length() > 0) {
idList.append(",");
}
idList.append(id);
}
Statement stmt = con.createStatement();
stmt.executeQuery("SELECT MESE,IMPORTO,ANNO FROM VISTASTATISTICHEMENSILI WHERE ANNO in("+idList+");
There is no issue with injection because the integers can't possibly have injected characters (if they did, they wouldn't be integers)

Try binding n integers manually inside for loop.
Before that you should create ?,?,...,? pattern in sql.
Good luck.
import org.apache.commons.lang3.StringUtils;
/*
* example: for n=4 creates pattern: ?,?,?,?
*/
public String createInListPattern(int n) {
return StringUtils.repeat("?", ",", n);
}
public void doSelect(Integer[] myArr, Connection conn) {
int size = myArr.length;
String sql = "SELECT MESE,... FROM TABLE WHERE ANNO in ("
+ createInListPattern(size) + ")";
// be sure to properly handle sql exceptions
PreparedStatement stmt = conn.prepareStatement(sql);
// bind parameters
for (int i = 0; i < size; i++) {
stmt.setInt(i + 1, myArr[i]);
}
// execute query
ResultSet rs = stmt.executeQuery();
}

Related

Insert list <string> into database using Java

I want to insert list of string into database so usually we will store the string directly into the database by either using a prepared statement or a batch statement. Now I want to insert list of string into a database, so I have used a prepared statement.
List<String> Account_Number = Files.lines(Paths.get("D:\\PDFTOEXCEL\\Extractionfrompdf.txt"))
.filter(s -> s.contains(arra.get(7)))
.map(s -> s.split(":")[1].trim())
.collect(Collectors.toList());
System.out.println(Account_Number);
try {
Connection conn = PDFTOEXCEL.getConnection();
PreparedStatement stmt = conn.prepareStatement("insert into client_info values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
stmt.setString(1, Account_Number);
int k = stmt.executeUpdate();
I have about 31 columns in my database. Just for showing I have posted only one in this code. All are in the list of the string only.
Have you tried to set the parameters one by one? Something like this:
int size = Account_Number.size();
for (int i = 1; i <= size; i++) {
stmt.setString(i, Account_Number.get(i-1));
}

How to do Looping with ResultSet?

So, I want to loop this ResultSet in order to update the table one by one, but the method while(rsl.next()) can't help me do the looping. It's just work once, and then the others are skipped. Can someone help me fix this problem? Thanks in advance
try {
String url = "jdbc:mysql://localhost/minimarket";
String user = "root";
String pass = "";
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection(url, user, pass);
Statement stmt = conn.createStatement();
ResultSet rsl = stmt.executeQuery("SELECT * FROM keranjang WHERE pemesan='"+login.userid+"'");
while (rsl.next()) {
String nb = rsl.getString("nama_barang");
String dtl = rsl.getString("detail");
String beratt = rsl.getString("berat");
String hrga = rsl.getString("harga");
String jmlh = rsl.getString("jumlah");
stmt.executeUpdate("UPDATE barang SET stok=stok+'"+jmlh+"' WHERE nama_barang='"+nb+"' AND detail='"+dtl+"' AND berat='"+beratt+"'");
stmt.executeUpdate("DELETE FROM keranjang WHERE pemesan ='"+login.userid+"' AND nama_barang='"+nb+"'");
}
conn.close();
} catch (Exception error) {
}
System.exit(0);
Problem:
if (rsl.next())
fix:
while (rsl.next())
Debug the app and check if the your connection to the database is valid.
When you execute an executeUpdate on your statement an int is returned and most importantly your result set object rs1 from your query gets closed and can't be accessed anymore since the Statement class only handles one query/result set. I haven't tested this myself but I am pretty sure this is the reason.
The solution is to have a separate Statement object for the update/delete so that the original ResultSet is not affected. Something like below
Statement stmt = conn.createStatement();
Statement updStmt = conn.createStatement();
ResultSet rsl = stmt.executeQuery("SELECT * FROM keranjang WHERE pemesan='"+login.userid+"'");
while (rsl.next()) {
String nb = rsl.getString("nama_barang");
String dtl = rsl.getString("detail");
String beratt = rsl.getString("berat");
String hrga = rsl.getString("harga");
String jmlh = rsl.getString("jumlah");
updStmt.executeUpdate("UPDATE barang SET stok=stok+'"+jmlh+"' WHERE nama_barang='"+nb+"' AND detail='"+dtl+"' AND berat='"+beratt+"'");
updStmt.executeUpdate("DELETE FROM keranjang WHERE pemesan ='"+login.userid+"' AND nama_barang='"+nb+"'");
}
If I've understood your problem correctly, there are two possible problems here:
the resultset is null - I assume that this cant be the case as if it was you'd get an exception in your while loop and nothing would be output
the second problem is that resultset.getString(i++) will get columns 1,2,3 and so on from each subsequent row
I think that the second point is probably your problem here.
Let us say you only had 1 row returned, as follows
Col 1, Col 2, Col3
A , B, C
Your code as it stands would only get A - it wouldn't get the rest of the columns.
I suggest you change your code as follows:
ResultSet resultset = ...;
ArrayList<String> arrayList = new ArrayList<String>();
while (resultset.next()) {
int i = 1;
while(i <= numberOfColumns) {
arrayList.add(resultset.getString(i++));
}
System.out.println(resultset.getString("Col 1"));
System.out.println(resultset.getString("Col 2"));
System.out.println(resultset.getString("Col 3"));
System.out.println(resultset.getString("Col n"));
}
To get the number of columns:
ResultSetMetaData metadata = resultset.getMetaData();
int numberOfColumns = metadata.getColumnCount();

How sql works and why this result is returned?

Hi I'm using preparedStatement in Java to execute query in DB.
The table:
When it comes to update, delete and insert it's all fine, however when it comes to select( ex. I've done "SELECT ?,?,?,?,? from person" and set strings afterwards) and the following result is returned:
I'm assuming that because it's the strings that are replacing ? so it did not come out as expected:(please correct me if it's wrong)
Expected sql: "SELECT no,name,tel,birthday,address FROM person"
Actual sql: "SELECT \"no\",\"name\",\"birthday\",\"address\" FROM person"
I've tested the second one in in Navicat:
I'd like to understand that why executing this query statement would return a result like this?
If it would help here's Java code:
// Data Assist Object
public class DAO {
static String jdbcurl;
static String username;
static String password;
static{
try {
Class.forName("com.mysql.jdbc.Driver");
ResourceBundle rb = ResourceBundle.getBundle("db");
jdbcurl = rb.getString("jdbcurl");
username = rb.getString("username");
password = rb.getString("password");
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
}
}
// for insert, delete and update
public int modify(String sql, String[] args){
int x=0;
try(Connection con = DriverManager.getConnection( jdbcurl,username ,password);
PreparedStatement ps = con.prepareStatement(sql);){
for (int i = 0; i < args.length; i++) {
ps.setString(i+1, args[i]);
}
x =ps.executeUpdate();
System.out.println(x);
}catch(SQLException e){
e.printStackTrace();
}
return x;
}
// for select
public List<Map<String,String>> query(String sql, String[] params){
List<Map<String,String>> resList = new ArrayList<>();
try(Connection con = DriverManager.getConnection( jdbcurl,username ,password);
PreparedStatement ps = con.prepareStatement(sql);){
for (int i = 0; i < params.length; i++) {
ps.setString(i+1, params[i]);
}
try(ResultSet res =ps.executeQuery();){
ResultSetMetaData mdata = res.getMetaData();
int num = mdata.getColumnCount();
while(res.next()){
HashMap<String,String> data = new HashMap<>();
for (int i = 1; i <= num; i++) {
String result = res.getString(i);
String columnName = mdata.getColumnName(i);
data.put(columnName,result);
}
resList.add(data);
}
}
}catch(Exception e){
e.printStackTrace();
}
return resList;
}
public static void main(String[] args) throws SQLException {
DAO dao = new DAO();
String sql = "insert into person(name,tel,birthday,address) values(?,?,?,?)";
sql = "select ?,?,?,?,? from person";
List<Map<String,String>> res = dao.query(sql, new String[]{"no","name","tel","birthday","address"});
for(Map m:res){
System.out.print("no: "+m.get("no")+",");
System.out.print("name: "+m.get("name")+",");
System.out.print("tel: "+m.get("tel")+",");
System.out.print("birthday: "+m.get("birthday")+",");
System.out.println("address: "+m.get("address"));
}
}
}
Thanks for any help.
SQL basically works on a show me these columns where this criteria is true basis.
In the statement:
"SELECT \"no\",\"name\",\"birthday\",\"address\" FROM person"
You're getting
SELECT "no", "name", "birthday", "address" FROM person
when it actually hits the database. The "" operator creates a string in SQL. In plain English, that means that you're telling the database to return that specified set of strings for each row in person where the criteria you listed is met.
Since you didn't list a where clause, all rows are true by default so you get one row of strings for every single row in the person table. The first query is the same thing, but instead of directly passing the strings, you're adding them in as bind variables.
If you actually want to see the values in the table, write the query without the "'s
SELECT no, name, birthday, address FROM person
Unless otherwise specified, bind functions generally pass the value as a string. Which is why the query behaved the way it did. I don't recommend using bind variables in the select clause. That's a strange practice.
Edit:
As Adrian pointed out in the comments, " denotes columns in SQL. My apologies for not catching that. I assume that you meant to use the ' operator which actually denotes strings.
If not, something else is going on here entirely.
For the select you use the question marks in the WHERE clause, not where you list the fields you need as output.
Replace
sql = "select ?,?,?,?,? from person";
with
sql = "select no,name,tel,birthday,address from person";
For this particular query there is no binding to do. It will retrieve all the records from the table.

ArrayList in SQL IN query throwing memory location instead of Strings [duplicate]

This question already has an answer here:
Passing an Array to a SQL query using Java's PreparedStatement
(1 answer)
Closed 7 years ago.
I am using mySQL JDBC driver in my java program. I want to pass a ArrayList in the IN clause in my SQL query.
i did use a prepared statement like this, but this throws an
"java.sql.SQLFeatureNotSupportedException"exception
since mysql doesn't support this.
ArrayList<String> list = new ArrayList<String>();
PreparedStatement pstmt =
conn.prepareStatement("select * from employee where id in (?)");
Array array = conn.createArrayOf("VARCHAR", list.toArray());
pstmt.setArray(1, array);
ResultSet rs = pstmt.executeQuery();
Is there any other way to do this ? Maybe with Statement stmt.
Build the SQL statement with the correct number of markers, and set all the values.
Beware: Databases have a limit to the number of parameters allowed, though it's very high for MySQL (65535).
char[] markers = new char[list.size() * 2 - 1];
for (int i = 0; i < markers.length; i++)
markers[i] = (i & 1 == 0 ? '?' : ',');
String sql = "select * from employee where id in (" + markers + ")";
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
int idx = 1;
for (String value : list)
stmt.setString(idx++, value);
try (ResultSet rs = stmt.executeQuery()) {
while (rs.next()) {
// code here
}
}
}

JAVA sql NOT IN list statement

Am trying to select record from database where record id NOT IN list.
take a look # my problem below.
String Sqlids = "2,6,3,9"; // this is dynamic so the number of element is unknown
String str= "SELECT TOP 1 * FROM student WHERE ID NOT IN (2,6,3,9) ORDER BY NEWID()";
PreparedStatement stat = con.prepareStatement(str);
ResultSet rs = stat.executeQuery();
The above statement work FINE, but if i change it to
String Sqlids = "2,6,3,9";
String str= "SELECT TOP 1 * FROM student WHERE ID NOT IN (Sqlids) ORDER BY NEWID()";
PreparedStatement stat = con.prepareStatement(str);
ResultSet rs = stat.executeQuery();
//i also try this
String Sqlids = "2,6,3,9";
String str= "SELECT TOP 1 * FROM student WHERE ID NOT IN (?) ORDER BY NEWID()";
PreparedStatement stat = con.prepareStatement(str);
stat.setString(1,Sqlids );
ResultSet rs = stat.executeQuery();
THE ABOVE STATEMENT DOESN'T FILTER
Since Sqlids is one string is seeing it as one parameter so it return repeated rows, is there an integer format for storing values like 2,6,3,9 ?
since the Sqlids is from an arraylist called SqlidList
i try somtin like this
Iterator iTr = SqlidList.iterator();
while(iTr.hasNext()){
stat.setString(1,iTr.next().toString()+",");
}
but the setString(1,--) is not available since is in a while loop
Use Connection#createArrayOf after converting your ids to a String[]
String[] ids = {"2", "6", "3", "9"};
String str= "SELECT TOP 1 * FROM student WHERE ID NOT IN ? ORDER BY NEWID()";
PreparedStatement stat = con.prepareStatement(str);
stat.setArray(1, con.createArrayOf("text",ids));
ResultSet rs = stat.executeQuery();
If createArrayOf is not supported by your JDBC driver (as in this case) I'd probably just construct the query string in place e.g:
String Sqlids = "2,6,3,9";
String str= "SELECT TOP 1 * FROM student WHERE ID NOT IN ("+Sqlids+") ORDER BY NEWID()";
or if you have a collection of ids use a utility method to create the array content:
public static String toSqlArray(List<String> strings) {
StringBuilder sb = new StringBuilder();
boolean doneOne = false;
for(String str: strings){
if(doneOne){
sb.append(", ");
}
sb.append("'").append(str).append("'");
doneOne = true;
}
return sb.toString();
}
The way I've solved the problem is :
SQL = "...WHERE ID NOT IN ({0}) ..."
have a method which builds a string containing a number of ? equal to the size of SqlidList
public static String buildQuestionMarks(final int count) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < count; i++) {
sb.append("?" + ",");
}
return sb.substring(0, sb.length() - 1);
}
use java.text.MessageFormat.format() to insert the list of ? into the sql
String finalSql = MessageFormat.format(SQL, questionMarksString);
have a method to set the params on teh prepared statement. Something similar to what you wrote although you need to increment the first parameter of stat.setString()
This should work for variable number of parameters.
Did you tried using
int[] array = {2,6,3,9};
String str= "SELECT TOP 1 * FROM student WHERE ID NOT IN (?,?,?,?) ORDER BY NEWID()";
PreparedStatement stat = con.prepareStatement(str);
for(int i = 1; i <= array.length; i++)
stat.setString(i,array[i - 1]);
ResultSet rs = stat.executeQuery();

Categories

Resources