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.
Related
I have this diagram:
table diagram
and I want to filter by the employees that have a project.
In normal SQL I will go like this
select * from employees e
join employee_projects ep on ep.employee_id = e.id
How can I achieve the same with Hibernate?
I tried using criteria builder and specifications but I can't get the data from the join table.
You can select all employees that have a project like this
em.createQuery(
"SELECT e FROM Employee e JOIN e.projects p WHERE p IS NOT NULL", Employee.class).getResultList()
You can join tables using join method of root object.
try something like this below
I have used it for one to many relation
Join<Post, Tag> join = root.join("tags", JoinType.INNER);
Predicate tagPredicate = criteriaBuilder.like(join.get("name"), "%" + search + "%");
for many to many relation,
Join<Post, Tag> postTagsTable = root.join("tags", JoinType.INNER);
return postTagsTable.<String>get("name").in(tagNames);
here I have tags field in Post entity, which is used inside join
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");
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
I am stuck in a situation where I am not able to create a filter on left join between two table.
My query is something like this.
select count(*)
from orders o
left
join payments p
on o.id = p.o_id
where o.uid_id = 1
and p.name = "abc"
I am trying to do left join using criteria query. In criteria query.
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Orders> query = cb.createQuery(Orders.class);
Root<Orders> ordersRoot = query.from(Orders.class);
Join<Orders, Payments> join = ordersRoot.join(JOIN_COLUMN, JoinType.LEFT);
List<Predicate> predicates = new ArrayList<>();
predicates.addAll(getPredicates(cb, ordersRoot)); //this method gives other predicates on order table
query.where(predicates.toArray(new Predicate[predicates.size()]));
query.select(ordersRoot).distinct(true);
TypedQuery<Orders> query = entityManager.createQuery(criteriaQuery);
List<Orders> list = query.getResultList();
This is my criteria Java code.
In this I have not added for this check.
orders and payments table has one to many relationship.
I have a criteriaQuery
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<School> criteriaQuery = builder.createQuery(School.class);
Root root = criteriaQuery.from(EducationDistrictBundle.class);
criteriaQuery.distinct(true);
Join join = root.join("schoolList",JoinType.LEFT);
join.fetch("address", JoinType.LEFT);
criteriaQuery.select(join);
adding predicates and ordering
criteriaQuery = criteriaQuery.where(builder.and(predicates.toArray(new Predicate[predicates.size()])));
criteriaQuery.orderBy(builder.desc(join.get("address").get("fullAddress")));
SQL query looks like this
SELECT DISTINCT
school2_.id AS id1_52_0_,
address3_.id AS id1_1_1_,
school2_.createdTs AS createdT2_52_0_,
school2_.guid AS guid3_52_0_,
school2_.updatedTs AS updatedT4_52_0_,
school2_.version AS version5_52_0_,
school2_.accreditation AS accredit6_52_0_,
school2_."address_id" AS address14_52_0_,
school2_."belonging_id" AS belongi15_52_0_,
school2_.director AS director7_52_0_,
school2_."financialType_id" AS financi16_52_0_,
school2_.fullName AS fullName8_52_0_,
school2_.license AS license9_52_0_,
school2_.number AS number10_52_0_,
school2_.parent_id AS parent_17_52_0_,
school2_.school AS school11_52_0_,
school2_.shortName AS shortNa12_52_0_,
school2_.site AS site13_52_0_,
school2_."subordinationType_id" AS subordi18_52_0_,
school2_."type_id" AS type_id19_52_0_,
address3_.createdTs AS createdT2_1_1_,
address3_.guid AS guid3_1_1_,
address3_.updatedTs AS updatedT4_1_1_,
address3_.version AS version5_1_1_,
address3_.addressUID AS addressU6_1_1_,
address3_.fullAddress AS fullAddr7_1_1_,
address3_.fullHouse AS fullHous8_1_1_,
address3_.houseUID AS houseUID9_1_1_,
address3_.oktmo_id AS oktmo_i12_1_1_,
address3_.plain AS plain10_1_1_,
address3_.postalCode AS postalC11_1_1_,
address3_1_.flat AS flat1_0_1_,
address3_1_.type AS type2_0_1_,
CASE WHEN address3_1_."id" IS NOT NULL THEN 1
WHEN address3_.id IS NOT NULL THEN 0 END AS clazz_1_
FROM "education_district_bundle" educationd0_ LEFT OUTER JOIN "education_district_bundle_school" schoollist1_
ON educationd0_.id = schoollist1_."education_district_bundle_id"
LEFT OUTER JOIN "school" school2_ ON schoollist1_."schoolList_id" = school2_.id
LEFT OUTER JOIN "address" address3_ ON school2_."address_id" = address3_.id
LEFT OUTER JOIN "address_refine" address3_1_ ON address3_.id = address3_1_."id"
CROSS JOIN "address" address4_
WHERE school2_."address_id" = address4_.id AND educationd0_."educationDistrict_id" = 179
ORDER BY address4_.fullAddress DESC
And i have an exception
PSQLException: ERROR: for SELECT DISTINCT, ORDER BY expressions must appear in select list
But why there was generated cross join "address4"? I just want to order like this
ORDER BY address3_.fullAddress DESC
if i'm ordering by school.name
order by school2_.shortName asc
there is no another cross join for school...
Even if Fetch is not a Join type, you can cast it.
You need to have the joins defined up-front, to avoid joining the same association twice
Since you need those two additional joins for the "orderBy" clause you can use INNER instead of LEFT:
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<School> criteriaQuery = builder.createQuery(School.class);
Root root = criteriaQuery.from(EducationDistrictBundle.class);
criteriaQuery.distinct(true);
Join schoolJoin = root.join("schoolList", JoinType.LEFT);
Join addressJoin = ((Join) schoolJoin.fetch("address", JoinType.INNER));
Join fullAddressJoin = addressJoin.fetch("fullAddress", JoinType.INNER);
criteriaQuery = criteriaQuery.where(builder.and(predicates.toArray(new Predicate[predicates.size()])));
criteriaQuery.orderBy(builder.desc(fullAddressJoin));
criteriaQuery.select(schoolJoin);