HQL error in named query subselect - java

This HQL results in the tremendously helpful "error in named query" message
"FROM courseform c WHERE c.application.application IN
(SELECT a.application FROM application a WHERE a.applicant=: applicant)"
The CourseForm has a OneToOne unidirectional relationship with the Application (this could potentially be made bidirectional if it would help). Application in turn has the same unidirectional OneToOne relationship with the Applicant. One applicant can have many applications.
Here are the (abridged) definitions
CourseForm
#Entity
#NamedQueries({
#NamedQuery(name = "CourseForm.findByApplicant",
query = "FROM courseform c WHERE c.application.application IN
(SELECT a.application FROM application a WHERE a.applicant=: applicant)") })
public class CourseForm implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
long id;
#Enumerated(EnumType.STRING)
private Career career;
private String academicPlan;
private String courseName;
#Enumerated(EnumType.STRING)
private ModeOfAttendance modeOfAttendance;
#OneToOne
#JoinColumn(name = "application_fk")
private Application application;
...
}
Application
#Entity
public class Application implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
long applicationNumber;
#OneToOne
#JoinColumn(name = "applicant_fk")
private Applicant applicant;
#Type(type = "org.jadira.usertype.dateandtime.joda.PersistentLocalDateTime")
private LocalDateTime lastUpdate = LocalDateTime.now();
#Type(type = "org.jadira.usertype.dateandtime.joda.PersistentLocalDateTime")
private LocalDateTime submitted = null;
public Application() {
}
Applicant
#Entity
#NamedQueries({ #NamedQuery(name = "Applicant.findByApplicantID",
query = "FROM Applicant a WHERE a.applicantID= :applicantID") })
public class Applicant implements Serializable {
private static final long serialVersionUID = -7210042752148566673L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
long id;
private String applicantID;
Applicant() {
}

Ok, according to Mark, right answer is
FROM courseform c WHERE c.application.applicant =: applicant

I think the error is with FROM courseform c WHERE c.application.application.You have used c.application.application in where clause
It should be FROM courseform c WHERE c.application

You can change to:
FROM courseform c WHERE c.application.applicationNumber IN (SELECT a.applicationNumber FROM application a WHERE a.applicant=: applicant)

Related

duplicate [ID] alias error for sql statement with join

I created a search button with a SQL query which is including JOIN 2 times, but its throwing error like:
org.hibernate.loader.NonUniqueDiscoveredSqlAliasException: Encountered a duplicated sql alias ID during auto-discovery of a
native-sql query
This is the Repository method:
#Query(value = "select * from reports r join patients p on r.patient_id = p.id join lab_technicians lt on r.lab_technician_id = lt.id where p.name like '%:patientName%' and lt.name like '%:labTechnicianName%' and p.identity_no like '%:patientIdentityNo%'", nativeQuery = true)
List<Report> findBySearch(#Param("patientName") String patientName, #Param("labTechnicianName") String labTechnicianName, #Param("patientIdentityNo") String patientIdentityNo);
To make you understand the project templates, these are the entities classes:
Person class:
#MappedSuperclass
public abstract class Person {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "name")
private String name;
Patient class:
#Entity
#Table(name = "patients")
public class Patient extends Person{
#Column(name = "identity_no") private String identityNo;
#OneToMany(mappedBy = "patient") private List<Report> reports;
LabTechnician class:
#Entity
#Table(name = "lab_technicians")
public class LabTechnician extends Person{
#Column(name = "hospital_id")
private String hospitalId;
#OneToMany(mappedBy = "labTechnician")
private List<Report> reports;
and lastly Report class:
#Entity
#Table(name = "reports")
public class Report {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#ManyToOne
#JoinColumn(name = "lab_technician_id")
private LabTechnician labTechnician;
#ManyToOne
#JoinColumn(name = "patient_id")
private Patient patient;
#Column(name = "file_number")
private String fileNumber;
#Column(name = "diagnostic")
private String diagnostic;
#Column(name = "detail_of_diagnostic")
private String detailOfDiagnostic;
#Column(name = "date_of_report")
private Date dateOfReport;
I changed List in #OneToMany relationships to Set but its not changed anything
#Query(value = "select * from reports r join patients p on r.patient_id =
p.identity_no join lab_technicians lt on r.lab_technician_id =
lt.hospital_id where p.name like '%:patientName%' and lt.name like
'%:labTechnicianName%' and p.identity_no like '%:patientIdentityNo%'",
nativeQuery = true)
List<Report> findBySearch(#Param("patientName") String patientName,
#Param("labTechnicianName") String labTechnicianName,
#Param("patientIdentityNo") String patientIdentityNo);
Use this query it will work fine

Hibernate one to one criteria fetching

I am using hibernate one to one mapping between car and person table. But a person might have car and might not have a car. now while fetching the records from the person table using hibernate criteria , I want to fetch only those persons who have a car, i.e only those entries in person table for which a corresponding entry in car table exists. How this can be done using hibernate criteria/alias?
Below is the piece of code. kindly help with the criteria or alias that has to written to fetch result:
#Getter
#Setter
#Entity
#Table(name = "Person")
public class Person implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "Person_ID")
private Long personId;
#OneToOne(mappedBy = "personAsset", cascade = CascadeType.ALL)
private Car car;
}
#Getter
#Setter
#Entity
#Table(name = "Car")
public class Car implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "Car_ID")
private Long carId;
#OneToOne
#JoinColumn(name = "Person_ID")
private Person personAsset;
}
what you are looking for is the cascadeType orphanRemoval=true on the #OneToOne annotation.
here is your class how would look like :
#Getter
#Setter
#Entity
#Table(name = "Car")
public class Car implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "Car_ID")
private Long carId;
#OneToOne(fetch=FetchType.EAGER , cascade=CascadeType.ALL, orphanRemoval=true)
#JoinColumn(name = "Person_ID")
private Person personAsset;
}
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Person> query = cb.createQuery(Person.class);
Root<Person> person = query.from(Person.class);
Predicate predicate = cb.isNotNull(person.join("car"));
predicates.add(predicate );

