SPRING|Java - Use IN clause with SpEl in query - java

I got an enum (ClubRole) which got a method returning a collection of values from this enum. I trying to call this method from inside the query using SpEl.
#Query("select m from ClubMember m " +
"where m.student = :student " +
"and m.role in :#{#role.getParents()}"
)
List<ClubMember> findByRoleWithInheritance(#Param("student") Student student, #Param("role") ClubRole role);
This passes the build, and the application runs but when this method's called I got ``No parameter binding found for name role!; nested exception is java.lang.IllegalArgumentException: No parameter binding found for name role!
I tried different ways but none worked. I would like to know if it's possible to use SpEl in this situation, and if so how ?

Looks like this is an issue in spring-data-jpa. I could see people discussing same issue on spring-blog. Not sure whether there is an open issue for this.
You can try following as a workaround.
#Query("select m from ClubMember m " +
"where m.student = :#{#student}" +
"and m.role in :#{#role.getParents()}"
)
List<ClubMember> findByRoleWithInheritance(#Param("student") Student student, #Param("role") ClubRole role);
Or you can try with index access for second parameter like #{[1].getParents()}
this might help.

Related

JPA Passing a list of Strings in to IN clause in a native query (using citext)

I am trying to pass a list of Strings in to IN clause in a native query using citext for a case insensitive search. Everytime I try to test this query out using postman I get the following error:
org.hibernate.QueryException: Named parameter not bound : ingredientFilter
Below is the query I am trying to test:
#Query(value = "select personal_recipes.name, personal_recipes.type, personal_recipes.comments, " +
"personal_recipes.instructions, personal_recipes.rating, ingredients.name, ingredients.quantity " +
"from personal_recipes " +
"inner join ingredients on personal_recipes.name = ingredients.recipe_name " +
"where (ingredients.name::citext in (:ingredientFilter))" , nativeQuery = true)
List<PersonalRecipesEntity> getPersonalRecipesByIngredient(#Param(value = "ingredient") List<String> ingredientFilter);
I am confused as this query works when I test it out in Dbeaver.
I tried removing the brackets around :ingredientFilter. It did not change anything. I am new to Spring boot and havent been able to find anything online.
Parameters can be exposed via the name declared using #Param. You should rename ingredient by ingredientFilter. You can find more about the subject here

Why does my JpaRepository (spring-data-jpa) custom query return me an empty list?

i'm trying to develop a webapp where users post their ads, I'm currently working on the research an ad section, it's just a form that sends a search model (it has a string which is the text written on the search bar and some non-required filters) to the backend (spring boot), the backend gets the string and gives it to a JpaRepository method that should do a query on my oracle database and give me back the result set as a list of AdEntity, only problem is the list is always empty, this is the method:
#Query(value = "select distinct a.ann_id, a.nome, a.autore, a.descrizione, a.prodotto, a.prezzo "
+ "from annunci a, prodotti p "
+ "where a.prodotto = p.prod_id "
+ "and (a.nome like '%:main%' or p.nome like '%:main%')", nativeQuery = true)
public List<AnnuncioEntity> searchWithoutFilters(String main);
and this is where I call it:
#PostMapping("/")
public List<FullAnnuncio> searchAnnunci(#RequestBody SearchEntity search) {
List<AnnuncioEntity> li = annuncioDAO.searchWithoutFilters(search.getMain());
return null;
}
The li list is always empty (checked with debugger) and I have no idea how to fix it, I'm sure the query works and produces the expected resultSet as I tried it on sqlDeveloper first, and no the string I get from search isn't null
Help pls I'm new to these things as I'm not even a junior programmer lmao
Done, the Like clause on jpa repository kinda works like dodoo so I had to write it like this:
LIKE CONCAT(CONCAT('%', :main), '%')
(the sintax is correct only with oracle databases tho so be careful, for mySql and others write it like this:
LIKE CONCAT('%', :param, '%')
thanks #Arnaud
Try changing the query ":main" to "?1" in both occurrences

Spring Repositories and DATA_FORMAT with nativeQuery=false

I am trying do something super simple but with Spring Repositories somethings is a bit hard. Basically I wanted to group by with DATE_FORMAT, example:
#Query("SELECT " +
" new users.bridge.models.dto.PerformanceDTO(sum(t.gl), sum(t.gl)) " +
"FROM " +
" Transaction t " +
"GROUP BY DATA_FORMATE(t.createdDate,'%Y-%m-%d')")
But it throws a syntax error. Is there a way to do that with spring repositories? I don't want to use nativeQuery=true flag, otherwise I can not use this syntax
new gara.users.bridge.models.dto.PerformanceDTO(sum(t.gl), sum(t.gl))
UPDATE:
The erros are:
all the java stack is quite big but:
org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: asc near line 1, column 180 [SELECT new gara.users.bridge.models.dto.PerformanceDTO(sum(t.gl), sum(t.gl),t.createdDate) FROM gara.model.db.Transaction t GROUP BY DATE_FORMAT(t.createdDate,'%Y-%m-%d') asc]
If you specify nativeQuery=false (the default) you need to use valid JPQL.
JPQL doesn't know the function DATE_FORMAT but you can use the generic FUNCTION function which allows you to call arbitrary SQL functions.
So a group by clause like this should work: GROUP BY FUNCTION('DATA_FORMAT', t.createdDate,'%Y-%m-%d')
Just be aware that such queries aren't portable between databases.
but with Spring Repositories somethings is a bit hard.
You can always fall back on custom method implementations which shouldn't be much harder than implementing your repository yourself in the first place.

Like clause in JPA 2 TypedQuery works only for some name params and for others not

