Dynamic Sql qyery using prepare statement - java

Hii i want to create a dynamic query for filtering products. I want filter product from PRODUCTS table
on the basis of certain parameters like
Brand
Flavour
Price
Size
Type
i am creating a function in which i am executing MySQL query i want to check which parameter user has used which parameter is used those value will not be null and rest of the not selected parameters will be null. so i am checking the function which is null which is not and passing them in query
I have tried the following code
but it shows null pointer execption with following message
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 '' at line 1
and u tried printing the query:
SELECT * FROM products WHERE 1=1 AND brand in (?,? AND Price < ? AND Size < ? AND Type = ?
Follwing is the code:
public List<Products> Filter_Itemsl(String[] Brand, String[] Flavour, float Price, float Size, String Type) {
List<Object> parameters = new ArrayList<Object>();
ResultSet rs;
List<Products> data = null;
PreparedStatement stmt;
try {
StringBuilder query = new StringBuilder("SELECT * FROM products WHERE 1=1");
if (Brand != null) {
query.append(" AND brand in (");
for (int i = 0; i < Brand.length; i++) {
query.append('?');
if (i < Brand.length - 1) {
query.append(',');
}
parameters.add(Brand[i]);
}
}
if (Flavour != null) {
query.append(" AND Flavour in (");
for (int i = 0; i < Brand.length; i++) {
query.append('?');
if (i < Flavour.length - 1) {
query.append(',');
}
parameters.add(Flavour[i]);
}
}
if (Price != 0) {
query.append(" AND Price < ?");
parameters.add(Price);
}
if (Size != 0) {
query.append(" AND Size < ?");
parameters.add(Size);
}
if (Type != null) {
query.append(" AND Type = ?");
parameters.add(Type);
}
String Query = query.toString();
System.out.println(Query);
stmt = DataBaseConnection.DBConn.getConnection().prepareStatement(Query);
int i = 1;
for (Object parameter : parameters) {
stmt.setObject(i++, parameter);
}
rs = stmt.executeQuery();
if (rs != null) {
data = new ArrayList<Products>();
while (rs.next()) {
Products p = new Products();
p.setTitle(rs.getString("Ttile"));
p.setCategory(rs.getString("Category"));
p.setSubCategory(rs.getString("SubCategory"));
p.setSubCategoryTwo(rs.getString("SubCategorytwo"));
p.setPrice(rs.getInt("Price"));
p.setFlavour(rs.getString("Flavour"));
p.setSize(rs.getFloat("Size"));
p.setImage(rs.getString("image"));
p.setBrand(rs.getString("Brand"));
p.setInstock(rs.getString("instock"));
p.setInstockQty(rs.getInt("instockqty"));
p.setType(rs.getString("Type"));
data.add(p);
}
}
} catch (Exception e) {
System.out.println(e.getStackTrace());
System.out.println("----------------------");
System.out.println(e.getMessage());
System.out.println("----------------------");
System.out.println(e.getSuppressed());
System.out.println("----------------------");
e.printStackTrace();
return null;
}
return data;
}

You are missing the closing ) for every IN sql statement.

You need to close the bracket after the for loop
if (Flavour != null) {
query.append(" AND Flavour in (");
for (int i = 0; i < Brand.length; i++) {
query.append('?');
if (i < Flavour.length - 1) {
query.append(',');
}
parameters.add(Flavour[i]);
}
query.append(")");
}

Related

How to frame sql queries in java without SQL injection vulnerability? [duplicate]

