Spring data jpa multiple table join with subquery - java

This is SQL Query I have tried to join all the tables using Spring Data JPA. Some please help me out.
SELECT op.id AS "Profile ID",
op.organization_name AS "Organization name",
pav.annotation AS "legacy-sams-acc-id",
ip.subnet AS "CIDR IP range"
FROM profile.profile p
JOIN profile.organization_profile op ON op.id = p.id
JOIN profile.profile_annotation_type pat ON pat.publisher_id = p.supplier_publisher_id
LEFT OUTER JOIN
(SELECT pa.id AS id,
pa.profile_id AS profile_id,
ftpa.annotation AS annotation,
ftpa.free_text_profile_annotation_type_id AS free_text_profile_annotation_type_id
FROM profile.profile_annotation pa
JOIN profile.free_text_profile_annotation ftpa ON ftpa.id = pa.id
) AS pav ON pav.free_text_profile_annotation_type_id = pat.id AND pav.profile_id = p.id
LEFT OUTER JOIN profile.ip_range_identifier ip ON ip.organization_profile_id = op.id
WHERE pat.description = 'legacy-sams-acc-id'
AND p.supplier_publisher_id = 66
ORDER BY op.id ASC
Following will be the corresponding Java class. I'm struck with converting SQL to Java.
public Specification<OrganizationProfile> organizationProfileReportCriteria(Long publisherId) {
return (root, criteriaQuery, criteriaBuilder) -> {
Subquery<Profile> profileSubquery = criteriaQuery.subquery(Profile.class);
Root<Profile> profileRoot = profileSubquery.from(Profile.class);
Join<Profile, OrganizationProfile> profileOrganizationProfileJoin = profileRoot.join("supplierPublisher");
profileSubquery.select(profileRoot)
.where(criteriaBuilder.equal(profileOrganizationProfileJoin, root),
criteriaBuilder.equal(profileRoot.get("supplierPublisher").get("id"), publisherId));
Subquery<ProfileAnnotationType> profileAnnotationTypeSubquery = criteriaQuery.subquery(ProfileAnnotationType.class);
Root<ProfileAnnotationType> profileAnnotationTypeRoot = profileAnnotationTypeSubquery.from(ProfileAnnotationType.class);
Join<ProfileAnnotationType, OrganizationProfile> organizationProfileAnnotationTypeJoin
= profileAnnotationTypeRoot.join("publisher");
profileAnnotationTypeSubquery.select(profileAnnotationTypeRoot)
.where(criteriaBuilder.equal(organizationProfileAnnotationTypeJoin, root),
criteriaBuilder.equal(profileAnnotationTypeRoot.get("publisher").get("id"), publisherId));
Subquery<ProfileAnnotation> profileAnnotationSubquery = criteriaQuery.subquery(ProfileAnnotation.class);
Root<ProfileAnnotation> profileAnnotationRoot = profileAnnotationTypeSubquery.from(ProfileAnnotation.class);
Join<ProfileAnnotation, OrganizationProfile> profileAnnotationOrganizationJoin
= profileAnnotationRoot.join("profile");
profileAnnotationSubquery.select(profileAnnotationRoot)
.where(criteriaBuilder.equal(profileAnnotationOrganizationJoin, root),
criteriaBuilder.equal(profileAnnotationRoot.get("profile").get("supplierPublisher").get("id"), publisherId));
return criteriaBuilder.or(criteriaBuilder.exists(profileSubquery));
};
}
Basically, I'm not sure how to join multiple tables using JPA. Someone, please explain to me how to convert multiple join and Subquery for converting SQL to Java. Basically confusion about profile and Organization profile table.

Related

Spring specification, Criteria API, join and subquery

