How to select object by another object's field - spring

I have a 2 entity - Klient and DocAcc. For access to my data I use Spring Data. Here is my repository:
public interface DocAccRepository extends CrudRepository<DocAcc, Long> {
#Query("select d from DocAcc d where d.sals = klient.sals")
List<DocAcc> findByKlient(Klient klient);
}
this code didn't work. Error:
Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: Invalid path: 'klient.sals' [select d from vap.entity.DocAcc d where d.sals = klient.sals]
My entity wired more than one field. How can I acces to object parameters inside Query?

You can use SpEL expressions in #Query
public interface DocAccRepository extends CrudRepository<DocAcc, Long> {
#Query("select d from DocAcc d where d.sals = :#{#klient.sals}")
List<DocAcc> findByKlient(#Param("klient") Klient klient);
}
More info here: https://spring.io/blog/2014/07/15/spel-support-in-spring-data-jpa-query-definitions

Related

does JPQL not have an * symbol?

#Repository
public interface ParticipantRepository extends CrudRepository<Participant,Integer> {
#Query("select e from Participant e WHERE e.event.venue =:venue")
List<Participant> getParticipantsByEventVenue(String venue);
}
As you can see here ^ I have to use e to represent the * symbol. Is that just how JPQL works?
is there an * symbol in JPQL?
Yes, it is particular syntax for JPQL. But if you like to use native SQL query, it is also possible as follows:
#Repository
public interface ParticipantRepository extends
JpaRepository<Participant,Integer> {
#Query("select * from Participant e WHERE
e.event.venue =:venue",nativeQuery = true)
List<Participant> getParticipantsByEventVenue(String venue);}
also it is recommender to use JpaRepository instead of crudRepository.

Spring data jpa #Query - Cannot create an "AS" alias for a result map

I map the result of the following JPQL-Query directly to a SpecialCustomDto object instead of the used javax.persistency entity object MyEntity. But I do not know, how to access the COUNT(DISTINCT e.attributeB), which will be mapped to the SpecialCustomDto.
This is the query.
#Repository
public interface MyEntityRepository extends JpaRepository<MyEntity, Long> {
#Query("SELECT new com.test.SpecialCustomDto(e.attributeA, COUNT(DISTINCT e.attributeB)) as specialCustomDto "
+ "FROM MyEntity e WHERE 5 = specialCustomDto.count GROUP BY e.attributeA")
List<SpecialCustomDto> getSpecialCustomDtos();
}
As soon as I start the spring-boot application, Hibernate throws me following error:
Caused by: java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: as near line 1, column...
I don't know how to access the aggregated COUNT(DISTINCT e.attributeB) element of the newly created SpecialCustomDto. Without the additional WHERE-clause, the mapping works as expected.
Aggregate functions can be used as condition using HAVING. The same as in native SQL.
SELECT new com.test.SpecialCustomDto(e.attributeA, COUNT(e.attributeB))
FROM MyEntity e
GROUP BY e.attributeA
HAVING COUNT(e.attributeB) = 5
Remove the alias, move the condition to a HAVING-clause since it operates on an aggregate-value and just put the count-expression in there.
public interface MyEntityRepository extends JpaRepository<MyEntity, Long> {
#Query("SELECT new com.test.SpecialCustomDto(e.attributeA, COUNT(DISTINCT e.attributeB)) "
+ "FROM MyEntity e "
+ "GROUP BY e.attributeA "
+ "HAVING COUNT(DISTINCT e.attributeB) = 5")
List<SpecialCustomDto> getSpecialCustomDtos();
}
Note: The #Repository is superfluous.

select distinct values using spring data rest