I'm currently having a little issue with JPA 2 and Typed Query.
I'm creating a search feature in my project using LIKE clause, however when I try to search for a string like "marina" it no works, it works only when I type "marin", even when exists in the database the name marina.
This is my code:
StringBuilder builder = new StringBuilder("select u from User u"
+ " where (u.login LIKE :regex OR u.fullname LIKE :regex)"
+ " AND (u.status <> :status)"
+ " order by u.fullname");
TypedQuery<User> query = jpaAPI.em().createQuery(builder.toString(),User.class);
query.setParameter("status", statusTypeDeleted());
query.setParameter("regex", "%"+regex+"%");
query.setFirstResult(init);
query.setMaxResults(end);
So, does anyone know where is the problem?
Ok. I solved this problem right now.
The problem is on this line:
query.setFirstResult(init);
The value I was passing to this method was 1 instead 0. How just exist only one entity with name "marina", the query result nothing, since the first result should be 0.

I need help with this error: java.lang.NoSuchMethodError

I have this Java code (JPA):
String queryString = "SELECT b , sum(v.votedPoints) as votedPoint " +
" FROM Bookmarks b " +
" LEFT OUTER JOIN Votes v " +
" on (v.organizationId = b.organizationId) " +
"WHERE b.userId = 101 " +
"GROUP BY b.organizationId " +
"ORDER BY votedPoint ascending ";
EntityManager em = getEntityManager();
Query query = em.createQuery(queryString);
query.setFirstResult(start);
query.setMaxResults(numRecords);
List results = query.getResultList();
I don't know what is wrong with my query because it gives me this error:
java.lang.NoSuchMethodError: org.hibernate.hql.antlr.HqlBaseParser.recover(Lantlr/RecognitionException;Lantlr/collections/impl/BitSet;)V
at org.hibernate.hql.antlr.HqlBaseParser.fromJoin(HqlBaseParser.java:1802)
at org.hibernate.hql.antlr.HqlBaseParser.fromClause(HqlBaseParser.java:1420)
at org.hibernate.hql.antlr.HqlBaseParser.selectFrom(HqlBaseParser.java:1130)
at org.hibernate.hql.antlr.HqlBaseParser.queryRule(HqlBaseParser.java:702)
at org.hibernate.hql.antlr.HqlBaseParser.selectStatement(HqlBaseParser.java:296)
at org.hibernate.hql.antlr.HqlBaseParser.statement(HqlBaseParser.java:159)
at org.hibernate.hql.ast.QueryTranslatorImpl.parse(QueryTranslatorImpl.java:271)
at org.hibernate.hql.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:180)
at org.hibernate.hql.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:134)
at org.hibernate.engine.query.HQLQueryPlan.(HQLQueryPlan.java:101)
at org.hibernate.engine.query.HQLQueryPlan.(HQLQueryPlan.java:80)
at org.hibernate.engine.query.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:94)
at org.hibernate.impl.AbstractSessionImpl.getHQLQueryPlan(AbstractSessionImpl.java:156)
at org.hibernate.impl.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:135)
at org.hibernate.impl.SessionImpl.createQuery(SessionImpl.java:1650)
Thanks.
You definitely have an issue with the version of hibernate and ANTLR jars that you are using. The recover method wasn't present in the ANTLR Parser class until version 2.7.6? If you are using an earlier version of ANTLR, such as 2.7.2, then you will see this problem.
Using maven can cause this sort of situation, where you depend on Hibernate and its transitive dependencies, but something 'closer'; e.g. Struts; providers a different, earlier version of ANTLR and that earlier version gets resolved in your application.
If you can provide the version of jars involved, we would be able to help some more. Once you have fixed the issue with the jar versions, you should get a more revealing error message which shows what is wrong with your HQL expression.
Stab in the dark - Are you sure you have a consistent set of jars - perhaps you need to get the antlr jar that comes with the hibernate distribution you are using...
I've found the problem:
because this is a native query, java classes for this 2 tables must have some special attributes:
in Bookmarks.java class
#OneToMany(mappedBy = "bookmarkId")
private Collection votesCollection;
and in Votes.java class
#JoinColumn(name = "bookmark_id", referencedColumnName = "bookmark_id")
#ManyToOne
[private Bookmarks bookmarkId;
and i have also changed the query to work
tring queryString = "SELECT b, sum(v.votedPoints) " +
"FROM Bookmarks b " +
"LEFT OUTER JOIN b.votesCollection v " +
"WHERE b.userId = 101 " +
"GROUP BY b.organizationId " +
"ORDER BY sum(v.votedPoints) asc ";
thanks for the help
May be you have some double-quotes " missing or which should be doubled in your HQL.
Illustration here.
Or you miss some simple quotes as illustrated there
The query seems to be invalid unless it's an artifact of formatting.
I think you meant this:
Select b, ...
to be:
Select b.organizationId, ...
??
I have the consistent set of jars because simple queries like this one
"SELECT b FROM table_name b WHERE b.userId = 102 "
are working. I have verified all double quotes and everything is alright.
My database is: mysql, and I use jpa to connect to it. I don't know what is causing the problem. Maybe this type of join, i don't know
Er, isnt your query trying to select b which is a table alias and thats not allowed as far as I know.
I'd probably guess that something is going wrong with your query, because the method HqlBaseParser fails to lookup is called recover(RecognitionException, Bitset). Perhaps this query fails for some reason the other simpler queries don't (and the NoSuchMethod exception is thrown when attempting to recover from that error).
java.lang.NoSuchMethodError: org.hibernate.hql.antlr.HqlBaseParser.recover(Lantlr/RecognitionException;Lantlr/collections/impl/BitSet;)V
Your query is still wrong. Maybe it works with your driver/db but it isn't standard SQL. You should be selecting b.* or b.organizationId.

Categories