How can i execute sql query like this through Criteria API and org.springframework.data.jpa.domain.Specification?
select b.id from brands b
where b.id not in
(select b.id from brands b
left join brand_categories bc on bc.brand_id = b.id
left join categories c on c.id = bc.category_id
where c.id = :id)
I tried this variant, but it didn't work
public static Specification<Brand> notContains(Long id) {
return (root, query, criteriaBuilder) -> {
Subquery<List> subQuery = query.subquery(List.class);
Root<Brand> subRoot = subQuery.from(Brand.class);
Join<Category, Brand> join = root.join("categories");
subQuery.select(subRoot.get("id"));
subQuery.where(criteriaBuilder.equal(join.get("id"), id));
return root.get("id").in(subQuery).not();
};
}
The problem here is that you just mixed up the Root<Brand> outside and the Root<Brand> in the sub-select query. This causes a different query to occur and the result is incorrect.
If you change your join relation in 'subquery' as below, your code will work:
Join<Category, Brand> join = subRoot.join("categories");

Flexible Search Issue SAP Hybris

I have a problem with a Flexible Query. This is my query:
Select
{pp.productCode} as 'Code',
{p.descriptionCics} as 'Desc CISC',
{bs.uid} as 'Store',
{evo.code} as 'Status',
{p.department} as 'Department',
{pca.name} as 'Category',
{p.grm} as 'GRM',
{p.buyerCode} as 'Code Buyer',
{p.buyerids} as 'Buyer',
{ps.planogramCode} as 'Code Planogram',
{pca.categoryCode} as 'Category Planogram',
{s.puvmBlock} as 'Blocked',
(CASE WHEN ({p.productDetailTypeList} is not null )THEN 'YES' else
'NO' END) as 'IMAGE'
from
{
Product as p
JOIN PlanogramProducts as pp on {p.code} = {pp.productCode}
JOIN StockLevel as s on {pp.productCode} = {s.productCode}
JOIN EnumerationValue as evo on {p.status} = {evo.pk}
JOIN PlanogramCategory as pc on {pp.planogramCode} =
{pc.planogramCode}
JOIN PlamnogramCategoryAnag as pca on {pc.categoryCode}=
{pca.categoryCode}
JOIN BaseStore as bs JOIN PlanogramStore as ps on {bs.storeRef} =
{ps.storeRef} AND {bs.bramchOffice} = {ps.branchOffice}
}
WHERE 1=1
and this my error when I execute it:
Can someone help me? Thanks a lot.
Your statement contains errors. You join basestore with planogramStore. But neither planogram store, nor basestore is joined with any other part of your query. You need to join basestore or planogramstore with one of the other tables.
Now you have 2 detached parts in your from statement, which is why you are getting errors
Product as p
JOIN PlanogramProducts as pp on {p.code} = {pp.productCode}
JOIN StockLevel as s on {pp.productCode} = {s.productCode}
JOIN EnumerationValue as evo on {p.status} = {evo.pk}
JOIN PlanogramCategory as pc on {pp.planogramCode} =
{pc.planogramCode}
JOIN PlamnogramCategoryAnag as pca on {pc.categoryCode}=
{pca.categoryCode}
and
JOIN BaseStore as bs JOIN PlanogramStore as ps on {bs.storeRef} =
{ps.storeRef} AND {bs.bramchOffice} = {ps.branchOffice}
you need to have a join between these 2 parts to get the correct data

Spring Data JPA Specification FETCH JOIN Issue

I am trying to create below query using spring jpa specification but it is giving error.
SELECT x FROM Magazine x join fetch x.articles a join a.publishers p WHERE p.title = 'JDJ'
Invalid path: 'generatedAlias2.title'
problem here is I am trying to do something like below
return (r, cq, cb) -> {
Join join1 = (Join) root.fetch("articles");
Join join2 = join1.join("publisher");
return cb.equal(join2.get("title"), title);
};
Is it possible to create query. Please help.

JPA Criteria Query for Left joins