I am preparing a SQL statement from values passed through a query string. ( I am using the Play! framework. Basically what I'm running into (not really an issue just something I don't like very much) is that when I want to use ? in the SQL string and set them later with dynamic values.
This is what I have:
String sql = "SELECT * FROM foobar_table WHERE";
if ( foo != 0 )
sql += " AND foo=?";
if ( !bar )
sql += " AND bar=?";
try{
PreparedStatement getStmt = con.prepareStatement(sql);
if ( foo != 0 )
getStmt.setInt(1,foo);
if ( foo != 0 && !bar )
getStmt.setBoolean(2, bar);
else
getStmt.setBoolean(1, bar);
} catch (SQLException e ){
e.printStackTrace();
}
This does work but as you can see not very intuitive. It's OK when there are 2 dynamic values but when you get up to 5 or 6 this would just get ridiculous.
Is there an easier way of doing this to make it more flexible so that I would know how to fill in all the ? in a better fashion?
An example (was too long for comment):
String sql = "SELECT * FROM foobar_table WHERE 1 = 1 ";
ArrayList paramList = new ArrayList();
if ( foo != 0 ) {
sql += " AND foo=?";
paramList.add(foo);
}
if ( !bar ) {
sql += " AND bar=?";
paramList.add(bar);
}
try{
PreparedStatement getStmt = con.prepareStatement(sql);
int index = 1;
for (Object param : paramList) {
getStmt.setObject(index, param);
index++;
}
// execute
} catch (SQLException e ){
e.printStackTrace();
}
Something like this maybe (just rough code but you get the idea):
class Param{
final int type;
final Object value;
Param(int type, Object value){
this.type = type;
this.value = value;
}
}
final List<Param> params = new ArrayList<>();
final StringBuilder sql = new StringBuilder("SELECT * FROM bcu_venue_events WHERE 1=1");
int foo = 0;
boolean bar = true;
if (foo != 0){
sql.append(" AND foo=?");
params.add(new Param(Types.INTEGER, foo));
}
if (!bar){
sql.append(" AND bar=?");
params.add(new Param(Types.BOOLEAN, bar));
}
try(Connection conn = null; PreparedStatement getStmt = conn.prepareStatement(sql.toString())) {
for(int i = 0; i < params.size(); i++){
Param p = params.get(i);
getStmt.setObject(i + 1, p.value, p.type);
}
} catch (SQLException e) {
e.printStackTrace();
}
How about this:
String sql = "SELECT * FROM foobar_table WHERE 1=1";
if ( foo != 0 )
sql += " AND foo=" + foo;
if ( !bar )
sql += " AND bar=" + bar;
try{
PreparedStatement getStmt = con.prepareStatement(sql);
} catch (SQLException e ){
e.printStackTrace();
}

read cassandra data by paging doesn't work

I try to read cassandra data by paging, but it doesn't work. My codes are as below. I got the same content for every page. Anything I missed ?
// Persist the entity objects
for (int i=0; i<1000; i++) {
// change person1's id
personObj1.setPersonId("haofan" + i);
dataServiceClient.persist(personObj1);
}
Query query;
List<Person> personList;
// Create and execute SELECT * query
for (int i =0; i<10; i++) {
String cqlString = "Select p from Person p";
// String cqlString = "Select p from Person p";
query = dataServiceClient.createQuery(cqlString).setMaxResults(100).setFirstResult(i*100);
personList = query.getResultList();
// Get the same personId for every page.
Assert.assertEquals(100, personList.size());
System.out.println("haofan for: " + personList.get(10).getPersonId());
}
You are looking for offset queries there is no support on Cassandra natively.
I try multi solution, finally it works for me as below solution. Refer: https://docs.datastax.com/en/developer/java-driver/3.6/manual/paging/
public String paging(Session session, String pageState) {
Statement statement = new SimpleStatement("SELECT * FROM testkeyspace.\"PERSON\"");
statement.setFetchSize(3);
if (pageState != null) {
statement.setPagingState( PagingState.fromString(pageState));
}
ResultSet rs = session.execute(statement);
int remaining = rs.getAvailableWithoutFetching();
System.out.println("remaining " + remaining);
for (Row row : rs) {
System.out.println("first" + row);
if (--remaining == 0) {
break;
}
}
return rs.getExecutionInfo().getPagingState().toString();
}
How to use this function:
#Test
#Category(DataServiceRequired.class)
public void pagingTest() throws Exception {
Cluster cluster = Cluster.builder().addContactPoint("localhost").withPort(9042).build();
Session session = cluster.connect();
String pageState = paging(session, null);
paging(session, pageState);
}

How to customize the TotalRecordCount and Paging after filter in jTable jquery (Java-JSP)

