I'd like to use criteria and create something like this but with hibernate criterias:
WHERE concat(X, Y) like '%Some Value%'
I don't want to do it using query concatenation, but using Restrictions because I am making a dynamic library that gets the left and right side of the like operator? Am I clear? Please if not ask me to give more clarification.
Thank you!
Hope it may works.
Criteria crit = session.createCriteria(Table.class);
crit.add(Restrictions.ilike("param1 || param2", "%" + dniWithLetter + "%"));
If the above code not working, please go through the following link.
Can we concatenate two properties in Hibernate HQL query?
I think that the best solution for your problem is the following
...
Object[] params = {objX, objY, someValue};
Type[] typeOfParams = {Hibernate.STRING, Hibernate.STRING, Hibernate.STRING};
Criteria crit = session.createCriteria(Table.class);
crit.add(Restrictions.sqlRestriction("concat(?, ?) like '%?%'", params, typeOfParams));
...
When you use Restrictions.sqlRestriction, you can build a complex query with multiple parameters, you just have to set the parameters and type of each parameter, this is done with params array and typeOfparams array.
I hope this information helps you.
Good luck.
Related
How can I use find_in_set in jpa?
I need to achieve like this
SQL - select * from teacher where find_in_set("5", deptIds) and id = 101
where deptIds have comma separated ids (I know it's bad idea but legacy.)
To do so I had been tried using Criteria but not found any Restrictions that can fulfill find_in_set.
Note - need possible solution with Criteria and Restrictions
criteriaBuilder.function("find_in_set", Boolean.class,
criteriaBuilder.literal(s),
root.get("field"))
Here is an example:
Here is java code snippet.
list.add(cb.greaterThan(cb.function("FIND_IN_SET", Integer.class,
cb.literal(val.toString()), root.get(attributeName)), 0));
select t from Teacher t where find_in_set("5", t.deptIds) = 0 and t.id = 101
In my Case after getting a certain list I need to to iterate that list to set some other fields of the POJO class.
if (transportHeaderList.get(i) instanceof TransportHeaderIiss){
transHeadIiss=(TransportHeaderIiss)transportHeaderList.get(i);
customerVendor= tOManagementDAO.getVendorCode(transHeadIiss.getCustVendUid());
}
if(customerVendor!=null){
transHeadIiss.setVendorCode(customerVendor.getCustVendCode());
}
The Above code calls getVendorCode method to get custVendorCode value from the database. The code for getVendorCode is as follows
public CustomerVendorIiss getVendorCode(Long custVendUid) {
List list=new ArrayList();
/* Criteria criteria = sessionFactory.getCurrentSession().createCriteria(CustomerVendorIiss.class);
criteria.add(Restrictions.eq("companyCode",user.getDefaultCompany().getCompanyCode()));
if(custVendUid!=null && custVendUid.intValue()>0)
{
criteria.add(Restrictions.eq("custVendUid",custVendUid));
}
list=criteria.list();*/
UsersIiss user= ApplicationContextProvider.getLoggedInUser();
String sqlQuery="select custVendCode as custVendCode from CustomerVendorIiss where companyCode ='"+ user.getDefaultCompany().getCompanyCode() +"' and custVendUid= "+custVendUid;
Query query = sessionFactory.getCurrentSession().createQuery(sqlQuery);
query.setResultTransformer(Transformers.aliasToBean(CustomerVendorIiss.class));
list=query.list();
if(list.size()>0){
return (CustomerVendorIiss)list.get(0);
}else{
return null;
}
}
When I executed above code with criteria, it took a lot time to get the values from table and set it to POJO class and sometimes I would get java.lang.OutOfMemoryError: Java heap space error . I guess that's because I am not de-allocating the criteria object.
when I executed the above code using createQuery() method I did not run into that issue and all that process of getting and setting was faster.
I want to understand what is that I am doing wrong here?
it would be great to know how and when criteria is better or HQL is better ?
Thank you !!
Actually these queries are different. The second one has an additional restriction
companyCode ='"+ user.getDefaultCompany().getCompanyCode() +"'
So try to add the same to the criteria
criteria.add(Restrictions.eq("companyCode",user.getDefaultCompany().getCompanyCode()));
Also it's not god to concate strings this way to get the query. SQL injection is possible. Use parameters instead.
Criteria and HQL is better than SQL in one case - you need DB independent logic to swap DB when necessary without rewriting code.
Is there a way to have named parameters in Java MySQL query?
Like this:
SELECT * FROM table WHERE col1 = :val1 AND col2 = :val2
instead of this:
SELECT * FROM table WHERE col1 = ? AND col2 = ?
UPDATE: Im' using java.sql.*, however would be interested in alternatives capable of this.
Maybe Hibernate is good choice for you. It provided the query style as your description, and it's so powerful and convenient to do persistence work that you'll feel cool.
e.g
Query query = sesion.createQuery("from Student s where s.age = :age");
query.setProperties(student);
see the doc:http://docs.jboss.org/hibernate/orm/3.2/api/org/hibernate/Query.html#setParameter(java.lang.String, java.lang.Object)
The excellent JDBI library lets you do this and much more.
Yes, there are alternatives. By example, with javax.persistence.* you can achieve that quite easily.
http://docs.oracle.com/javaee/6/tutorial/doc/bnbrg.html
An entity manager will allow you to create dynamic (parametrized) queries with the methods EntityManager.createQuery, and EntityManager.createNamedQuery.
Note: This may be a simple question but I can't find a short way to make it clear. So, sorry for this long question.
In a project I am responsible, I use Spring 2.5, Hibernate 3.3.2 as middleware and Oracle database. As database is related to many other projects, some queries as really very complicated and I can't get a solution with Hibernate's solutions (HQL, Criteria, etc...). So I feel more comfortable with JdbcTemplate's queryForX() methods, as an example;
String sql = "select * from myTable";
jdbc.queryForList(sql);
Sure there are mostly "where" conditions and params indeed:
jdbc.querForList(sql, new Object[]{obj1,obj2,obj3 /* and many more arguments... */})
In this case, I must write question marks "?" for my parameters, so my SQL query string turns out some messy and hard to read; something like this:
select t1.col1, t2.col2, t1.col, --...some cols ,
sum(nvl(some_col1,?)-nvl(other_col2,?)) over (partition by col1,col2,col3,col4) sum_of_cols
from weird_table t1, another_table t2
where t1.col20=? and sum_of_cols>? and t1.col3=t2.col3 --and many ?'s...
and not exists (
select ? from boring_table t3 where -- many ?'s
)
--group by and order by order by etc
So now, which question mark is for which parameter? It is obvious but hard to read. But there are some other solutions for binded params like:
select * from a_table t where t.col1= :col1 and t.col2= :col2 -- and many more ":param"s
For this type query, we can write if it were Hibernate:
Query q = hibernateTemplate.createQuery();
q.setString("col1","a value");
q.setInteger("col2", 3);
I think it is more readable and easy to understand which value is what. I know I can do this with SQLQuery;
SQLQuery sq = hibernateTemplate.createSQLQuery();
/* same as above setInteger() etc. */
But this sq.list() gives me a list without a column name. so I have a basic array which is difficult to use:
[[1,2,"a"],[1,2,"b"], ...]
But with queryForList() I get better one:
[{COL1=1,COL2=2,COL3="a"},{COL1=1,COL2=2,COL3="b"},...]
So if I use queryForList(), I must write a very messy params Object;
or I use SQLQuery and then I have to get my list without a map as column names.
Is there a simple solution with mapped list using more readable param setting (like query.setX()) ?
Well you can use NamedParameterJdbcTemplate to do just that
Heres a sample
String query = "INSERT INTO FORUMS (FORUM_ID, FORUM_NAME, FORUM_DESC)
VALUES (:forumId,:forumName,:forumDesc)";
Map namedParameters = new HashMap();
namedParameters.put("forumId", Integer.valueOf(forum.getForumId()));
namedParameters.put("forumName", forum.getForumName());
namedParameters.put("forumDesc", forum.getForumDesc());
namedParameterJdbcTemplate.update(query, namedParameters);
You check the complete example with the source code in the below link
Spring NamedParameterJdbcTemplate Tutorial
I have a problem - I create my SQL queries dynamically and basing on user input options. So the user has 5 parameters (actually it's more) and he can choose to use some of them (all if he wants) or none and specify their value in the query. So I construct my query String (basic the WHERE conditions) by checking if a parameter was selected and if a value was provided. However now there is the problem of special characters like '. I could try to use replaceAll("'", "\\") but this is quite dull and I know that preparedStatement.setString() does the job better. However for me I would need than to check again if the parameter was provided and if the previous one were also (to specify the poison of ? and connect it to the right parameter). This causes a lot of combinations and does not look elegant.
So my question is - can I somehow receive the string preparedStatement.setString() produces? Or is there a similar function that would do the same job and give me the String so I can put it in the query manually.
Maybe the intro was too long but someone might have a better idea and I wanted to explain why I need it.
What you can do is construct the basic, unparameterized SQL query based on whether the parameters were specified, and then use the prepared statement to fill in the parameters.
It could look something like this (rough sketch):
Map<String, Object> parameterValues = /*from user*/;
List<String> parameterNames = Arrays.asList("field1", "field2", "field3");
List<Object> valueList = new ArrayList<Object>();
StringBuilder statementBuilder = new StringBuilder("select * from table where ");
for ( String parameterName : parameterNames ) {
if ( parameterValues.containsKey(parameterName) ) {
statementBuilder.append(parameterName + " = ? AND");
valueList.add(parameterValues.get(parameterName));
}
}
PreparedStatement st = conn.prepareStatement(statementBuilder.toString(),
valueList);
//set each parameter here.
It's only hard the first time; then you can make it generic. That said there are probably query builders that abstract all of this away for you. I use QueryDSL but that does not have bindings for pure JDBC but rather JPA and JDO, etc.
On another forum I was given a different, simpler and cleaner approach that work perfectly.
Here are some links for others with the same problem:
http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:1669972300346534908
http://www.akadia.com/services/dyn_modify_where_clause.html