how hibernate deal with like keyword in query sentence - mysql

Here met a hesitation about the way hibernate dealing with like keyword in query sentence.This's a small snippet in DaoImpl and see it first:
public List<T> findBySQL(String sql, String... params){
SQLQuery query = getSession().createSQLQuery(sql);
query.addEntity(clazz);
for (int i = 0; i < params.length; i++){
query.setParameter(i, params[i]);
}
List<T> list = query.list();
return list;
}
ok! without any doubt and use it in below controller:
#RequestMapping(value = "/getFirst/{var}", produces = "application/json; charset=utf-8")
public #ResponseBody Site getFirst(#PathVariable String var){
String fr = "select * from Food f where f.resname = ?";
List<Site> siteList = siteService.findBySQL(fr, var);
Site first = siteList.get(0);
return first;
}
here is the result:{"src":"http://p0.meituan.net/350.214/deal/ac8ba922d7a6030325976fb31e51b4ce38985.jpg","resname":"哈哈派"}
but when i change such sql sentence like this using like and without amending anything else:
String fr = "select * from Food f where f.resname like '%?%'";
List<Site> siteList = siteService.findBySQL(fr, var);
redeploy and run, exception appear:
HTTP Status 500 - Request processing failed; nested exception is org.hibernate.QueryParameterException: Position beyond number of declared ordinal parameters. Remember that ordinal parameters are 1-based! Position: 1
but i don't think it's the parameter index problem, maybe something error or maybe like can not be used like such way? so i wonder how hibernate deal with 'like' keyword?

You should add the wildchar(%) to the parameter and not the query. So modify your query as below.
String fr = "select * from Food f where f.resname like ? ";
List<Site> siteList = siteService.findBySQL(fr, "%"+var+"%");
OR
String fr = "select * from Food f where f.resname like ? ";
List<Site> siteList = siteService.findBySQL(fr, new String[]{"%"+var+"%"});

Related

C sharp Dapper ms access query like parameters

