Simple query with variable parameters - java

I have three queries which I would like to consolidate into one query which can accept a variable length of WHERE arguments; I cannot remember for the life of me how to do this.
PreparedStatement queryOne = connection.prepareStatement
("SELECT columnOne, columnTwo, columnThree FROM tableOne WHERE columnOne = ?;" );
PreparedStatement queryTwo = connection.prepareStatement
("SELECT columnOne, columnTwo, columnThree FROM tableOne WHERE columnTwo = ?;" );
PreparedStatement queryThree = connection.prepareStatement
("SELECT columnOne, columnTwo, columnThree FROM tableOne WHERE columnOne = ? AND columnTwo = ?;" );

All three queries select the same columns from the same table, so their union can be easily done in one statement:
SELECT columnOne, columnTwo, columnThree
FROM tableOne
WHERE columnOne = ?
or columnTwo = ?
or (columnOne = ? AND columnTwo = ?)

Answered my own question, feel free to chime in on whether this is bad practice or not.
String columnOne = getValue();
String columnTwo = getValue();
String queryString = "SELECT columnOne, columnTwo, columnThree FROM tableOne"
if (columnOne != null && columnTwo != null)
queryString = queryString + "WHERE columnOne = ? AND columnTwo = ?"
else if (columnOne != null)
queryString = queryString + "WHERE columnOne = ?"
else if (columnTwo != null)
queryString = queryString + "WHERE columnTwo = ?"
PreparedStatement query = connection.prepareStatement(queryString);

Related

set value = 0 while updating record in jsp

im trying to update a column using jsp
here i want my count column value to be updated as zero
count = 0
how can i do that. through this code value is not updating
String code = request.getParameter("code");
Connection conn = null;
Statement st=null;
ResultSet rs = null;
PreparedStatement ps = null;
int count = 0;
try{
conn = DataBaseConnection.initializeDatabase();
String query1 = null;
conn.setAutoCommit(false);
query1 = "update employee set count = ? where code= ' +code+' ";
ps = conn.prepareStatement(query1);
ps.setInt(1, count);
ps.executeUpdate();
}
catch (Exception e) {
e.printStackTrace();
}
here is my record in db
employee table
CODE VARCHAR2(12)
COUNT NUMBER(3)
You can replace
"update employee set count = ? where code= ' +code+' ";
with
"update employee set count = ? where code= '" + code + "'";
e.g. if the value of code is xyz then after this change, the query will become:
"update employee set count = ? where code= 'xyz'";
However, I recommend you do it as follows to avoid the SQL Injection:
query1 = "update employee set count = ? where code= ?";
ps = conn.prepareStatement(query1);
ps.setInt(1, count);
ps.setString(2, code);

sql for paging notice board in jsp

