duplicate [ID] alias error for sql statement with join - java

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

Related

CrudRepository Find by Custom join field filter

I have below entity
RequestObj
AdditionalReqObj.
Both entities are linked with REQ_ID column in table (reqId field). I am using Spring data CrudRepository interface for repository.
Now I want to findAll RequestObj entity by REQUEST.REQ_STATUS which is open & linked Additional request should also be filter by ADDL_REQUEST.ADD_REQ_STATUS
#Entity
#Table(name = "REQUEST")
public class RequestObj implements Serializable {
#Id
#Column(name = "REQ_ID")
private long reqId;
#Column(name = "REQ_NM")
private String reqUserNm;
#Column(name = "REQ_EMAIL")
private String reqUserEmail;
#Column(name = "REQ_ID")
private String reqComments;
#Column(name = "REQ_STATUS")
private String reqStatus;
#OneToMany(mappedBy = "request", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private List<AdditionalReqObj> requestDtls;
---getter setter----
}
#Entity
#Table(name = "ADDL_REQUEST")
public class AdditionalReqObj implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name = "AdD_REQ_ID")
private long addReqId;
#Column(name = "ROLE_NM")
private String add_req_comment;
#ManyToOne
#JoinColumn(name = "REQ_ID")
private RequestObj request;
#Column(name = "ADD_REQ_STATUS")
private String addReqStatus;
---getter setter----
}
You will have to fire a Native Query on your method. You can do it like this,
#Query(value = "SELECT R.* FROM REQUEST R INNER JOIN ADDL_REQUEST AR ON R.REQ_ID = AR.REQ_ID WHERE R.REQ_STATUS = :PARAM1 and AR.ADD_REQ_STATUS = :PARAM2 ", nativeQuery = true)
List<ReqObj> findAllByAddressId(Object PARAAM1, Object PARAM2);

OneToMany could not determine type for SpringBoot/SQLite3

I have a problem with the relationship oneToMany. I created tables in SQLite DB, this is my tables:
I created the two models CategoryModel and ProductModel.
ProductModel is:
#Entity
#Table(name = "Product_Category")
#JsonIgnoreProperties({ "hibernateLazyInitializer", "handler" })
public class ProductModel {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.AUTO)
private Long product_id;
private Long category_id;
private String name;
private String description;
private int numberOfProduct;
private String image;
private int price;
#JoinColumn(name = "country_id", nullable = false)
private CategoryModel category;
//geter's and seter's
}
My CategoryModel:
#Entity
#Table(name = "Category")
#JsonIgnoreProperties({ "hibernateLazyInitializer", "handler" })
public class CategoryModel {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String category_name;
private String category_description;
private String image_path;
#OneToMany( mappedBy = "category")
private Set<ProductModel> category;
//Geter's and Seter's
My Repository:
public interface CategoryRepository extends JpaRepository<CategoryModel, Long> {
#Query("SELECT * "
+ "FROM Product_Category d INNER JOIN d.categoryModel e")
List<ProductModel> fetchEmpDeptDataInnerJoin();
}
I do not understand where I make a mistake. I have this error:
Could not determine type for:
com.dar.darkozmetika.models.CategoryModel, at table: product_category,
for columns: [org.hibernate.mapping.Column(category)]
1) Add #ManyToOne annotation:
#ManyToOne
#JoinColumn(name = "country_id", nullable = false)
private CategoryModel category;
2) Remember that you are using JPQL, not SQL (unless you sent native="true"):
#Query("SELECT p "
+ "FROM ProductModel p INNER JOIN p.category c")

Loading DTO with collection