I have a list of parameters : numericPartList : 029%, 035% for example.
As mentioned in the code, with only 1 parameter it works, but more, no...
public static List<tLicencie> GetDepartement(List<string> numericPartList)
{
ConnectionStringSettings connex = ConfigurationManager.ConnectionStrings["MaConnection"];
string connString = connex.ProviderName + connex.ConnectionString;
using (OleDbConnection con = new OleDbConnection(connString))
{
string sql;
if (numericPartList.Count < 2)
{
sql = "select * from tLicencie where NOCLUB like #numericPartList "; // Works !
}
else
{
sql = "select * from tLicencie where NOCLUB like #numericPartList "; // Does not Work
}
return (List<tLicencie>)con.Query<tLicencie>(sql, new { numericPartList });
}
}
I get an error message :
Syntax error (comma) in expression 'NOCLUB like (# numericPartList1, # numericPartList2)'. "
How to solve this problem?
A solution for the moment: I add DapperExtentions then
var pga = new PredicateGroup { Operator = GroupOperator.Or, Predicates = new List<IPredicate>() };
pga.Predicates.Add(Predicates.Field<tLicencie>(f => f.NOCLUB, Operator.Like, "029%"));
pga.Predicates.Add(Predicates.Field<tLicencie>(f => f.NOCLUB, Operator.Like, "035%"));
IEnumerable<tLicencie> list = con.GetList<tLicencie>(pga);
The dapper list expansion is only intended for use with in, i.e. it would expand:
where foo in #x
to
where foo in (#x0, #x1, #x2)
(or some other variants, depending on the scenario).
It cannot be used with like in this way, as it will give invalid SQL; you would need to compose your SQL and parameters in a more manual fashion, perhaps using DynamicParameters which works more like a dictionary; i.e. you would need to loop in such a way as to construct
where (foo like #x0 or foo like #x1 or foo like #x2)

MySQL workbench returns stored procedure with multiple rows, but from Java code, only one row is returned

It is MYSQL, and the same stored procedure call in Workbench works fine, but from Java code, it always only return one row.
String sql = "{ CALL getList(?, ?, ?) }";
CallableStatement cs = conn.prepareCall(sql);
cs.setLong(1, key);
cs.setString(2, id);
cs.setInt(3, java.sql.Types.INTEGER);
ResultSet rs = cs.executeQuery();
rtn = cs.getInt(3); // this return as 1
while (rs.next()) {
String name = rs.getString("name");
String age= rs.getString("age");
//.....
}
from this while loop, always and only return one row, it is very strange, spend hours, no clue yet, please advice what may be wrong, the hint is that the MYSQL is old version 5.3, and Java is old version JDK 1.6.
Anybody have experience to deal with it, please advice, thanks.
In addition to what you have, you need to also implement the add() method. Try this:
String sql = "{ CALL getList(?, ?, ?) }";
CallableStatement cs = conn.prepareCall(sql);
cs.setLong(1, key);
cs.setString(2, id);
cs.setInt(3, java.sql.Types.INTEGER);
ResultSet rs = cs.executeQuery();
rtn = cs.getInt(3);
while(rs.next()) {
String name = add(rs.getString("name"));
String age= add(rs.getString("age"));
}

Why is "Input string was not in a correct format." in the query in mySQL?

In the following code,
I get a run time error of
"Input string was not in a correct format." after oCommand.ExecuteReader().
oCommand.CommandText = "CheckOutItem";
oCommand.CommandType = System.Data.CommandType.StoredProcedure;
oCommand.Parameters.AddWithValue("#OrderID", OrderID);
oCommand.Parameters.AddWithValue("#GivenLargeSizeName", Enum.GetName(typeof(Size), Size.REGULAR));
oCommand.Parameters.AddWithValue("#GivenSmallSizeName", Enum.GetName(typeof(Size), Size.SMALL));
oCommand.Parameters.AddWithValue("#Latitude",oOrder.OrderTimeLocation.Location.latitude);
oCommand.Parameters.AddWithValue("#Longitude",oOrder.OrderTimeLocation.Location.longitude);
oCommand.Parameters.AddWithValue("#ListingID", MySqlDbType.Int64);
oCommand.Parameters.AddWithValue("#Quantity", MySqlDbType.Int16);
oCommand.Parameters.AddWithValue("#Size", MySqlDbType.VarChar);
oCommand.Parameters.AddWithValue("#DeliveryMethod", MySqlDbType.VarChar);
foreach (var OrderItem in oOrder.OrderItems)
{
oCommand.Parameters["#ListingID"].Value = OrderItem.ListingID;
oCommand.Parameters["#Quantity"].Value = OrderItem.Quantity;
oCommand.Parameters["#Size"].Value = Enum.GetName(typeof(Size), OrderItem.Size);
oCommand.Parameters["#DeliveryMethod"].Value = Enum.GetName(typeof(DeliverMethod), OrderItem.DeliveryPickupMethod);
using (var reader = oCommand.ExecuteReader())
{
while (reader.Read())
{
Int64 OrderItemID = Convert.ToInt64(reader["#ORDER_ITEM_ID"]);
Int64 OrderItemStatusID = Convert.ToInt64(reader["#ORDER_ITEM_STATUS_ID"]);
Int64 OrderItemPriceID = Convert.ToInt64(reader["#ORDER_ITEM_PRICE_ID"]);
TotalOrderCostFromDB = TotalOrderCostFromDB + Convert.ToDecimal(reader["#TOTAL_ORDER_COST"]);
}
}
}
if I use statements like
oCommand.Parameters.AddWithValue("#ListingID",OrderItem.ListingID)
works fine but I can not loop.
All the values I am assigning are correct in debugging and no nulls or weird stuff getting into .Value.
Since I get the correct answer in AddWithValue method, I don't think I have any issue with StoredPoocedure.
Is there a better approach to loop for this purpose?
After some debugging, I was able to narrow down the issues to last two lines
oCommand.Parameters.AddWithValue("#Size", MySqlDbType.VarChar);
oCommand.Parameters.AddWithValue("#DeliveryMethod", MySqlDbType.VarChar);
If I initialize this with a dummy string, everything is fine. But initializing with VarChar or String cause problems.
For my understanding, following returns a string right?
Enum.GetName(typeof(Size), OrderItem.Size)

Can't delete form database SQLGrammarException

I want to DELETE column from base in hibernate where my inserted -regBroj- parameter is same as one in a base.
This is my method in controller for deleting.But i constantly get
SQLGrammarException:
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'BG026CH' in 'where clause'
This 'BG026CH' is value of regBroj that i use as a parameter to find vehicle in database and delete it.And i insert it in text area in adminPage.
public String izbrisi(String regBroj) {
List<Vozilo> lista = listaj();
Session s = HibernateUtil.getSessionFactory().getCurrentSession();
Transaction t = s.beginTransaction();
for (int i = 0; i < lista.size(); i++) {
if (regBroj .equals(lista.get(i).getRegBroj())) {
String izbrisiquery = "DELETE FROM Korisnik WHERE brojLk=" + regBroj + "";
Query q = s.createQuery(izbrisiquery);
int a = q.executeUpdate();
t.commit();
return "adminPage";
}
}
t.commit();
return "error";
}
Please replace below string with these one
String izbrisiquery = "DELETE FROM Korisnik WHERE brojLk='" + regBroj + "'";
You should consider using prepared statements because they will automatically take care of escaping field values with quotes, and they will also protect you from SQL injection.
// obtain a Connection object using your Hibernate session, or through some other means
Connection conn = getDBConnection();
for (int i = 0; i < lista.size(); i++) {
if (regBroj .equals(lista.get(i).getRegBroj())) {
String izbrisiquery = "DELETE FROM Korisnik WHERE brojLk = ?";
PreparedStatement ps = conn.prepareStatement(izbrisiquery);
ps.setString(1, regBroj);
ps.executeUpdate();
t.commit();
return "adminPage";
}
}
To see how SQL injection works, or how a malicious user could wreck the Korisnik table, imagine that someone hacks the UI to pass a value of '' OR TRUE for brojLK. This is what the resulting DELETE statement would look like:
DELETE FROM Korisnik WHERE brojLk = '' OR TRUE
In other words, this injected query would drop your entire table! Prepared statements would choke on this input and a hacker would not get as far as executing the query.

hibernate query for Getting json key value pair with joins

I am using REST , hibernate query language for getting some data from database with the help of joins in that query i need to fetch columns from two or more tables and i am getting the result record , and when i return that object through REST as json i am getting the json as in the follwoing format
{"table1col1value","table2col1value","table3colvalue","table1col2value","table2col2value"}
but i need to get the json data in the following format
{"table1colname1":"table1col1value","table2colname":"table2col1value","table1colname":"table3colvalue","table1colname":"table1col2value","table2colname":"table2col2value"}
for that i am using the following code and its working fine, but its working with sql query only i need it in HQL , please help me in this.
#Override
#Transactional
public List<Map<String,Object>> getMixProperties(List<String> keys,Set<String> s) {
StringBuilder sb = new StringBuilder();
sb.append("select ");
Iterator<String> i = keys.iterator();
int q = keys.size();
while (i.hasNext()) {
q=q-1;
if(q==0){
String n= i.next();
sb.append(" "+n);
}
else{
String n2= i.next();
sb.append(" "+n2+",");}
}
sb.append(" from Book Book "
+ " join Systems Systems ON Systems.idSystems =Book.idSystems "
+ " join Machine Machine ON Machine.id =Systems.id ");
/*Iterator<String> iterator = s.iterator();
int q2 = s.size();String s5 = null;
while(iterator.hasNext()) {
String s4 = iterator.next();
q2=q2-1;
if(q2==0){
sb.append(" "+s4+" "+s4);
}
else{
s5=s4;
sb.append(" "+s4+" "+s4+",");}
}*/
System.out.println("query "+sb);
String sbb = sb.toString();
Query query=sessionFactory.getCurrentSession().createSQLQuery(sbb);
query.setResultTransformer(AliasToEntityMapResultTransformer.INSTANCE);
List<Map<String,Object>> aliasToValueMapList=query.list();
return aliasToValueMapList;
}
in this above code List keys will be the column name of different tables and (set s will be table names, but i am not using it in current code)
even this is working only if i have both class and db table name are same and property and column names are same, if its not same then its not working.
I am getting JSON only if i have the pojo class , but in my case result set can be any number of columns so its depends on runtime only , please help me in this