I'm trying to make a notice board and before apply paging function it showed posts well.
but after i applied paging fuction it shows only one post and paging function shows pages well.
so i think this is a sql problem.
when i try to show count it shows 1. even i tried with this shows 1.
sql = "select * from mvc_board ";
this is my sql
String sql = "SELECT ROWNUM, bId, bName, bTitle, bContent," +
"bDate, bHit, bGroup, bStep, bIndent " +
"from(select * from mvc_board order by bGroup DESC , bStep asc)";
i tried to make mine from this sql. but couldn't understand.
sql = "select *, (select u_name from user where idx = writer_fk) writer, (select idx from answer where idx = answer_fk) answer from board order by idx desc limit "+startRow+", "+endRow;
ref. http://queserasera.tistory.com/14
this is DAO
public ArrayList<BDto> getBoardList(int startRow, int endRow, String keyField, String keyWord) {
ArrayList<BDto> dtos = new ArrayList<BDto>();
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
String sql = "SELECT ROWNUM, bId, bName, bTitle, bContent," +
"bDate, bHit, bGroup, bStep, bIndent " +
"from(select * from mvc_board order by bGroup DESC , bStep asc)";
System.out.println(sql);
try{
if(keyWord != null && !keyWord.equals("") && !keyWord.equals("null")) {
sql += " WHERE " + keyField.trim() +" LIKE '%"+keyWord.trim()+"%'";
}
connection = dataSource.getConnection();
//특정행부터 레코드를 가져오기 위해서 옵션 설정
preparedStatement = connection.prepareStatement(sql);
resultSet = preparedStatement.executeQuery();
while(resultSet.next()){
int count=0;
int ROWNUM = resultSet.getInt("ROWNUM");
int bId = resultSet.getInt("bId");
String bName = resultSet.getString("bName");
String bTitle = resultSet.getString("bTitle");
String bContent = resultSet.getString("bContent");
Timestamp bDate = resultSet.getTimestamp("bDate");
int bHit = resultSet.getInt("bHit");
int bGroup = resultSet.getInt("bGroup");
int bStep = resultSet.getInt("bStep");
int bIndent = resultSet.getInt("bIndent");
BDto dto = new BDto(ROWNUM, bId, bName, bTitle, bContent, bDate, bHit, bGroup, bStep, bIndent);
dtos.add(dto);
count++;
System.out.println(count);
//while문끝
}//if문끝
}catch (Exception e) {
System.out.println(e+"=> getBoardList fail");
}finally {
try {
if(resultSet != null) resultSet.close();
if(preparedStatement != null) preparedStatement.close();
if(connection != null) connection.close();
} catch (Exception e2) {
// TODO: handle exception
e2.printStackTrace();
}
}
return dtos;
}
=============added sql on sql developer==================================
select rn, bId, bName, bTitle, bContent, bDate, bHit, bGroup, bStep, bIndent
from ( select b.*, row_number() over (order by bGroup DESC, bStep asc) rn
from mvc_board b %s )
where rn between 1 and 10
order by rn;
The main problem in your getBoardList() method was the usage of if (resultSet.next()) instead of while (resultSet.next()) when iterating through the result set; that caused the code to only ever return a single DTO.
There are other things you should also consider. For example, starting from Java 7, it's preferrable to use the try-with resources statement instead of traditional try-finally for JDBC resource handling.
An important thing to note is that injecting field names like keyField from the UI is a really bad practice because it makes the query vulnerable to SQL injection.
You should at least create a static whitelist of allowed field names to sanitize the input, if you cannot use static WHERE conditions.
Finally, paging queries in Oracle 11g are traditionally done with an inline view that uses the row_number analytic function. Note that row-numbering starts from 1. Starting from Oracle 12c, the row-limiting clause can be used and the inline view is no longer needed.
An example implementation that considers the above points could look like the following:
public List<BDto> getBoardList(int startRow, int endRow, String keyField, String keyWord) {
List<BDto> dtos = new ArrayList<BDto>();
// the %s in the template will be replaced with a
// WHERE condition when a keyword is present
final String sqlTemplate = "select rn, bId, bName, bTitle, "
+ "bContent, bDate, bHit, bGroup, bStep, bIndent "
+ "from ( "
+ " select b.*, row_number() over (order by bGroup DESC, bStep asc) rn"
+ " from mvc_board b %s "
+ " ) "
+ " where rn between ? and ? "
+ "order by rn";
boolean whereCondition = false;
String sql = null;
if (keyWord != null && !keyWord.equals("") && !keyWord.equals("null")) {
sql = String.format(sqlTemplate,
" WHERE " + keyField.trim() + " LIKE '%' || ? || '%'");
whereCondition = true;
} else {
sql = String.format(sqlTemplate, "");
}
System.out.println(sql);
try (Connection connection = dataSource.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement(sql)) {
int parameterIndex = 1;
if (whereCondition) {
preparedStatement.setString(parameterIndex++, keyWord);
}
preparedStatement.setInt(parameterIndex++, startRow);
preparedStatement.setInt(parameterIndex, endRow);
try (ResultSet resultSet = preparedStatement.executeQuery()) {
int count = 0;
while (resultSet.next()) {
int ROWNUM = resultSet.getInt("rn");
int bId = resultSet.getInt("bId");
String bName = resultSet.getString("bName");
String bTitle = resultSet.getString("bTitle");
String bContent = resultSet.getString("bContent");
Timestamp bDate = resultSet.getTimestamp("bDate");
int bHit = resultSet.getInt("bHit");
int bGroup = resultSet.getInt("bGroup");
int bStep = resultSet.getInt("bStep");
int bIndent = resultSet.getInt("bIndent");
dtos.add(new BDto(ROWNUM, bId, bName, bTitle,
bContent, bDate, bHit, bGroup, bStep, bIndent));
count++;
}
System.out.println(count);
}
} catch (SQLException e) {
System.out.println(e + "=> getBoardList fail");
}
return dtos;
}
In the example you gave us the paging is added by the limit clause, but ORACLEhas it's own syntax for these. Try:
String sql = "SELECT rown, bId, bName, bTitle, bContent," +
"bDate, bHit, bGroup, bStep, bIndent " +
"from(select rownum rown, mvc_board.* from mvc_board order by bGroup DESC , bStep asc) " +
"WHERE rown between ? and ? ";
Bind startRow and endRow before executing the query:
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1,startRow);
preparedStatement.setInt(2,endRow);
resultSet = preparedStatement.executeQuery();
Change the WHERE to AND:
sql +=" and " + keyField.trim()+" LIKE '%"+keyWord.trim()+"%'" ;
And finally change the if(resultSet.next()){ back to a while loop to get more then one row as result.

How to retrieve data in chunks using Pagination(Limit/offset) from a select query in this following example code? [duplicate]

This question already has answers here:
JDBC Pagination
(13 answers)
Closed 4 years ago.
I have an select sql query statement that returns 900000+ rows.But i want data to be retrieved in small chunks using limit/offset clause,so that it can be easily inserted into another table.
public class Snomedinfo {
public void snomedinfoinsert()
{
Root oRoot = null;
ResultSet oRsSelect = null;
PreparedStatement oPrStmt = null;
PreparedStatement oPrStmt2 = null;
PreparedStatement oPrStmtSelect = null;
String strSql = null;
int count=0;
int batchSize=1000;
ResultSet oRs = null;
String refid = null;
String id = null;
String effectivetime = null;
String active = null;
String moduleid = null;
String conceptid = null;
String languagecode = null;
String typeid = null;
String term = null;
String caseSignificanceid = null;
try{
oRoot = Root.createDbConnection(null);
strSql = "SELECT d.* FROM snomed_conceptdata c, snomed_descriptiondata d WHERE c.active = 1 and conceptid = c.id AND d.active = 1 ";//this is the query that returns 900000 rows
oPrStmt2 = oRoot.con.prepareStatement(strSql);
oRs = oPrStmt2.executeQuery();
String sql = "INSERT INTO snomedinfo_date (refid,id,effectivetime,active,moduleid,conceptid,languagecode,typeid,term,caseSignificanceid) VALUES( ?, ?, ?,?,?,?,?,?,?,?)";
oPrStmt = oRoot.con.prepareStatement(sql);
while (oRs.next())
{
refid = Root.TrimString(oRs.getString("refid"));
id = Root.TrimString(oRs.getString("id"));
effectivetime = Root.TrimString(oRs.getString("effectivetime"));
active = Root.TrimString(oRs.getString("active"));
moduleid = Root.TrimString(oRs.getString("moduleid"));
conceptid = Root.TrimString(oRs.getString("conceptid"));
languagecode = Root.TrimString(oRs.getString("languagecode"));
typeid = Root.TrimString(oRs.getString("typeid"));
term = Root.TrimString(oRs.getString("term"));
caseSignificanceid = Root.TrimString(oRs.getString("caseSignificanceid"));
oPrStmt.setString(1, refid);
oPrStmt.setString(2, id);
oPrStmt.setString(3, effectivetime);
oPrStmt.setString(4, active);
oPrStmt.setString(5, moduleid);
oPrStmt.setString(6, conceptid);
oPrStmt.setString(7, languagecode);
oPrStmt.setString(8, typeid );
oPrStmt.setString(9, term);
oPrStmt.setString(10, caseSignificanceid);
oPrStmt.addBatch();
if (++count % batchSize == 0) {
oPrStmt.executeBatch();
oPrStmt.clearBatch();
}
}
oPrStmt.executeBatch();
System.out.println("done");
}
catch (Exception e) {
e.printStackTrace();
}
finally {
oRs = Root.EcwCloseResultSet(oRs);
oPrStmt = Root.EcwClosePreparedStatement(oPrStmt);
oPrStmt = Root.EcwClosePreparedStatement(oPrStmt2);
oRoot = Root.closeDbConnection(null, oRoot);
}
}
How do i implement the logic for setting limit/offset in my program ??
I have an select sql query statement that returns 900000+ rows.But i want data to be retrieved in small chunks using limit/offset clause,so that it can be easily inserted into another table.
SELECT d.* FROM snomed_conceptdata c, snomed_descriptiondata d WHERE c.active = 1 and conceptid = c.id AND d.active = 1 limit offset,limit;
Offset - The row from which you want to start reading data.
Limit - The number of rows you want to read.
For example-
SELECT d.* FROM snomed_conceptdata c, snomed_descriptiondata d WHERE c.active = 1 and conceptid = c.id AND d.active = 1 limit 10,20;
If you are using this in a web page then you need pagination.
Otherwise use a simple loop like this -
for(int i=0;i<=(90000/100);i+=10){
strSql = " SELECT d.* FROM snomed_conceptdata c, snomed_descriptiondata d WHERE c.active = 1 and conceptid = c.id AND d.active = 1 limit "+i+",10";
// run other code
}
This offsets the pointer by 10 rows with each iteration.

sql Query builder in JPA query?

I've made a search tool in java.
String query = "SELECT * FROM Customer WHERE 1 = 1 ";
if (!firstname.isEmpty()) query += "AND cName = '" + firstname + "' ";
if (!lastname.isEmpty()) query += "AND cLastName = '" + lastname + "' ";
if (!epost.isEmpty()) query += "AND cEpost = '" + epost + "' ";
if (!phonenumber.isEmpty()) query += "AND cPhonenumber '" + phonenumber + "' ";
That ouput this if all of those paramerets has values:
SELECT * FROM Customer WHERE 1 = 1
AND cName = 'test'
AND cLastName = 'test1'
AND cEpost = 'test2'
AND cPhonenumber 'test3'
This way I can get better results by filling in more data, but i can still choose to not do.. I need a solution for JPA for this.. any tips?
Thanks!
EDIT: End result based on the answer below:
public static List<Customer> searchCustomersByParameters(String firstname, String lastname,
String epost, String phonenumber) {
String sql = "SELECT c FROM Customer c WHERE 1 = 1 ";
if (!firstname.isEmpty()) sql += "AND c.cName = :firstname ";
if (!lastname.isEmpty()) sql += "AND c.cLastName = :lastname ";
if (!epost.isEmpty()) sql += "AND c.cEpost = :epost ";
if (!phonenumber.isEmpty()) sql += "AND c.cPhonenumber = :phonenumber";
Query q = em.createQuery(sql);
if (!firstname.isEmpty()) q.setParameter("firstname", firstname);
if (!lastname.isEmpty()) q.setParameter("lastname", lastname);
if (!epost.isEmpty()) q.setParameter("epost", epost);
if (!phonenumber.isEmpty()) q.setParameter("phonenumber", phonenumber);
return q.getResultList();
}
While it is of course possible to create dynamic SQL using string concatenation as suggested in this answer, a more type safe and less risky (in terms of SQL injection) approach is to use the JPA criteria API
public static List<Customer> searchCustomersByParameters(String firstname, String lastname,
String epost, String phonenumber) {
var qb = em.getCriteriaBuilder();
var query = qb.createQuery(Customer.class);
var root = query.from(Customer.class);
query.select(root);
if (!firstname.isEmpty()) query.where(qb.equal(root.get("cName"), firstName));
if (!lastname.isEmpty()) query.where(qb.equal(root.get("cLastName"), lastname));
if (!epost.isEmpty()) query.where(qb.equal(root.get("cEpost "), epost ));
if (!phonenumber.isEmpty()) query.where(qb.equal(root.get("cPhonenumber "), phonenumber));
return em.createQuery(query).getResultList();
}
... or if you don't strictly need to use JPQL you could also use a third party SQL builder like jOOQ:
public static List<Customer> searchCustomersByParameters(String firstname, String lastname,
String epost, String phonenumber) {
return
ctx.selectFrom(CUSTOMER)
.where(!firstname.isEmpty() ? CUSTOMER.CNAME.eq(firstname) : noCondition())
.and(!lastname.isEmpty() ? CUSTOMER.CLASTNAME.eq(lastname) : noCondition())
.and(!epost.isEmpty() ? CUSTOMER.CEPOST.eq(epost) : noCondition())
.and(!phonenumber.isEmpty() ? CUSTOMER.CPHONENUMBER.eq(phonenumber) : noCondition())
.fetchInto(Customer.class);
}
Disclaimer: I work for the company behind jOOQ
use ? and set Parameters for preventing sql injection and in JPA you can use native sql as old way you do and also JPQL.Generate your sql by conditions and set your parameters.I use here where 1=1 condition to easy append next conditions by and.Otherwise you will have difficulties for appending "where" to your sql.
by native:
public static List<YourEntity> getFromTable(String name,String surname) {
EntityManager em = PersistenceManager.instance().createEntityManager();
try {
String sql = " select * from table where 1=1 ";
if(name!=null && !name.trim().isEmpty()){
sql +=" and name = :name";
}
if(surname!=null && !surname.trim().isEmpty()){
sql +=" and surname = :surname";
}
Query q = em.createNativeQuery(sql);
if(name!=null && !name.trim().isEmpty()){
q.setParameter("name", name);
}
if(surname!=null && !surname.trim().isEmpty()){
q.setParameter("surname", surname);
}
List<YourEntity> l = q.getResultList();
return l;
} finally {
em.close();
}
}
By jpql:
public static List<YourEntity> getFromTable(String name,String surname) {
EntityManager em = PersistenceManager.instance().createEntityManager();
try {
String sql = " select e from YourEntity e where 1=1 ";
if(name!=null && !name.trim().isEmpty()){
sql +=" and e.name = :name";
}
if(surname!=null && !surname.trim().isEmpty()){
sql +=" and e.surname = :surname";
}
Query q = em.createQuery(sql);
if(name!=null && !name.trim().isEmpty()){
q.setParameter("name", name);
}
if(surname!=null && !surname.trim().isEmpty()){
q.setParameter("surname", surname);
}
List<YourEntity> l = q.getResultList();
return l;
} finally {
em.close();
}
}

SQL query in Java Code does not work properly

I have problem with SQL query in JAVA.
JAVA code:
public boolean zeKontrolaExistujiciZalohyTest(String datum) {
try {
connected();
boolean existujeZaloha = false;
int pocet;
ResultSet rs = statement.executeQuery("SELECT count(id) FROM "+table_ze+"\n" +
"WHERE TO_CHAR(TO_DATE(datum, 'dd.mm.yyyy'), 'mm.yyyy') = TO_CHAR(TO_DATE('"+datum+"', 'dd.mm.yyyy'), 'mm.yyyy')");
rs.next();
pocet = rs.getInt(1);
rs.close();
closed();
if (pocet >= 0) {
existujeZaloha = true;
} else {
existujeZaloha = false;
}
return existujeZaloha;
} catch (Exception e) {
e.printStackTrace();
Dialogs.create()
.title("Exception Dialog")
.showException(e);
return true;
}
}
SQL query in SQL Developer:
SELECT count(id) FROM pbtest.u_zalohy_energie
WHERE TO_CHAR(TO_DATE(datum, 'dd.mm.yyyy'), 'mm.yyyy') = TO_CHAR(TO_DATE('15.09.2014', 'dd.mm.yyyy'), 'mm.yyyy');
When I run JAVA code, so result a variable is "pocet = 0". But, when I run SQL query in any the SQL Developer, so result column COUNT(id) is "1".
When I do change the SQL query, let me run JAVA code retuns a variable "pocet = 1".
Change sql code:
ResultSet rs = statement.executeQuery("SELECT count(id) FROM "+table_ze+"\n" +
"WHERE datum = TO_DATE('"+datum+"', 'dd.mm.yyyy')");
Does anyone know where is the problem?
For information: I use an Oracle database.
Thank you.
datum is string
SELECT count(id)
FROM pbtest.u_zalohy_energie
WHERE TO_DATE(datum, 'dd.mm.yyyy') = TO_DATE('15.09.2014', 'dd.mm.yyyy');
datum is date
SELECT count(id)
FROM pbtest.u_zalohy_energie
WHERE TRUNC(datum) = TO_DATE('15.09.2014', 'dd.mm.yyyy');
If datum is date, it might contain time component too. So remove it. using TRUNC()
TRUNC(datum) = TO_DATE('15.09.2014', 'dd.mm.yyyy');
Java code:
ResultSet rs = statement.executeQuery("SELECT count(id) FROM "+table_ze+"\n" +
"WHERE TRUNC(datum) = TO_DATE('"+datum+"', 'dd.mm.yyyy')");
As a side note, use PreparedStatement and bind variables to avoid SQL*Injection
Your statement has a syntax error
ResultSet rs = statement.executeQuery("SELECT count(id) FROM "+table_ze+"\n" +
"WHERE TO_CHAR(TO_DATE(datum, 'dd.mm.yyyy'), 'mm.yyyy') = TO_CHAR(TO_DATE('"+datum+"', 'dd.mm.yyyy'), 'mm.yyyy')");
the executed query would be
SELECT count(id) FROM pbtest.u_zalohy_energie\nWHERE TO_CHAR(TO_DATE(datum, 'dd.mm.yyyy'), 'mm.yyyy') = TO_CHAR(TO_DATE('15.09.2014'', 'dd.mm.yyyy'), 'mm.yyyy')")
You should remove the "\n" as this will not lead in a line break.
Try it as
ResultSet rs = statement.executeQuery("SELECT count(id) FROM " + table_ze
+ " WHERE TO_CHAR(TO_DATE(datum, 'dd.mm.yyyy'), 'mm.yyyy') = TO_CHAR(TO_DATE('"+datum+"', 'dd.mm.yyyy'), 'mm.yyyy')");
Take also into consideration the comment from Maheswaran Ravisankar about: "... PreparedStatement and bind variables to avoid SQL*Injection"
Thank you for your advice, I solved the problem as follows:
public boolean zeKontrolaExistujiciZalohy(String datum, String typZalohy, String zalohaNaMesic) {
connected();
boolean existujeZaloha = false;
int pocet = 0;
ResultSet rs;
PreparedStatement pstmt = null;
try{
statement = connection.createStatement();
String SQL = "SELECT count(id) AS pocet FROM " + table_ze + " WHERE (EXTRACT(MONTH FROM datum)) = (EXTRACT(MONTH FROM to_date(?, 'dd.mm.yyyy'))) "
+ "AND (EXTRACT(YEAR FROM datum)) = (EXTRACT(YEAR FROM to_date(?, 'dd.mm.yyyy')))"
+ "AND typ_zalohy = ? "
+ "AND zaloha_na_mesic = ? ";
pstmt = connection.prepareStatement(SQL);
pstmt.setString(1, datum);
pstmt.setString(2, datum);
pstmt.setString(3, typZalohy);
pstmt.setString(4, zalohaNaMesic);
rs = pstmt.executeQuery();
while(rs.next()){
pocet = rs.getInt("pocet");
}
rs.close();
if (pocet > 0) {
existujeZaloha = true;
} else {
existujeZaloha = false;
}
return existujeZaloha;
}
catch(SQLException ex){
Dialogs.create()
.title("Exception Dialog")
.showException(ex);
return true;
}
}

Categories

Resources