I am new to JPA and I have a Left Join scenario.
I have my native sql query as below and I am using left join to fetch the complete records from V_MONITORING table for st.id = 10001.
I have some null values for id_legislature which also needs to be selected and hence using a left join
select distinct
mv.id_set, mv.id_travel, mv.id_legislature
from
V_MONITORING mv
left join v_set st on mv.id_set = st.id
left join v_travel fg on mv.id_travel = fg.id
left join v_legislature gg on mv.id_legislature = gg.id;
The same thing I am implementing using the JPA criteria query, I am unable to fetch the null records
Below is the code
Predicate predicate = cb.conjunction();
Root<MonitoringBE> mvRoot = criteriaQuery.from(MonitoringBE.class);
mvRoot.fetch(MonitoringBE.id_set, JoinType.LEFT);
mvRoot.fetch(MonitoringBE.id_travel, JoinType.LEFT);
mvRoot.fetch(MonitoringBE.id_legislature, JoinType.LEFT);
final Path<Object> serieneinsatzterminPath= mvRoot.get(MonitoringBE.id_set);
predicate = cb.and(predicate, cb.EqualTo(serieneinsatzterminPath.get(SetBE.GUELTIG_VON_DATUM), startSetDate));
criteriaQuery.multiselect(
mvRoot.get(MonitoringBE.id_travel).alias("id_travel"),
mvRoot.get(MonitoringBE.id_set).alias("id_set"),
mvRoot.get(MonitoringBE.id_legislature).alias("id_legislature"))
.distinct(true).where(predicate);
Can some one guide me.
You have to replace the mvRoot.get(MonitoringBE.id_travel) and others in the multiselect-statement with mvRoot.join(MonitoringBE.id_travel, JoinType.LEFT). Otherwise they will end up in a inner join.

named query to fetch result by using IN clause with null or without null conditionally

I need a single named query that fulfills below both named query conditions only by setting the Query parameter.
Named Query, to fetch record where "softwareVersion" is null OR softwareVersion matched with the list.
#NamedQuery(name = "getIPDetectionDetailsForPanIndia",
query = "select cssc.css.sapId,
cssc.css.hostName,
cssc.cssGoldenConfiguration.category,
cssc.cssGoldenConfiguration.parameter,
cssc.cssGoldenConfiguration.vendor,
cssc.recommendedValue,
cssc.actualValue,
cssc.cssGoldenConfiguration.id,
cssc.cssGoldenConfiguration.information,
cssc.css.softwareVersion,
jioc.name,
cssc.cssGoldenConfiguration.impact,
cssc.cssGoldenConfiguration.command
from CssComplianceDetail cssc
join cssc.css c
left join c.cluster club
left join clus.jiocenter jioc
where cssc.cssGoldenConfiguration.impact in (:impactType)
and cssc.cssGoldenConfiguration.category in (:category)
and TO_CHAR(cssc.creationDate, 'yyyy-MM-dd') = TO_CHAR(:date, 'yyyy-MM-dd')
and (cssc.css.softwareVersion in (:softwareVersion)
or cssc.css.softwareVersion is null)";
Named Query, to fatch record where "softwareVersion" matched with the list only, no need to fatch null softwareVersion.
#NamedQuery(name = "getIPDetectionDetailsForPanIndiaAcceptNull",
query = "select cssc.css.sapId,
cssc.css.hostName,
cssc.cssGoldenConfiguration.category,
cssc.cssGoldenConfiguration.parameter,
cssc.cssGoldenConfiguration.vendor,
cssc.recommendedValue,
cssc.actualValue,
cssc.cssGoldenConfiguration.id,
cssc.cssGoldenConfiguration.information,
cssc.css.softwareVersion,
jioc.name,
cssc.cssGoldenConfiguration.impact,
cssc.cssGoldenConfiguration.command
from CssComplianceDetail cssc
join cssc.css c
left join c.cluster club
left join clus.jiocenter join
where cssc.cssGoldenConfiguration.impact in (:impactType)
and cssc.cssGoldenConfiguration.category in (:category)
and TO_CHAR(cssc.creationDate, 'yyyy-MM-dd') = TO_CHAR(:date, 'yyyy-MM-dd')
and cssc.css.softwareVersion in (:softwareVersion)";
Below is my Java code:
List softwareVersion = new ArrayList();
if(softwareVersion.contains("All")) {
query = getEntityManager().createNamedQuery("getIPDetectionCountForPanIndiaAcceptNull");
} else {
query = getEntityManager().createNamedQuery("getIPDetectionCountForPanIndia");
}
query.setParameter("softwareVersion", softwareVersion);

Categories

Resources