Updating Value in table based on foreign key association in spring jpa

I have two tables.
Table A
#Entity
public class MerchantsInfo implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String firstName;
private String lastName;
}
Table B
#Entity
public class MerchantsSdkConfig implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#JoinColumn( name = "merchantId")
#ManyToOne(fetch = FetchType.LAZY)
private MerchantsInfo merchant;
private String applicationId;
}
Now I want to update applicationId in Table B through the foreign key merchantId. I tried the following
#Modifying
#Query("update MerchantsSdkConfig u set u.applicationId = ?1 where u.merchantId = ?2")
public int updateApplicationId(String applicationId, Long merchantId);
But I keep getting the error below
could not resolve property: merchantId of: com.bus.api.entity.MerchantsSdkConfig [update com.bus.api.entity.MerchantsSdkConfig u set u.applicationId = ?1 where u.merchantId = ?2]
#Modifying
#Query("update MerchantsSdkConfig u set u.applicationId = ?1 where u.merchant.id = ?2")
public int updateApplicationId(String applicationId, Long merchantId);
Thanks to the comments on the question. I was able to solve the following with the above.
Apparently I had to reference/access the mapped table, before getting to the column I needed.

<expression> expected got <from> in spring-data hibernate

Working with spring-data and hibernate and trying to write this request in a repository :
#Query("select u from AppUser u inner join u.roles r inner join u.contrats c where r = :role and not exists ( from c.project p where p = :project)")
My goal is to get List of AppUser (Users) from entity AppUer ,but with a condition , only those who don't have the entity project .
To explain more , there is an entity Contrat between Project and AppUser , it contains Project project , AppUser appuser .
There is a mapping between one_to_many between AppUser and Contrat(AppUser can have multiple contrats) .
Also a mapping of one_to_many between Contrat and project ( One project can have multiple contrat ) .
The problme is that this request returns a empty list while it should return a list of 12 users as they don't have the specified project i passe to it.
I remark in this request (from c.project p where p = :project) 'from' is underlined with red line saying :
<expression> expected got <from> in spring-data hibernate.
Any idea ?
Edit
Entity AppUser
#Entity
#Data
#AllArgsConstructor #NoArgsConstructor
public class AppUser implements Serializable {
#Id #GeneratedValue
private Long id;
#Column(unique = true)
private String username;
private String password;
private String prenom;
private String nom;
private Long tel;
private String cin;
private String email ;
#ManyToMany(fetch = FetchType.EAGER)
private Collection<AppRole> roles = new ArrayList<>();
#OneToMany(mappedBy = "appUser" )
#Fetch(value = FetchMode.SUBSELECT)
#JsonManagedReference(value="appuser-contrat")
private Collection<Contrat> contrats = new ArrayList<Contrat>();
public void addToContrats(Contrat contrat){
this.contrats.add(contrat);
}
}
Entity Contrat
#Entity
#Data
#AllArgsConstructor
#NoArgsConstructor
public class Contrat implements Serializable{
#Id #GeneratedValue
private Long id;
private Date dateDebut ;
private Date dateFin ;
private Long idDevloppeur;
#ManyToOne
#JoinColumn(name = "Id_Project")
#JsonBackReference(value="projet-contrat")
private Project project;
#ManyToOne
#JoinColumn(name = "Id_AppUser")
#JsonBackReference(value="appuser-contrat")
private AppUser appUser;
}
Entity Project
#Entity
#Data
#AllArgsConstructor
#NoArgsConstructor
public class Project implements Serializable{
#Id #GeneratedValue
private long id;
private String intitule;
private String description;
#OneToMany(mappedBy = "project" )
#Fetch(value = FetchMode.SUBSELECT)
#JsonManagedReference(value="projet-contrat")
private Collection<Contrat> contrats = new ArrayList<Contrat>();
public void addToContrats(Contrat contrat){
this.contrats.add(contrat);
}
}
(Posting answer to summarize solution in comments)
In given select query "inner join u.contrats" was used, but there were no contracts entities for users. Solution: replace with "left join u.contrats".
Inner join vs left join already solved here
What's the difference between INNER JOIN, LEFT JOIN, RIGHT JOIN and FULL JOIN?

