Spring boot JPA filter by join table - spring

I cant find something concrete in the docs (https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods.query-creation)
and no satisfying answere in several blogs.
so here my question.
I have table Entity like:
#Entity
#Table(name = "workstation")
public class Workstation
{
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "userid", nullable = false)
public User user;
}
And the user table Entity:
public class user
{
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "ID", unique = true, nullable = false)
public Integer id;
#Column(name = "age", nullable = false)
public int age
}
Now I would like to have a query in my Repository like this:
public interface WorkstationRepo extends CrudRepository<Workstation, Long> {
findByUserAgeLesserThan(int maxAge);
}
Means I want to find all user who are under a certain age through my Workstation Entity.
And is it possible without a #Query annotation? Or/And how should it look like?

Try this
List<Workstation> findByUserAgeLessThan(int maxAge);
Alternatively you can also write your query
#Query("Select w from Workstation w where w.user.age < :maxAge")
List<Workstation> findByUserAgeLesserThan(#Param("maxAge") int maxAge);

This works:
#Query("SELECT w from Workstation w INNER JOIN w.user u where u.age < ?1")
List<Workstation> findByUserAgeLessThan(int age);

You should have something like this:
#Query("SELECT w from Workstation w INNER JOIN w.user u where u.age < :age")
List<Workstation> findByUserAgeLessThan(#Param("age") int age);
Basically, you need to JOIN the tables using JPQL.

Related

Spring JPA - Is there a good way for inner join between entities or the only way is JPQL?

I have the following Entities:
#Entity
public class Organisation {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
// ...
}
#Entity
public class Section{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
// ...
#ManyToOne
#JoinColumn(name = "organisation_id", nullable = false)
private Organisation organisation;
}
#Entity
public class SubSection {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
// ...
#ManyToOne
#JoinColumn(name = "section_id")
private Section section;
}
Now I want to find all SubSections by Organisation Id. Right now I am doing it using JPQL at the SubSectionRepository as above:
public interface SubSectionRepository extends JpaRepository<SubSection, Long>{
#Query(value = "SELECT ss.* FROM sub_section as ss INNER JOIN section as s ON ss.section_id = s.id WHERE s.organisation_id = ?1", nativeQuery = true)
List<SubSection> findByOrganisation(Long organisationId);
}
Is there any way that I can make INNER JOIN using the JpaRepository interface?
Did you try this way
subsectionRepository.findBySectionOrganizationId(long organizationId)
Update your method to
public interface SubSectionRepository extends JpaRepository<SubSection, Long> {
List<SubSection> findBySectionOrganisationId(Long organisationId);
}
Hibernate will generate something like this.
select subsec.*,
from sub_section subsec
left outer join section sec on subsection.section_id=sec.id
left outer join organisation org on section.organisation_id=org.id
where org.id=?
Don't worry about the left join term. It is actually a inner join because you have a where condition with id = on the most right table. Because of that, it effectively becomes a inner join. I.e if there is no record on the right table for that record, it will be ignored.

How to retrieve data from many to many relationship in HQL, with Spring and JPA,when the joinTable is not an entity?

I have a similar case as this question [a link] (How do I do with HQL, many to many?)
I want to have the number of users (entity 1) for each libelle of role (entity 2). I defined a relation many to many between User and Role.
I am using Spring MVC, Hibernate, MySQL and JPA.
Entity 1: User
#Entity(name = "user")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String email;
#ManyToMany(mappedBy = "user")
private List<Role> role;
Entity 2: Role
#Entity
#Table(name = "role")
public class Role {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int ID;
private String libelle;
#ManyToMany
#JoinTable(
name = "user_role",
joinColumns = { #JoinColumn(name = "ID_role") },
inverseJoinColumns = { #JoinColumn(name = "id_user") }
)
private List<User> user;
JPA repository
#Repository
public interface UserRepository extends JpaRepository<User, Long> {
#Query(value = "select new map( count(u.id) as numberOfUsers,r.libelle as roleLibelle ) FROM user u join role r where r.ID =: ???? group by r.libelle")
List<Object> countByRoleList();
I am trying to figure out what =:id proposed in the question that i mentioned, have to be in my case. Instead of the "????" i tried ID, id , ID_role. All what i get is the error
"Named parameter not bound : ".
How can i solve that?
I suppose the type of your parameter is long. it's name is abc and it refer to an id.
Follow these steps:
Remove the space in front of your param .
so you will have (=:abc) not (=: abc).
Your query depends on an external parameter, uses the #param annotation for the specified param.
so you will have
".....countByRoleList(#Param("abc") long id );"
A code exemple
#Repository
public interface UserRepository extends JpaRepository<User,Long> {
#Query(value = "select new map( count(u.id) as numberOfUsers,r.libelle as roleLibelle ) FROM user u join role r where r.ID =:abc group by r.libelle")
List<Object> countByRoleList(#Param("abc") long id);
Note: abc is a provided param . It can come from an HTML page, a function. you can also provide it manually ...

Spring Data JPA find by nested object id (nested twice)

Is it possible?
I'd like to get all AAA objects with a specific CCC.incidentAssessmentResultId id using JPARepository. Is it possible?
#Entity
#Table(schema = "aaa", name = "table")
public class AAA {
#Column(name = "kryterium")
private String criterion;
#OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
#JoinColumn(name = "id_kryterium_naruszen")
private List<BBB> violationFactors;
}
public class BBB {
#Column(name = "czynnik")
private String factor;
#Column(name = "stopien")
private float degree;
#JsonManagedReference
#OneToOne(mappedBy = "violationFactor")
private CCC incidentAssessmentFactor;
}
public class CCC {
#Column(name="komentarz")
private String comment;
#Column(name="ocena_naruszenia_wynik_id", updatable=false, insertable=false)
private Long incidentAssessmentResultId; //-> I'd like to find AAA objects with a specific incidentAssessmentResultId ID
#Column(name="czynnik_wybrany")
private Boolean factorIsSelected;
#Column(name = "wartosc_wybrana")
private float value;
#Repository
public interface ViolationCriterionRepository extends JpaRepository<AAA, Long> {
// #Query("select vc from AAA vc left join vc.violationFactors vf left join vf.incidentAssessmentFactor iaf where iaf.incidentAssessmentResultId = ?1")
List<AAA> findByViolationFactors_IncidentAssessmentFactor_IncidentAssessmentResultId(Long incidentId);
}
Now, when I call ViolationCriterionRepository .findAll() I get all data but I want to get all data but with certain CCC objects. I've tried with the method below in my Repository but I get 0 results.
UPDATE
My repo:
#Repository
public interface ViolationCriterionRepository extends JpaRepository<ViolationCriterion, Long> {
#Query("select vc from AAA vc join vc.violationFactors vf join vf.incidentAssessmentFactor iaf where iaf.incidentAssessmentResultId = ?1")
List<AAA> findByIncidentAssessmentResultId(Long incidentId);
}
In the AAAJpaRepository:
List<AAA> aaaList = findByViolationFactorsIncidentAssessmentFactorIncidentAssessmentResultId( long incidentAssessmentResultId);
And the answer is (#JB Nizet - many thanks!):
#Repository
public interface ViolationCriterionRepository extends JpaRepository<ViolationCriterion, Long> {
#Query("select vc from AAA vc join vc.violationFactors vf join vf.incidentAssessmentFactor iaf join iaf.incidentAssessment ia where ia.incidentAssessmentId = ?1 group by vc ")
List<ViolationCriterion> findIncidentAssessmentByIncidentAssessmentId(Long incidentId);
}

Selecting latest workout set by user

I'm trying to select the latest added workout set associated with a given user.
Users has sessions and sessions has sets. My entities are defined as below.
#Entity(name = "users") // Postgres doesn't like the table name "user"
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#OneToMany(mappedBy = "user")
private Set<Session> sessions;
...
#Entity
public class Session {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#ManyToOne
private User user;
#OneToMany(mappedBy = "session")
private Set<WorkoutSet> sets;
...
#Entity
public class WorkoutSet {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#OneToOne
private User user;
#ManyToOne
private Session session;
private LocalDateTime timestamp = LocalDateTime.now();
...
The following sql query seems to do the trick
select w
from workout_set w
inner join session s
on w.session_id = s.id
where s.user_id = 1
order by w.timestamp DESC
limit 1
But when I'm trying to do something like the below
#Repository
public interface WorkoutSetRepository extends CrudRepository<WorkoutSet, Long> {
#Query("select w from WorkoutSet w inner join Session s on w.session_id = s.id where s.user = :user order by w.timestamp")
List<WorkoutSet> findLastSet(User user, Pageable limit);
I get...
org.springframework.data.mapping.PropertyReferenceException: No property user found for type WorkoutSet!
Any clues about how to do the query right? I'm very open to alternative ways as well because I'd rather avoid writing jpql if possible.
Try this:
#Repository
public interface WorkoutSetRepository extends CrudRepository<WorkoutSet, Long> {
#Query("select w from WorkoutSet w inner join w.session s where s.user = :user order by w.timestamp")
List<WorkoutSet> findLastSet(#Param("user") TestUser user);
}
Note the difference in the join clause. This works with hibernate 5.0.11.

HQL query for Association

I am having below tables here but having some problem while fetching results.
#Entity
#Table(name = "USER_VW")
public class WorkspaceUserImpl
{
#JoinColumn(name = "USER_ID", insertable=false, updatable=false)
#OneToOne(targetEntity = UserImpl.class, fetch = FetchType.EAGER)
private User user;
}
#Table(name = "IK_USER")
#Inheritance(strategy = InheritanceType.JOINED)
#AttributeOverride(name = "id", column = #Column(name = "USER_ID") )
public class UserImpl extends BaseAuditable<UserIdentifier>implements User, UserAuthentication {
private static Logger log = LoggerFactory.getLogger(UserImpl.class);
#Id
#Type(type = "com.commons.UserIdentifierTypeMapper")
#Column(name = "USER_ID")
private UserIdentifier id;
}
and User
Public Inteface User
{
UserIdentifier getId();
}
Now i have written an HQL query to fetch all the data from WorkspaceUserImpl class with a given user ID for UserImpl class like below.
SELECT w from WorkspaceUserImpl w where w.user.id = : user_id;
and also tried
SELECT w from WorkspaceUserImpl as w INNER JOIN w.user as u where u.id = : user_id;
and even tried with JOIN FETCH also
and setting the parameter user_id with some say 1234.
but am getting List as emply for the partcular ID but in DB its having 5 records.
am i making any query mistake here? kindly advice..
Have you tried below query:
from WorkspaceUserImpl as w JOIN FETCH w.user as u where u.id = : user_id;

Resources