Delete using NOT IN clause in HQL - java

I have a table issue_assigned having user_id as Integer and issue number as Varchar. The issues can be assigned to multiple users.
Now there is a condition if the issue is previously assigned to 3 users and then admin wants to assign it only to 2 users, The system should delete the 3rd user entry for that I wrote following code
String hql = "delete from issueAssigned where issueNumber=:issueNum AND assignedToUserId not in (:userIds)";
Query query = getHibernateTemplate().getSessionFactory().getCurrentSession().createQuery(hql);
query.setParameter("issueNum", issueNum);
query.setParameter("userIds", userIds);
if(query.executeUpdate() > 0){
return "success";
}else{
return "error";
}
userIds is a string which contain userId seperated by comma(,). When executed I get String cannot be caste to integer error.
How can i keep the required users and delete rest? What changes I will have to do?

userIds is a string which contain userId seperated by comma(,)
It shouldn't be. You should just pass an array or collection of user IDs. Hibernate will create the corresponding SQL prepared statement for you, by adding a parameter placeholder for each user ID.
And the parentheses around :userIds aren't needed either.

Instead of setParameter which take only one parameter you have to use setParameterList which take a Collection of parameters not String :
query.setParameterList("userIds", userIds);

Your query will be
String hql = "delete from issue_assigned where issue_number=:issueNum AND assigned_to_user_id not in :userIds";
and use query.setParameterList as follows
query.setParameterList("userIds", userIds);
hibernate will create the prepared statement using the collection passed.

Related

Distinct and List of other column in postgresql

I am using postgres DB and i have table with two column name and sal .
name Sal
Raunak 10000
Raunak 5000
Rahul 500
Raunak 300
And i want
Raunak 10000,5000,300
Rahul 500
i am using JPA is there any way to get in JPA data
You can use string_agg function to build a comma separated list of values:
select name, string_agg(sal::text, ',')
from t
group by name
You might want to consider json_agg instead of csv if your application can consume json data.
If you want to preserve the data type of the sal column, you can use array_agg() that returns an array of values. Not sure if JPA will let you access that properly though
select name, array_agg(sal) as sals
from the_table
group by name;
If I understand your question correctly, you want to get the result via below SQL statement:
SELECT
name,
string_agg (sal::varchar(22), ', ') as sals
FROM
test
GROUP BY
name;
Since it's postgresql related SQL, we can't or hard to express it via common object query. You can construct the above SQL via native query mode in your JPA code.
#Query(value = "<the above query>", nativeQuery = true)
List<Object[]> query();

Lookup and extract db value based on input (Java & SQL Server)