I use a jTable jquery for jsp page, it work very well. It can display the showing count records in bottom right of table well (e.g. Showing 1-10 of 22). When I insert the Filtering into the page, the showing count record is not correctly.
I follow this for Filtering: http://www.jtable.org/Demo/Filtering
How to customize the code for showing count record (I use java-jsp and sql server). Sorry for my English language :))
Here is the code I am using right now in controller.
if (action.equals("list")) {
try {
int startPageIndex = Integer.parseInt(request.getParameter("jtStartIndex"));
int numRecordsPerPage = Integer.parseInt(request.getParameter("jtPageSize"));
String jtSorting = null;
//Fetch Data from Rejected_Product Table
lstSite = dao.**getAllSite**(filter_site, startPageIndex, numRecordsPerPage, jtSorting);
//Get Total Record Count for Pagination
int siteCount = dao.**getSiteCount**();
//Convert Java Object to Json
Gson gson = new Gson();
JsonElement element = gson.toJsonTree(lstSite, new TypeToken<List<Site>>() {
}.getType());
JsonArray jsonArray = element.getAsJsonArray();
String listData = jsonArray.toString();
//Return Json in the format required by jTable plugin
listData = "{\"Result\":\"OK\",\"Records\":"+listData+",\"TotalRecordCount\":"+siteCount+"}";
response.getWriter().print(listData);
System.out.println(listData);
} catch (Exception ex) {
String error = "{\"Result\":\"ERROR\",\"Message\":" + ex.getStackTrace() + "}";
response.getWriter().print(error);
ex.printStackTrace();
}
}
and here method getAllSite:
public List<Site> getAllSite (FilterSite filter_site, int jtStartIndex, int jtPageSize, String jtSorting) {
List<Site> siteList = new ArrayList<Site>();
String query = "";
String siteQ = filter_site.getSite();
String clientQ = filter_site.getClient(); // wait
String locationQ = filter_site.getLocation();
if (locationQ.isEmpty()) {
locationQ = "";
} else {
locationQ = "and location like '%"+locationQ+"' ";
}
String site_idQ = filter_site.getSite_id();
if (site_idQ.isEmpty()) {
site_idQ = "";
} else {
site_idQ = "and site_id = '"+site_idQ+"' ";
}
String divisionQ = filter_site.getDivision();
if (divisionQ.isEmpty()) {
divisionQ = "";
} else {
divisionQ = "and division = '"+divisionQ+"' ";
}
int range = jtStartIndex+jtPageSize;
query = "SELECT * FROM (SELECT *, ROW_NUMBER() OVER (ORDER BY CODE) as row FROM [site]) a "
+ "WHERE (code like '%"+siteQ+"' "+locationQ+site_idQ+divisionQ+") "
+ "and row > "+jtStartIndex+" and row <= "+range;
try {
Statement statement = connection.createStatement();
ResultSet rs = statement.executeQuery(query);
System.out.println("query : "+query);
while (rs.next()) {
Site sitebean = new Site();
sitebean.setName(rs.getString("name"));
sitebean.setCode(rs.getString("code"));
.....
siteList.add(sitebean);
}
} catch (SQLException e) {
e.printStackTrace();
}
return siteList;
}
and here method getSiteCount :
public int getSiteCount () {
int count = 0;
String query = "SELECT COUNT(*) as count FROM [site] ";
try {
Statement statement = connection.createStatement();
ResultSet rs = statement.executeQuery(query);
while (rs.next()) {
count = rs.getInt("count");
}
} catch (SQLException e) {
e.printStackTrace();
}
return count;
}
If you mean by "not correctly" that the row count is larger than expected, then the solution would be to include the where clause in the siteCount query.
WHERE (code like '%"+siteQ+"' "+locationQ+site_idQ+divisionQ+")

prepare statement is not succesful in case of query is having subQuery