#Entity
#Table(name = "person")
public class Consignment implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(name = "person_id")
private String personId;
#Column(name = "person_name")
private String personName;
#OneToMany(fetch = FetchType.EAGER, mappedBy = "person")
#Column(name = "cars_owned")
private Set<Cars> casrsowned = new HashSet<>();
}
#Entity
#Table(name = "cars")
public class Cars implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(name = "cars_id")
private String carsId;
#ManyToOne
#JoinColumn(name = "person")
private Person person;
#OneToOne
private CarsDetail carsDetail;
}
#Entity
#Table(name = "carsDetail")
public class CarsDetail implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(name = "brand")
private String brand;
#Column(name = "color")
private String color;
#Column(name = "model")
private String model;
}
class CarModelDTO {
String personName;
List<String> models;
}
In the above relation, want to return CarModelDTO
JPA query where,
#Query("Select CarModelDTO(p.personName, p.casrsowned.carsDetail.model) from Person as p where p`enter code here`.id = :id"))
public CarModelDTO getCarmodelOwnedByAperson(#Param("id") Long id);
I tried multiple ways but it gives
org.hibernate.QueryException: illegal attempt to dereference collection
As I have already described Retrieve List from repository interface to DTO list you should go through the following step :
first create a constructor using the fields you want to be returned from the query output
in you query you should create new instance of your dto and pass the field from db to new instalnce :
so you need these changes:
1. In the constructor:
You should not use a list as List<String> models; as you should consider that your dto as a result row of DB. so you need to have a simple String model;
public CarModelDTO (String name,String model){
this.name=name;
this.model=model;
}
2. In the #Query:
you should use multi inner join appropriately
you should also append your package name to CarModelDTO in the query (here i used com.example you should change it)
#Query("Select com.example.CarModelDTO(p.personName, d.model ) from Person as p inner join p.carsowned c inner join c.carDetail d where p`enter code here`.id = :id"))
public CarModelDTO getCarmodelOwnedByAperson(#Param("id") Long id)

Join queries with JPQL in Spring Data Jpa

I created a left join query with JPQL in spring data jpa but failed in my unit test. There are two entities in the project.
Product entity:
#Entity
#Table(name = "t_goods")
public class Product implements Serializable {
#Id
#GeneratedValue
#Column(name = "id", length = 6, nullable = false)
private Integer id;
#Column(name = "name", length = 20, nullable = false)
private String name;
#Column(name = "description")
private String desc;
#Column(name = "category", length = 20, nullable = false)
private String category;
#Column(name = "price", nullable = false)
private double price;
#Column(name = "is_onSale", nullable = false)
private Integer onSale;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "brand_id")
private Brand brand;
// getter and setter
}
Brand entity:
#Entity
#Table(name = "tdb_goods_brand")
public class Brand implements Serializable {
#Id
#GeneratedValue
#Column(name = "id", length = 6, nullable = false)
private Integer id;
#Column(name = "brand_name", unique = true, nullable = false)
private String name;
#OneToMany(mappedBy = "brand", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private List<Product> products;
// getter and setter
}
And a third class Prod to map the query results to Object:
public class Prod implements Serializable {
private Integer id;
private String name;
private double price;
//private String brandName;
// getter and setter
}
It works fine with this query:
public interface ProductRepository extends JpaRepository<Product, Integer> {
#Query(value = "select new com.pechen.domain.Prod(p.id, p.name, p.price) from Product p ")
Page<Prod> pageForProd(Pageable pageRequest);
}
But if I add new property brandName for Prod and refactor the query with left join, it test fails:
#Query(value = "select new com.pechen.domain.Prod(p.id, p.name, p.price, b.name) from Product p left join com.pechen.domain.Brand b on p.brand_id = b.id")
Page<Prod> pageForProd(Pageable pageRequest);
The problem seems to be here on p.brand_id = b.id because there is not a brand_id property in Product, it's just a column name. So how can I make this work?
Update:
There turned to be some sytax errors in the JPQL query, just fix it as the following:
#Query(value = "select new com.pechen.domain.Prod(p.id, p.name, p.price, b.name) from Product p left join p.brand b")
Page<Prod> pageForProd(Pageable pageRequest);
Besides, it's very troublesome in this way to create another class everytime to map the query results into object(I mean the Prod class). So is there a good way to work with it? Any help would be appreciated.
Instead of p.brand_id = b.id you should do p.brand.id = b.id

Hibernate QueryException: could not resolve property

So I have these relations between these 3 tables
And what I'm trying to do is to search (by code or designation) and get list of projects for a specific chief, something like this:
SELECT * FROM Project p JOIN ProjectHasChief phc ON (p.id = phc.idproject)
JOIN Chief c ON (c.id = phc.id_chief)
WHERE c.id = (myID)
AND (designation LIKE '%user_string%' OR code LIKE '%user_string%');
AND since I'm using hibernate I've used Criteria:
Criteria c = session.createCriteria(ProjectHasChief.class);
c.add(Restrictions.eq("chief", chief))
.add(Restrictions.disjunction()
.add(Restrictions.like("project.designation", reg, MatchMode.ANYWHERE))
.add(Restrictions.like("project.code", reg, MatchMode.ANYWHERE)));
List<ProjectHasChief> list = (List<ProjectHasChief>)c.list();
But I get this error:
org.hibernate.QueryException: could not resolve property: project.designation of: smt.agm.entities.ProjectHasChief
Project entity:
#Entity
#Table(name="projet")
public class Project {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", columnDefinition="serial")
private int id;
#Column(name="code")
private String code;
#Column(name="designation")
private String designation;
#OneToMany(cascade = CascadeType.ALL, mappedBy="project", orphanRemoval=true)
#OrderBy(clause="id DESC")
private List<ProjectHasChief> chiefs = new ArrayList<ProjectHasChief>();
}
Chief entity:
#Entity
#Table(name="chief")
public class Chief {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", columnDefinition="serial")
private int id;
#Column(name = "name")
private String name;
}
ProjectHasChief entity:
#Entity
#Table(name="mapping_chantier_chef")
public class ProjectHasChief {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", columnDefinition="serial")
private int id;
#ManyToOne
private Project project;
#ManyToOne
private Chief chief;
#Column(name="date_deb")
private Date startDate;
#Column(name="date_fin")
private Date endDate;
}
Whe hibernate don't know the property designation of Project entity ?!!
Are you absolutely sure all the mappings and joins actually work?
If so, you can try to declare an implicit alias for Project like so:
Criteria c = session.createCriteria(ProjectHasChief.class);
c.createAlias("project", "project") //THIS ONE
c.add(Restrictions.eq("chief", chief))
c.add(Restrictions.disjunction()
.add(Restrictions.like("project.designation", reg, MatchMode.ANYWHERE))
.add(Restrictions.like("project.code", reg, MatchMode.ANYWHERE)));
List<ProjectHasChief> list = (List<ProjectHasChief>)c.list();

Categories