New to java.
I am attempting to write a class that will input a username, run a query on the username to find the ID, and subsequently use that ID in "where clauses" on all my other classes.
This is the statement that I execute (which will only ever return a recordset of a single row):
String sqlStatement = "SELECT AccountHolderId, Passcode from CIS4720.DBO.AccountHolder " +
"where Username = '" + logonName + "'";
Here is my attempt at extracting the ID via the username...
while (rset.next())
{
if(rset.getInt("Username")==logonName){
int whosOnFirst = rset.getInt("AccountHolderId");
}
I saw another answer on the forum that says you can't assign database values to variables. If that is the case, what is a better strategy?
(Also, I realize I'm not parameterizing, but I'd like to get this working before fixing that issue. This is for a course assignment so I am not worried about hack attacks).
P. S. Thanks I fixed the double equals sign (and the extra parenthesis) in the code above.
Here are some comments about the code:
rset.getInt("Username") will get the column Username from the result but it also looks for an Integer column because of getInt. You are not selecting that column in the sql statement so will error out.
If you select it and get a string, use .equals() instead of == to compare string. Also, one = is assignment and == is comparison.
You can use getString to read Strings from the result set.
You don't need to check the username and match it since your query should return exactly that user's data so I would remove the if condition entirely and just have the getInt line there.

Get SQL String substituted with parameters using java

Is there any easy way to get a completed SQL statement after parameter substitution?
I am using elasticsearch-sql to query elastic search with sql statements, however I have to submit the query with all the parameters substituted.
I tried Hibernate Query getQueryString, but the parameter substitution is not happening for those sql strings.
The following sql string is produced:
"SELECT * FROM USER WHERE NAME=? AND SURNAME=?"
rather than:
"SELECT * FROM USER WHERE NAME='Selva' AND SURNAME='Esra'
Appreciate any better idea/thoughts?
1. Named parameters
This is the most common and user friendly way. It use colon followed by a parameter name (:example) to define a named parameter. See examples…
String hql = "SELECT * FROM USER WHERE NAME= :userName AND SURNAME= :surName";
Query query = session.createQuery(hql);
query.setParameter("userName ", "userName");
query.setParameter("surName", "SurName");
List results = query.list();
An object-oriented representation of a Hibernate query. A Query instance is obtained by calling Session.createQuery(). This interface exposes some extra functionality beyond that provided by Session.iterate() and Session.find():
a particular page of the result set may be selected by calling setMaxResults(), setFirstResult()
named query parameters may be used
the results may be returned as an instance of ScrollableResults
Named query parameters are tokens of the form :name in the query string. A value is bound to the integer parameter :foo by calling
setParameter("foo", foo, Hibernate.INTEGER);
for example. A name may appear multiple times in the query string.
JDBC-style ? parameters are also supported. To bind a value to a JDBC-style parameter use a set method that accepts an int positional argument (numbered from zero, contrary to JDBC).
You may not mix and match JDBC-style parameters and named parameters in the same query.
2. Positional parameters
It’s use question mark (?) to define a named parameter, and you have to set your parameter according to the position sequence. See example…
Java
String hql = "from Stock s where s.stockCode = ? and s.stockName = ?";
List result = session.createQuery(hql)
.setString(0, "7277")
.setParameter(1, "DIALOG")
.list();
This approach is not support the setProperties function. In addition, it’s vulnerable to easy breakage because every change of the position of the bind parameters requires a change to the parameter binding code.
Java
String hql = "from Stock s where s.stockName = ? and s.stockCode = ?";
List result = session.createQuery(hql)
.setParameter(0, "DIALOG")
.setString(1, "7277")
.list();
Conclusion
In Hibernate parameter binding, i would recommend always go for “Named parameters“, as it’s more easy to maintain, and the compiled SQL statement can be reuse (if only bind parameters change) to increase the performance.

extract column names from sql query after where clause

I've a requirement where I need to pull out data from database.
The query is-
SELECT e.Data AS EntityBlob, f.Data AS FpmlBlob
FROM [Trades.InventoryRecord] ir, EntityBlob e, FpmlBlob f
WHERE %s AND uid = e.uid AND uid = f.uid
Here %s is the predicate after where clause which user will input from an html form.
User input will be in this form :
1. TradeDate = '2013-04-05' AND IsLatest = 'TRUE'
2. StreamId= 'IA0015'
3. The query may have IN clause also
Now when this query is rendered I get exception ambigous column streamId or ambigous column IsLatest, as these columns exists in more than one table with same name. So to remove this ambiguity I need to modify the query as - ir.IsLatest or ir.StreamId
To do so by java code, I need to first parse the predicate after where clause, extract column names and insert table name alias- 'ir' before each column name so that the query becomes -
SELECT e.Data AS EntityBlob, f.Data AS FpmlBlob
FROM [Trades.InventoryRecord] ir, EntityBlob e, FpmlBlob f
WHERE ir.TradeDate = '2013-04-05' AND ir.IsLatest = 'TRUE' AND uid = e.uid AND uid = f.uid
what is the best way to parse this predicate, or if there is any other way I can achieve the same result?
My answer to this question is to not parse the user input - there is far too much that can go wrong. It would be a lot better to have a UI with drop downs and buttons for selecting equality, inequality, ranges, in statements, etc. It may seem like more work, but protecting yourself from a SQL injection attack is even more. And even if you are not concerned about malicious SQL injection, then the user still has to get every thing exactly right, or the statement fails.

Hibernate & Security Threats

In my java program I used Hybernate technology to access MySQL database table called items .That table has columns named "itemname itemprice itemid" & my java program has HQL statements to fetch data. Also it has a combo box which populates from the items table. Once we select an itemname from combo box it automatically fill two non editable jtext fields called itemid & itemprice, & another part of the program has codes to get string values from those jtextfields & write those values in another database table called orders using a POJO class.
I want to know that this kind of program can be attacked by sql injections ???, if we use Hibernate it is safe from sql injection attacks ???....
If my program has security threats briefly explain how can I avoid those...
I post some codes here.
This statement to fill combo box
String SQL_QUERY = "Select items.iname,items.iid,items.iprice from Item items";
This statement fills jtextfields. The "selecteditem" variable is the selected index of the combo box.
String SQL_QUERY ="Select items.iname,items.iid,items.iprice from Item items where items.iid = '"+selecteditem+"'";
This method writes data in orders table
//To send data to the orders table
private void fillordertable(){
String itemname = (String) jcbItemCode.getSelectedItem();
String itempric = jtfItemPrice.getText();
String tmp = jtfQuantity.getText();
int itemqty = Integer.parseInt(tmp);
String temp = jtfUnitPrice.getText();
double unitpric = Double.parseDouble(temp);
Session session = null;
//This variables for validating purposes
String tempcname = jtfName.getText();
String tempcemail = jtfEmail.getText();
if(tempcname.equals("") || tempcemail.equals("")){
jtaDisplay.setText("Check * fields");
}
else{
try{
SessionFactory sessionFactory = new org.hibernate.cfg.Configuration().configure().buildSessionFactory();
session =sessionFactory.openSession();
session.beginTransaction();
Order order = new Order();
order.setItcode(itemcode);
order.setItdiscription(itemdis);
order.setItqty(itemqty);
order.setItemprice(unitpric);
order.setTotprice(unitpric * itemqty);
order.setOstatus("Placed");
session.save(order);
session.getTransaction().commit();
}
catch(Exception exc){
jtaDisplay.setText(exc.getMessage());
}
finally{
session.flush();
session.close();
}
jtaDisplay.setText("Order & customer tables updated successfully !!!");
}
}
It is difficult to understand my whole code if I post it here. So I have posted some codes which I thought helpful to answer my question. If that is not enough please comment.
Thanks!
String SQL_QUERY ="Select items.iname,items.iid,items.iprice from Item items where items.iid = '"+selecteditem+"'";
is susceptible to sql injection if selectedItem is data entered by the user.
Generating SQL or HQL queries by concatenating strings is in general bad form, and likely to lead to sql injection possibilities.
The safe way is to use named parameters in any SQL or HQL.
In your example, which appears to be SQL, after acquiring a Hibernate session, something like:
String SQL_QUERY ="Select items.iname,items.iid,items.iprice from Item items where items.iid = :selecteditem";
SQLQuery query = session.createSQLQuery(SQL_QUERY);
query.setParameter("selecteditem", selecteditem);
List<Object[]> results = query.list();
should be approximately the way you want to code and execute your query.
Similar things apply to HQL.
If you just concatenate strings, the evil values entered by a hacker as in the famous xkcd become part of your query and can do awful things.
If this is not a web form but a desktop application, you may well be in complete control of the values that can get into this variable, but it's still advisable to try to do these things correctly.
Another effect of named parameters is that the parametrized sql can be cached and reused for different values of the parameter. So it's a good idea even without the security concern.
if you are creating HQL by concatenating field values with the rest of the HQL text, you have a problem. if you are using HQL (correctly) with substitution variables for all field values, you are fine. (obviously there could be more to say about this, but without more details from the OP, this is about all we can say at this time). also, if you insert/update logic is purely using POJOs, then you are fine there.
UPDATE:
now that you've posted some code, yes you have problems. you should use named parameters in your HQL. (your write code is fine, though).

Categories

Resources