How to create query with Spring Data JPA? - sql

Please help me. I can not create query from native sql using spring data.
How do I convert the following expression?
select distinct brand, model from cars
where brand like '%:query%' or model like '%:query%' limit 2;

You could use projections with Spring Data JPA, something of the likes of:
interface SimpleCar {
String getBrand();
String getModel();
}
and then:
List<SimpleCar> findDistinctByBrandLikeOrModelLike(String query);
You can review here for different options to query a DB with some examples.
By the way, if you want to see what queries your methods are executing you can activate DEBUG logging mode in log4j for org.springframework package or org.hibernate (if you're using Hibernate)

that helped me, hopefully you too
https://www.petrikainulainen.net/programming/spring-framework/spring-data-jpa-tutorial-three-custom-queries-with-query-methods/

Use:
#Query("select distinct brand, model from cars " +
"where brand like %:query% or model like %:query% limit 2")
public List<Car> find(#Param("query") String query);
Basically what you had but without the speech marks.

Related

Apache Ignite : Not able to query Select...in() clause with spring boot

I am not able to use IN() clause with apache ignite using spring-boot.
I have tried two ways but both are not working.
Please help me to solve the issue.
repository:
#RepositoryConfig(cacheName = "test")
public interface TestRepo extends IgniteRepository<Test, TestKey>{
#Query("SELECT distinct subscribers FROM test where city in :cities")
List<Integer> selectAll(#Param("cities") List<String> cities, Pageable pageable);
List<Test> findByCityIn( List<String> cities);
error:
org.h2.jdbc.JdbcSQLException: Syntax error in SQL statement "SELECT ""test"".""TEST""._KEY, ""test"".""TEST""._VAL FROM TEST WHERE ((TEST.CITY IN ?[*])) "; expected "("; SQL statement:
SELECT "test"."TEST"._KEY, "test"."TEST"._VAL FROM Test WHERE ((Test.city IN ?)) [42001-196]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:345) ~[h2-1.4.196.jar:1.4.196]
at org.h2.message.DbException.getSyntaxError(DbException.java:205) ~[h2-1.4.196.jar:1.4.196]
SELECT "test"."TEST"._KEY, "test"."TEST"._VAL FROM Test WHERE ((Test.city IN ?))
First of all, question mark should definitely be in parens: IN (?).
Second, you are trying to bind multiple values (in list) to the same question mark at once. I'm not sure that will work. Docs tell that it won't work for IN but would for the case described below.
Third, using IN with Ignite is not recommended for performance reasons, and using join table() is suggested instead:
https://apacheignite-sql.readme.io/docs/performance-and-debugging#section-sql-performance-and-usability-considerations

How to use a dynamic parameter in a IN clause of a JPA named query?

my problem is about this kind of query :
select * from SOMETABLE where SOMEFIELD in ('STRING1','STRING2');
the previous code works fine within Sql Developer.
The same static query also works fine and returns me a few results;
Query nativeQuery = em.createNativeQuery(thePreviousQuery,new someResultSet());
return nativeQuery.getResultList();
But when I try to parameterize this, I encounter a problem.
final String parameterizedQuery = "select * from SOMETABLE where SOMEFIELD in (?selectedValues)";
Query nativeQuery = em.createNativeQuery(parameterizedQuery ,new someResultSet());
nativeQuery.setParameter("selectedValues","'STRING1','STRING2'");
return nativeQuery.getResultList();
I got no result (but no error in console).
And when I look at the log, I see such a thing :
select * from SOMETABLE where SOMEFIELD in (?)
bind => [STRING1,STRING2]
I also tried to use no quotes (with similar result), or non ordered parameter (:selectedValues), which leads to such an error :
SQL Error: Missing IN or OUT parameter at index:: 1
I enventually tried to had the parentheses set directly in the parameter, instead of the query, but this didn't work either...
I could build my query at runtime, to match the first (working) case, but I'd rather do it the proper way; thus, if anyone has an idea, I'll read them with great interest!
FYI :
JPA version 1.0
Oracle 11G
JPA support the use of a collection as a list literal parameter only in JPQL queries, not in native queries. Some JPA providers support it as a proprietary feature, but it's not part of the JPA specification (see https://stackoverflow.com/a/3145275/1285097).
Named parameters in native queries also aren't part of the JPA specification. Their behavior depends on the persistence provider and/or the JDBC driver.
Hibernate with the JDBC driver for Oracle support both of these features.
List<String> selectedValues = Arrays.asList("STRING1", "STRING2");
final String parameterizedQuery = "select * from SOMETABLE where SOMEFIELD in (:selectedValues)";
return em.createNativeQuery(parameterizedQuery)
.setParameter("selectedValues", selectedValues)
.getResultList();
Instead of:
nativeQuery.setParameter("selectedValues", params);
I had to use:
nativeQuery.setParameterList("selectedValues", params);
This worked for me in derby. parameter without "()".
List<String> selectedValues = Arrays.asList("STRING1", "STRING2");
final String parameterizedQuery = "select * from SOMETABLE where SOMEFIELD in
:selectedValues";
return em.createNativeQuery(parameterizedQuery)
.setParameter("selectedValues", selectedValues)
.getResultList();
Replace this:
nativeQuery.setParameter("selectedValues","'STRING1','STRING2'");
with
List<String> params;
nativeQuery.setParameter("selectedValues",params);
I also faced the same issue.
This is what I did:
List<String> sample = new ArrayList<String>();
sample.add("sample1");
sample.add("sample2");
And now you, can set the sample in params.

Entity Framework Dynamic Lambda to Perform Search

I have the following entities in Entity Framwork 5 (C#):
OrderLine - Id, OrderId, ProductName, Price, Deleted
Order - Id, CustomerId, OrderNo, Date
Customer - Id, CustomerName
On the order search screen the user can enter the following search values:
ProductName, OrderNo, CustomerName
For Example they might enter:
Product Search Field: 'Car van bike'
Order Search Field: '100 101 102'
Customer Search Field: 'Joe Jack James'
This should do a OR search (ideally using linq to entities) for each entered word, this example would output the following where sql.
(ProductName like 'Car' Or ProductName like 'van' Or ProductName like 'bike') AND
(OrderNo like '100' Or OrderNo like '101' Or OrderNo like '102') AND
(CustomerName like 'Joe' Or CustomerName like 'Jack' Or CustomerName like 'James')
I want to do this using linq to entities, i am guessing this would need to be some sort of dynamic lambda builder as we don't know how many words the user might enter into each field.
How would i go about doing this, i have had a quick browse but cant see anything simple.
You can build a lambda expression using Expression Trees . What you need to do is split the value and build the expression . Then you can convert in in to a lambda expression like this,
var lambda = Expression.Lambda<Func<object>>(expression);
Here is an example
There are 2 basic approaches to Dynamic Expressions and Queries in LINQ.
3 if you count using Json as the approach to get a lambda expression. => Akash Kava post
a) String Dynamic Lambda
System.Linq.Dynamic can be found at following links
http://msdn.microsoft.com/en-US/vstudio/bb894665.aspx
http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx
http://www.scottgu.com/blogposts/dynquery/dynamiclinqcsharp.zip
b) Build Expression trees
More powerful but harder to master...
Build expressions trees with code found here:
http://msdn.microsoft.com/en-us/library/system.linq.expressions.aspx
an alternate approach is predicate builder but it isnt really that dynamic.
but can deal with the OR type scenario you give as example.
http://www.albahari.com/nutshell/predicatebuilder.aspx
I would recomend to go slightly different way from answers above and use EntitySQL as it is trivial to build SQL-like string with dynamic conditions.
http://msdn.microsoft.com/en-us/library/bb738683.aspx
Disclaimer: I am author of Entity REST SDK.
You can look at Entity REST SDK at http://entityrestsdk.codeplex.com
You can query using JSON syntax as shown below,
/app/entity/account/query?query={AccountID:2}&orderBy=AccountName
&fields={AccountID:'',AcccountName:''}
You can use certain extensions provided to convert JSON to lambda.
And here is details of how JSON is translated to Linq. http://entityrestsdk.codeplex.com/wikipage?title=JSON%20Query%20Language&referringTitle=Home
Current Limitations of OData v3
Additionally, this JSON based query is not same as OData, OData does not yet support correct way to search using navigation properties. OData lets you search navigation property inside a selected entity for example Customer(1)/Addresses?filter=..
But here we support both Any and Parent Property Comparison as shown below.
Example, if you want to search for List of Customers who have purchased specific item, following will be query
{ 'Orders:Any': { 'Product.ProductID:==': 2 } }
This gets translated to
Customers.Where( x=> x.Orders.Any( y=> y.Product.ProductID == 2))
There is no way to do this OData as of now.
Advantages of JSON
When you are using any JavaScript frameworks, creating query based on English syntax is little difficult, and composing query is difficult. But following method helps you in composing query easily as shown.
function query(name,phone,email){
var q = {};
if(name){
q["Name:StartsWith"] = name;
}
if(phone){
q["Phone:=="] = phone;
}
if(email){
q["Email:=="] = email;
}
return JSON.stringify(q);
}
Above method will compose query and "AND" everything if specified. Creating composable query is great advantage with JSON based query syntax.

How to create a dynamic query using EOD SQL?

This should be fairly simple, though I can't seem to find a single example.
I want to create a query looking like this:
SELECT column_name FROM table_name WHERE column_name IN (value1,value2,...)
As an option I could append OR-clauses to the end of the query.
The code I have written so far keeps blowing up with a Nullpointer:
#Select(sql = "select storename from broadcastrecipient where storecity in (?{1})")
public List<String> getStoresForCities(List<String> theCities) throws SQLException;
Thanks in advance.
//Abean
NOTE: I forgot to add some info about my env: PostGres 8.3, Java 1.6 and EOD SQL 0.9.
Thank you Jason.
For those who like to know, the query looks something like this:
#Select(sql = "select distinct(storename) from broadcastrecipient where storecity = any (?{1})", disconnected=true)
public List<String> getStoresForCities(String[] theCities) throws SQLException;
And I also needed to implement a TypeMapper class to map SQL-array to Java array.
I would suggest looking at EoD SQL 2.0: https://eodsql.dev.java.net/
Then take a look at the QueryTool.select() method which is designed exactly for this situation.
EoD SQL 0.9 has no functionality to cope with this sort of query built in.
A really ugly hack is to create a temp table, and populate it with your array data. Then run the query as:
#Select("SELECT storename FROM broadcastrecipient WHERE storecity IN (SELECT * FROM tmp_cities)")
public List<String> getStoresForCurrentCities();

SQl Query to Hibernate Query

I have a MySQL query that I use to retrieve random rows from a table. The query is:
SELECT * FROM QUESTION WHERE TESTID=1 ORDER BY RAND() LIMIT 10;
Now I need to change this query to Hibernate. Did a bit of googling but couldn't find the answer. Can someone provide help on this?
The random function is different between each underlying DB and is not a standard part of SQL92.
Given that you will need to implement a SQLDialect for the given database type you are using.
eg:
class PostgresSQLDialect extends org.hibernate.dialect.PostgreSQLDialect {
PostgresSQLDialect() {
super()
registerFunction( "rand", new NoArgSQLFunction("random", Hibernate.DOUBLE) );
}
}
Then you will need to define that dialect in the config
hibernate {
dialect='com.mycompany.sql.PostgresSQLDialect'
}
According to this post, you can do that :
String query = "from QUESTION order by newid()";
Query q = session.createQuery(query);
q.setMaxResults(10);
Not sure if it will work (especially for the random part), but you can try it :)