i am using below simple query to get the result for testing purpose.
qName = "select total_requests from (select 10000 as total_requests from dual)"; //this can be dynamic query
preStatement = connection.prepareStatement(qName);
ParameterMetaData pmd = preStatement.getParameterMetaData();
int stmtCount = pmd.getParameterCount();
int paramsCount = params == null ? 0 : params.length;
for (int i = 0; i < params.length; i++) {
if (params[i] != null) {
preStatement.setObject(i + 1, params[i]);
} else {
int sqlType = Types.VARCHAR;
if (!paramValid) {
try {
sqlType = pmd.getParameterType(i + 1);
} catch (SQLException e) {
paramValid = true;
}
}
preStatement.setNull(i + 1, sqlType);
}
}
ResultSet rs = preStatement.executeQuery();
once i am executing 3rd line, below error is thrown by application
Caused by: java.lang.AbstractMethodError: com.inet.pool.b.getParameterMetaData()Ljava/sql/ParameterMetaData;
at com.core.admin.util.AnalyzeHelper.fillQuery(AnalyzeHelper.java:61)
is this due to subQuery issue?
how to resolve this?
use this for executing query
preStatement.executeQuery();
you need to have a result set for viewing
ResultSet rs=preStatement.executeQuery();
while(rs.next())
{
rs.getString(1);// I assume that first column is a String.If it is an INT then use rs.getInt(1);
//similarly for other columns
}
It may helps you.
qName = "select total_requests from (select 10000 as total_requests from dual)";
preStatement = connection.prepareStatement(qName);
ResultSet rs= preStatement.executeQuery();

The proper way to prepare a dynamic Statement in Java

I am preparing a SQL statement from values passed through a query string. ( I am using the Play! framework. Basically what I'm running into (not really an issue just something I don't like very much) is that when I want to use ? in the SQL string and set them later with dynamic values.
This is what I have:
String sql = "SELECT * FROM foobar_table WHERE";
if ( foo != 0 )
sql += " AND foo=?";
if ( !bar )
sql += " AND bar=?";
try{
PreparedStatement getStmt = con.prepareStatement(sql);
if ( foo != 0 )
getStmt.setInt(1,foo);
if ( foo != 0 && !bar )
getStmt.setBoolean(2, bar);
else
getStmt.setBoolean(1, bar);
} catch (SQLException e ){
e.printStackTrace();
}
This does work but as you can see not very intuitive. It's OK when there are 2 dynamic values but when you get up to 5 or 6 this would just get ridiculous.
Is there an easier way of doing this to make it more flexible so that I would know how to fill in all the ? in a better fashion?
An example (was too long for comment):
String sql = "SELECT * FROM foobar_table WHERE 1 = 1 ";
ArrayList paramList = new ArrayList();
if ( foo != 0 ) {
sql += " AND foo=?";
paramList.add(foo);
}
if ( !bar ) {
sql += " AND bar=?";
paramList.add(bar);
}
try{
PreparedStatement getStmt = con.prepareStatement(sql);
int index = 1;
for (Object param : paramList) {
getStmt.setObject(index, param);
index++;
}
// execute
} catch (SQLException e ){
e.printStackTrace();
}
Something like this maybe (just rough code but you get the idea):
class Param{
final int type;
final Object value;
Param(int type, Object value){
this.type = type;
this.value = value;
}
}
final List<Param> params = new ArrayList<>();
final StringBuilder sql = new StringBuilder("SELECT * FROM bcu_venue_events WHERE 1=1");
int foo = 0;
boolean bar = true;
if (foo != 0){
sql.append(" AND foo=?");
params.add(new Param(Types.INTEGER, foo));
}
if (!bar){
sql.append(" AND bar=?");
params.add(new Param(Types.BOOLEAN, bar));
}
try(Connection conn = null; PreparedStatement getStmt = conn.prepareStatement(sql.toString())) {
for(int i = 0; i < params.size(); i++){
Param p = params.get(i);
getStmt.setObject(i + 1, p.value, p.type);
}
} catch (SQLException e) {
e.printStackTrace();
}
How about this:
String sql = "SELECT * FROM foobar_table WHERE 1=1";
if ( foo != 0 )
sql += " AND foo=" + foo;
if ( !bar )
sql += " AND bar=" + bar;
try{
PreparedStatement getStmt = con.prepareStatement(sql);
} catch (SQLException e ){
e.printStackTrace();
}

Categories