Custom #Query in Spring Data Repository through multiple entities

I have 4 JPA Entities as following:
Entity Farm :
#Entity
public class Farm implements Serializable {
#Id #GeneratedValue(strategy = GenerationType.IDENTITY)
private Long idFarm;
private String nameFarm;
}
Entity SAU :
#Entity
public class SAU implements Serializable {
#Id #GeneratedValue(strategy = GenerationType.IDENTITY)
private Long idSau;
private String nameSau;
#OneToOne
#JoinColumn(name="farm_id")
private Farm farm;
}
Entity Part :
#Entity
public class Part implements Serializable {
#Id #GeneratedValue(strategy = GenerationType.IDENTITY)
private Long idPart;
private String namePart;
#ManyToOne
#JoinColumn(name = "sau_id")
private Sau sau;
}
Entity Cult :
#Entity
public class Cult implements Serializable {
#Id #GeneratedValue(strategy = GenerationType.IDENTITY)
private Long idCult;
private String nameCult;
#OneToOne
#JoinColumn(name = "part_id")
private Part part;
}
I need to retrieve a Collection of Cult objects Where farm_id = x, I obviously can't do it by using the convention naming of methods like :
public Collection<Cult> = findCultByPartBySauByFarmIdFarm(Long idFarm);
I can't figure out how to write the custom #Query either for this case in Spring Data Repository.
Another version without explicit joins.
#Query("select c from Cult c where c.part.sau.farm.idFarm = ?1")
public Collection<Cult> findCultByFarmId(Long idFarm);
I usually prefer to use this as I let the underline implementation to deal with the joins for me.
Try:
#Query("select c from Cult c join c.part p join p.sau s join s.farm f where f.idFarm = ?1")
public Collection<Cult> = findCultByFarmId(Long idFarm);

Categories