Intuitively, what I want to do is something like this:
Restrictions.ilike("concat(user.firstName, ' ', user.lastName)",
text.toLowerCase() + "%")
However, I know that this won't work, because concat(user.firstName, ' ', user.lastName) is not a property that Hibernate understands, even though this is what I would have typed in a regular SQL statement as part of the where clause.
Is there any easy way to make this where restriction with Hibernate Criteria API, or do I have to fall back on good-old HSQL?
Thanks
One solution is to define fullName property in your User class.
#Formula(value="first_name || ' ' || last_name")
private String fullName;
And then use that filed in Criteria,
criteria.add(Restrictions.ilike("fullName", text.toLowerCase() + "%"));
I'm a little floppy on SQL so the statement may not be 100% accurate.
Obviously, this isn't an ilike but if you want to use SQL, why not use a sqlRestriction instead with a parameter?
Restrictions.sqlRestriction("select * from user where concat(user.firstName, ' ', user.lastName) like ?", text.toLowerCase() + "%", StandardBasicTypes.STRING);
I assume the goal is to be able to make a portable Restriction, in which case, this can sub in for your attempted ilike.
Related
I have a list of different ids and their names. For every id[0] we have name[0] that needs to be matched.
list of ids, l{1,2,3,4};
list of names, n{a,b,c,d};
Now suppose if I want to get an exact match for both above combination, is there any way in HQL to get the result?
I am looking to find a replacement for a query like:
select any_column
from table_name
where (id[0]=1 and name[0]=a) or (id[1]=2 and name[1]=b and so on...);
The HQL query should be something like below:
select any_column
from table_name
where (id,name) IN {(id[0],name[0]), (id[1], name[1]),...};
Any suggestions?
I am not hql/sql guy, however one way I can think of is, in your hql, you concatenate the id and name with a space (or other special char) then with in sub-clause. something like:
select * from table where concat(id, ' ', name) in (:pairList)
The pairList parameter is a java collection, you should prepare before the hql query call, which has element id[x] + " " + name[x].
I think this should work.
If you are using hibernate, another possible solution is, make use of the hibernate's #Formular annotation on your table entity, to create a calculated column, such as:
#Formula(value = " concat(id, ' ', name) ")
private String idNamePair;
Then you can in hql use it as a normal field. like ... from table where idNamePair in (:paramList)
Is there a way in JPA 2.0 to set parameter of a query with special characters? I mean, if I do: query.setParameter(field, "%" + value.toString() + "%");, it takes % as special (wildcard) character? It seems to me it's not true in this case, beacuse my search doesn't work with truncated words...
Can You help me??
If you are using
LIKE :feild
for
query.setParameter(field, "%" + value.toString() + "%");
Then value remains free from the '%' sign. You can try to use % in your query and send value from setParameter() method.
You can also try CreteriaBuilderInterface of JPA.
http://www.objectdb.com/java/jpa/query/jpql/string.
you have to escape the query. try to use "\\%" instead
what ever you pass in as a query parameter that will pass on to query and back to database. So to the choice of escape character of the query parameter will depend on database. Like in mysql it is "\'" for "'" and "\%" for "%" so if I want to send "john's 10% commission" as query parameter to mysql, i will try query.setParameter(field, "john\\'s 10\\% commission"); in your case query.setParameter(field, "\\%" + value.toString() + "\\%"); should work. But check the documentation of the database to find out escape character for special cases.
I have a bean class which does maintain user data:
soppose I have created a postgresql DB table like this:
StringBuffer sqlStr = new StringBuffer();
sqlStr.append("CREATE TABLE Users ("
user_id bigint,
username character varying NOT NULL,
biography character varying NOT NULL
);
& I want to make a query command and inject my String data inside it:
sqlStr.append("INSERT INTO users(" +
"user_id, username, biography)" +
"\n\tVALUES (" + user.getID()+ "," + user.getUsername() + "," + user.getBiography()+");";
my problem is for example if the data coming from my method has quote or double quote or "," my command will become wrong suppose that the user biography is something like this :
hello, I'm Mr X an "IT Pro" ...
If I run my application and save the output inside a file called query.sql I can't use it because my query command is wrong because of quote & double quote, something like this:
INSERT INTO users(userid, username, biography)
VALUES(2, 'Mehdi', 'hello, I'm Mr X an "IT Pro" ..');
how Can I fix this problem ?
You should never ever use the above method for constructing SQL queries.
"Why not?" you ask, well; where to start. The classic example is Bobby Tables, the more general problem is SQL injection. This leaves your program open to attack but also to random failure - like the situation you describe.
Now, the solution. Always use PreparedStatement to construct your query. In your example
final String query = "INSERT INTO users(user_id, username, biography) VALUES (?,?,?)";
final PreparedStatement ps = con.prepareStatement(query);
ps.setInt(1, user.getID());
ps.setString(2, user.getUsername());
ps.setString(3, user.getBiography());
ps.executeUpdate();
A much nicer syntax to use with is the the SET syntax rather than the traditional VALUES syntax. The query would then look like
final String query = "INSERT INTO users SET user_id = ?, username = ?, biography = ?";
EDIT
The OP is building a query for a script file, not executing a query in the code.
There is a utility class in Apache Commons Lang, StringEscapeUtils. This has an escapeSql method. Looking at the source code, all this does is escape single quotes with another single quote.
This works if you build your queries with single quotes:
VALUES (" + user.getID()+ ",'" + user.getUsername() + "'...
So the query, once the example value is inserted will go from:
VALUES (10 ,'hello, I'm Mr X an "IT Pro"'...
Will become
VALUES (10 ,'hello, I''m Mr X an "IT Pro"'...
The apostrophe in "I'm" is now escaped and harmless.
Note that you obviously need to escape the values and not the query, so (assuming you have a static import for the class)
VALUES (" + user.getID()+ ",'" + escapeSql(user.getUsername()) + "'...
But does not escape other sql characters, percent signs for example.
This is really a stop-gap measure to make the code work while you come up with a more robust solution. And you should come up with a more robust solution.
Why dont you use PreparedStatement? That will also give you better performance as the SQL will be pre-compiled on DB side.
Or
You can escape the quotes using
String.replaceAll http://docs.oracle.com/javase/6/docs/api/java/lang/String.html#replaceAll(java.lang.String, java.lang.String)
A quick question, I can't find it on the internet, probably I am looking at the wrong "term".
But how do you make a SQL query statement with "if contains"
"SELECT something FROM " + TABLE_NAME + " WHERE name **contains** '*String*'", null);
I know you got these statements: = > < >= <= but what to use for if contains?
You want the LIKE keyword
Depending on the variety of SQL for the wildcard.
...Where name like '%string%'
SQLite uses % for a sequence of 0 or more unspecified characters (like a *), and an underscore _ for any single character
SELECT something FROM table WHERE name LIKE '%spam%'
(percent signs act like asterisks in a "conventional" search, give or take.)
You can get much more complicated with dbms specific functions (eg, here's Oracle's) that can, situationally, add regular expressions and other ways of searching.
As always, watch out for collation issues and case.
you can use LIKE
"SELECT something FROM " + TABLE_NAME + " WHERE name like '%yourstring%'";
refer to: http://www.sqlite.org/lang_expr.html
Instead of "if contains" you can use the "like" statement...
the query will be...
"SELECT something FROM tablename where name like %'string'%"
This will return what u want,,,
For Example:
Your table name "abc" contains Jarry,Jack,John,Josh,.....
if u run the query
select * from abc where name like %Ja%
it will return
Jarry,Jack..
The query code and query:
ps = conn.prepareStatement("select instance_id, ? from eam_measurement where resource_id in (select RESOURCE_ID from eam_res_grp_res_map where resource_group_id = ?) and DSN like '?' order by 2");
ps.setString(1,"SUBSTR(DSN,27,16)");
ps.setInt(2,defaultWasGroup);
ps.setString(3,"%Module=jvmRuntimeModule:freeMemory%");
rs = ps.executeQuery();
while (rs.next()) { bla blah blah blah ...
Returns an empty ResultSet.
Through basic debugging I have found its the third bind that is the problem i.e.
DSN like '?'
I have tried all kinds of variations, the most sensible of which seemed to be using:
DSN like concat('%',?,'%')
but that does not work as I am missing the ' on either side of the concatenated string so I try:
DSN like ' concat('%',Module=P_STAG_JDBC01:poolSize,'%') ' order by 2
but I just cannot seem to find a way to get them in that works.
What am I missing?
First, the PreparedStatement placeholders (those ? things) are for column values only, not for table names, column names, SQL functions/clauses, etcetera. Better use String#format() instead. Second, you should not quote the placeholders like '?', it would only malform the final query. The PreparedStatement setters already do the quoting (and escaping) job for you.
Here's the fixed SQL:
private static final String SQL = "select instance_id, %s from eam_measurement"
+ " where resource_id in (select RESOURCE_ID from eam_res_grp_res_map where"
+ " resource_group_id = ?) and DSN like ? order by 2");
Here is how to use it:
String sql = String.format(SQL, "SUBSTR(DSN,27,16)"); // This replaces the %s.
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1, defaultWasGroup);
preparedStatement.setString(2, "%Module=jvmRuntimeModule:freeMemory%");
See also:
Sun JDBC tutorial: Using Prepared Statements
Format string syntax
If you want to use LIKE in prepared statement and also want to use % characters in LIKE;
write prepared statement as normally " .... LIKE ? ...." and while assigning parameter value to question mark use
ps.setString(1, "%" + "your string value" + "%");
This will work :)
There are two problems with your statement. You have to understand how bind variables work. The query is not processed by substituing the characters ? with your parameters. Instead, the statement is compiled with placeholders and then, during execution, the actual values of the parameters are given to the DB.
In other words, you parse the following query:
SELECT instance_id, :p1
FROM eam_measurement
WHERE resource_id IN (SELECT RESOURCE_ID
FROM eam_res_grp_res_map
WHERE resource_group_id = :p2)
AND DSN LIKE '?'
ORDER BY 2
I'm pretty sure the last parameter will be ignored because it is in a delimited character string. Even if it is not ignored, it does not make sense to have ' characters around because Oracle won't bind a parameter in a string (I'm surprised it hasn't raised any error, do you catch exceptions ?).
Now if you replace your DNS LIKE '?' with DSN LIKE ? and bind "%Module=jvmRuntimeModule:freeMemory%" this will make sense and should return the correct rows.
You still have the problem with your first parameter, it won't do what you expect, i-e the query that will be executed will be equivalent to the following query:
SELECT instance_id, 'SUBSTR(DSN,27,16)'
FROM ...
which is not at all the same as
SELECT instance_id, SUBSTR(DSN,27,16)
FROM ...
I would suggest parsing (=prepareStatement) the following query if you expect the SUBSTR to be dynamic:
SELECT instance_id, SUBSTR(DSN,?,?)
FROM eam_measurement
WHERE resource_id IN (SELECT RESOURCE_ID
FROM eam_res_grp_res_map
WHERE resource_group_id = ?)
AND DSN LIKE ?
ORDER BY 2
Omit the ' around the ?. Without the ', ? is a placeholder for a parameter. With it, it's an SQL string (i.e. the same as "?" in Java).
Then you must concatenate the string on the Java side; you can't pass SQL functions as parameters to queries; only basic values (like string, integer, etc) because the JDBC driver will convert the parameter to the SQL type the database expects and it cannot execute SQL functions in this step.
You can try:
String beforeAndAfter = "%" + yourVariable + "%";
PreparedStatement ps = con.prepareStatement(
"select columname from tablename where LOWER(columnname) LIKE LOWER('"+var+"%')");
Here var is the variable in which value that is to be searched is stored...
This should work:
"\'" + "?" + "\'"