i want to select rows from a table in JPA, my query paramter could be null.
So if it is null i want to consider all values for that attribute in that table.
Here is my code :
#Query("SELECT art FROM ArtWork art INNER JOIN art.subjects subject "
+ "INNER JOIN art.styles style "
+ "INNER JOIN art.collections collection "
+ "INNER JOIN art.priceBuckets priceBucket "
+ " WHERE ((subject.title) in (:subjectList) "
+ "AND (style.title) in (:styleList)"
+ "AND (collection.title) in (:collectionList)"
+ "AND (priceBucket.title) in (:priceBucketRangeList)"
+ "AND (art.medium is NULL OR art.medium = :medium)"
+ "AND (art.orientation) LIKE:orientation)"
+ ")")
In the code if :medium is null then i want it search on all mediums in the table
Thanks
Related
I want to delete an "order" from my database using the primary key, orderID. The orderID is a foreign key in orderItem, OrderItem has a foreign key in foodItem called foodItemID, foodItem has a foreign key in menu called menuID.
Below is my query:
"DELETE FROM orders, orderitem, fooditem, menu " +
"USING orders " +
"INNER JOIN orderitem " +
"WHERE orderID = " + "'" + orderID + "' " + " AND orders.orderID = orderItem.orderID " +
"INNER JOIN foodItem " +
"WHERE orderItem.foodItemID = foodItemID.foodItemID " +
"INNER JOIN Menu " +
"WHERE foodItem.menuID = menu.menuID";
I am coding in JAVAFX..
The error I receive is:
Caused by: java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'INNER JOIN foodItem WHERE orderItem.foodItemID = foodItemID.foodItemID INNER JOI' at line 1
You don't join WHERE, you join ON something. So
"DELETE FROM orders, orderitem, fooditem, menu " +
"USING orders " +
"INNER JOIN orderitem " +
"ON orderID = " + "'" + orderID + "' " + " AND orders.orderID = orderItem.orderID " +
"INNER JOIN foodItem " +
"ON orderItem.foodItemID = foodItemID.foodItemID " +
"ON JOIN Menu " +
"ON foodItem.menuID = menu.menuID";
Also, this part
"ON orderID = " + "'" + orderID + "' " + "
Is a SQL Injection waiting to happen. You should use prepared statements instead. How you use them depends on what library/framework you're using to connect to the db (which you didn't specify).
I came across a problem that I cannot think of a solution.
So I got this piece of code:
public List<Post> getPosts(List<PostStrategy> allowedStrategyList, Set<Tag> allowedTags, int page, int resultsPerPage) {
return entityManager.createQuery("select post from Post post join post.tags tag where post.postStrategy in (:postStrategyList) and (:allowedTagsSize = 0 or tag in (:allowedTags))", Post.class)
.setParameter("postStrategyList", allowedStrategyList)
.setParameter("allowedTags", allowedTags)
.setParameter("allowedTagsSize", allowedTags.size())
.setFirstResult((page - 1) * resultsPerPage)
.setMaxResults(resultsPerPage)
.getResultList();
}
The problem with this piece of code is that when someone searches with more than one tag (for example: #video, #image), it returns both posts with two tags and one tag.
I would like it to return a post with both #video, and #image in its tags. For it to work, I somehow need to check if the list contains all elements of another list.
I searched for a solution for a while and tried different approaches so far, nothing.
I tried replacing "tag in (:allowedTags)" with "post.tags in (:allowedTags)" but that throws that my SQL is invalid.
Two years later I got my answer. I am now using Spring Boot and SpEL expressions so bear with me. This query does a little more than just my original idea but you can extract what you need from it.
#Override
#Query("select p from PostSnapshot p where " +
// Tags
"(:#{#query.withTags.size()} = 0 or p.id in (" +
"select post.id from PostSnapshot post inner join post.tags tag " +
"where tag.value in (:#{#query.withTags}) " +
"group by post.id " +
"having count(distinct tag.value) = :#{#query.withTags.size() * 1L}" +
")) and (:#{#query.withoutTags.size()} = 0 or p.id not in (" +
"select post.id from PostSnapshot post inner join post.tags tag " +
"where tag.value in (:#{#query.withoutTags}) " +
"group by post.id " +
"having count(distinct tag.value) = :#{#query.withoutTags.size() * 1L}" +
")) " +
// Artists
"and (:#{#query.withArtists.size()} = 0 or p.id in (" +
"select post.id from PostSnapshot post inner join post.artists artist " +
"where artist.preferredNickname in (:#{#query.withArtists}) " +
"group by post.id " +
"having count(distinct artist.preferredNickname) = :#{#query.withArtists.size() * 1L}" +
")) and (:#{#query.withoutArtists.size()} = 0 or p.id not in (" +
"select post.id from PostSnapshot post inner join post.artists artist " +
"where artist.preferredNickname in (:#{#query.withoutArtists}) " +
"group by post.id " +
"having count(distinct artist.preferredNickname) = :#{#query.withoutArtists.size() * 1L}" +
")) " +
// Title like words
"and lower(p.title) like concat('%', lower(:#{(#query.words.isEmpty()) ? '' : #query.words.toArray()[0]}) ,'%')" +
// OwnerId
"and p.ownerId = :ownerId")
Page<PostSnapshot> findAllByOwnerIdAndQuery(#Param("ownerId") UUID ownerId, #Param("query") PostQuerySearchDTO query, Pageable pageable);
below is the query which is working fine
#Query("SELECT city.id as id,city.latitude as latitude, city.longitude as longitude, \n" +
"(SELECT cityTrans.name " +
" FROM city.listOfCityTrans as cityTrans " +
" WHERE cityTrans.languageId=:languageId AND cityTrans.cityId=city.id)" +
" AS name, \n" +
"(SELECT provinceTrans.name " +
" FROM city.province AS province JOIN province.listOfProvinceTrans AS provinceTrans " +
" WHERE provinceTrans.languageId=:languageId AND provinceTrans.provinceId=city.provinceId)" +
" AS provinceName, \n" +
"(SELECT countryTrans.name " +
" FROM city.province AS province JOIN province.country.listOfCountryTrans AS countryTrans " +
" WHERE countryTrans.languageId=:languageId AND countryTrans.countryId=city.provinceId)" +
" AS countryName, province.id as provinceId,province.countryId as countryId \n" +
" FROM City as city")
Page<CitySummary> findCities(#Param("languageId") Integer languageId, Pageable pageable);
but when i pass sort param ?sort=name
then it is creating wrong query
SELECT city.id as id,city.latitude as latitude, city.longitude as longitude,
\n(SELECT cityTrans.name FROM city.listOfCityTrans as cityTrans WHERE
cityTrans.languageId=:languageId AND cityTrans.cityId=city.id) AS name,
\n(SELECT provinceTrans.name FROM city.province AS province JOIN
province.listOfProvinceTrans AS provinceTrans WHERE
provinceTrans.languageId=:languageId AND
provinceTrans.provinceId=city.provinceId) AS provinceName, \n(SELECT
countryTrans.name FROM city.province AS province JOIN
province.country.listOfCountryTrans AS countryTrans WHERE
countryTrans.languageId=:languageId AND
countryTrans.countryId=city.provinceId) AS countryName, province.id as
provinceId,province.countryId as countryId \n FROM
com.pro.api.model.City as city order by cityTrans.name asc
^
can anyone tell why this is happening?
I think the MVC to JPA path only works for entity definitions, not Object[] results, so if your City entity doesn't have a name property, then JPA would try to find another field match, which would be the cityTrans
I would like to supply collection/arrays in the "IN" parameter but I got
When I used array:
org.jooq.exception.SQLDialectNotSupportedException: Cannot bind ARRAY types in dialect MYSQL
When I used list:
org.jooq.exception.SQLDialectNotSupportedException: Type class java.util.Arrays$ArrayList is not supported in dialect DEFAULT
Here is my plain sql:
String sql = "SELECT SUM(foo.reply = 'Y') yes " +
"FROM foo " +
"LEFT OUTER JOIN bar " +
"ON foo.id = bar.foo_id " +
"WHERE " +
"foo.id = ? " +
"AND foo.some_id IN (?) "; //this is the part I would like to use array or list
Here's how I execute it
dslContext.fetch(sql, val(fooId), val(someIds))
.into(Summary.class);
You can't do that with single bind variables (except in PostgreSQL with arrays). But you can use nested plain SQL query parts in jOOQ as such:
String sql = "SELECT SUM(foo.reply = 'Y') yes " +
"FROM foo " +
"LEFT OUTER JOIN bar " +
"ON foo.id = bar.foo_id " +
"WHERE " +
"foo.id = {0} " +
"AND foo.some_id IN ({1}) "; // Use the {0}, {1} placeholders
And then
dslContext.fetch(sql,
val(fooId),
DSL.list(someIds.stream().map(DSL::val).collect(toList())))
.into(Summary.class);
See also DSL.list(QueryPart...)
I have a case similar to the one described in this question, I wrote an identical query which works, but when I try to write it as a jpql named query, I'm getting an error.
My query:
#NamedQuery(
name = "findRankingsBetween",
query = "SELECT rt FROM Rankingtable rt " +
"INNER JOIN " +
"(SELECT teamId, MAX(lastupdate) as MaxDateTime " +
"FROM Rankingtable " +
"GROUP BY teamId) grouped " +
"ON rt.teamId = grouped.teamId " +
"AND rt.lastupdate = grouped.MaxDateTime " +
"WHERE rt.lastupdate BETWEEN :from AND :to"
)
Error:
Error in named query: findRankingsBetween: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: ( near line 1, column 79
How to write the query properly in jpql?
As noted in this answer, a subquery in JPQL can only occur in select and where clauses.
Hibernate doc.
An equivalent query in JPQL is:
"SELECT rt FROM Rankingtable rt " +
"WHERE rt.lastupdate = (SELECT MAX(r2.lastupdate) " +
"FROM Rankingtable r2 " +
"WHERE r2.teamid = rt.teamid) " +
"AND rt.lastupdate BETWEEN :from AND :to"