I'm using java 8 and spring-data-rest to create API on my data.
I have a table Car(id, name, date...)
I'm trying to have an endpoint to retrieve distinct car names.
here's my Repository :
#RepositoryRestResource(path = "cars")
public interface CarRepository extends JpaRepository<Car, Long> {
//What i want to do
//#Query(value = "select distinct c.name as name from Car c")
#Query(value = "select distinct c from Car c")
List<Car> findDistinctName();
}
The query commented does not work , i have an exception
java.lang.IllegalArgumentException: PersistentEntity must not be null!
apparently this is the normal behavior of SDR.
I tried another solution by using Projections
#Projection(name = "name", types = {Car.class})
public interface CarName {
String getName();
}
but i cant get the distinct values, any idea?
Thank you :)
All you need, to do if you need a distinct list of cars, is such this query method:
public interface CarRepository extends JpaRepository<Car, Long> {
List<Car> findDistinctBy();
}
Spring Data JPA supports the Distinct keyword in repository query methods to set a distinct flag on the query to be created.
I found an (ugly) workaround, using jpql :
#Query(value = "select c from Car C WHERE c.id IN (SELECT min(ca.id) FROM Car ca Group by ca.name)")
I think you should remove the #Query annotation.
Just
List<Car> findDistinctName(); or List<Car> findNameDistinct(); should suffice.
It will automatically generate the query select c.name from Car c

Hibernate JPA issue doesnt apply IS-A Relationship of table at some times

I have a Parent Table A and extended Child tables B and C
ex:
public class A {
private Long id;
//getters setters//
}
public class B extends A{
private String name;
//getters setters//
}
now at my repository,
public interface B extends JpaRepository<B, Long> {
#Query("select a from A a")//--This works
B getAll()
#Query("select a.id, b.name from A a join a.B b")//-- This doesn't
B getSpecificCols()
}
I need an explanation since "B is an A" that's why getAll() works
how come getSpecificCols() isn't working?
Error is
java.lang.ClassCastException: java.lang.Long cannot be cast to <package>.B
BTW I'm using Hibernate Spring
The query returns a long (a.id) and a string (b.name). The interface assumes that you return an entity (B). The returned id cannot be cast into a B, so you get a ClassCastException. If you want individual fields you can return List<Object[]>, where each record will be an array with id and name. Or you can use a projection (https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#projections).
By the way, does the first query really work when there are A entities in the database that are not B entities, for example if A also has a subclass C? It looks plain wrong to select the base class and return the derived class without filtering. I would select from B to return B.
After reading documentation what I needed all along was to put constructors in my entity/table where you put what specific parameters you need.

Ehcache not working with Spring boot application

I have a Spring boot application where i am using ehcache. The Ehcache is working fine if i have only one entity class but if i have more than 1 entity class the ehcache is not working and i am getting the below error:-
java.lang.ClassCastException: com.myapp.beans.Contact cannot be cast to com.myapp.beans.Department
at com.sun.proxy.$Proxy102.findOneById(Unknown Source) ~[na:na]
at com.myapp.service.impl.DepartmentServiceImpl.show(DepartmentServiceImpl.java:19) ~[classes/:na]
My Java Code :-
DepartmentRepository.java
#Repository
public interface DepartmentRepository extends JpaRepository<Department, Integer> {
#Cacheable(value="appCache")
#Query("select d from Department d where d.id=:id")
Department findOneById(#Param("id") int id);
}
ContactRepository
#Repository
public interface ContactRepository extends JpaRepository<Contact, Integer> {
#Cacheable(value = "appCache")
#Query("select c from Contact c where c.id=:id")
Contact findOneById(#Param("id") int id);
}
ehcache.xml
<ehcache>
<cache name="appCache" maxBytesLocalHeap="50m" timeToLiveSeconds="100"></cache>
</ehcache>
The entire code is available at - https://github.com/iftekharkhan09/SpringCaching . Any help is highly appreciated.
Probably you have "key collisions", because your cache's names are identical.
I suggest to rename the caches, like this:
#Cacheable(value="appCache1")
#Query("select d from Department d where d.id=:id")
Department findOneById(#Param("id") int id);
#Cacheable(value = "appCache2")
#Query("select c from Contact c where c.id=:id")
Contact findOneById(#Param("id") int id);
Also you have to create each of these caches in ehcache.xml
Another way - use key in your cache, you can read about it here

Resources