JPQL fetch data from multiple tables - mysql

I have the following classes.
class A{
#OneToMany
List<B> bList;
}
class B{}
class C extends A{
#OneToMany
List<D> dList;
}
class D{}
I have used lazy loading for each #OneToMany relationship.
My requirement is to fetch all data from C using "Join Fetch" as I do not want to trigger any other database calls when accessing B and D.
Basically I want to fetch C, with B and D loading "EAGER"
Something like following
"SELECT DISTINCT c FROM C c LEFT JOIN c.B"
If this is not possible with JPQL, can it be achieved with java criteria API?

Yes, it is possible,, it should be like:
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<String> cq = cb.createQuery(String.class);
Root<C> c = cq.from(C.class);
Join<C,B> b = c.join("b", JoinType.LEFT); //left outer join
b.on(
//define criteria here
)
);
cq.select(b.<String>get("field names"));
List<String> results = em.createQuery(cq)
.getResultList();
Above code needs to tweak for your requirements.

Related

Hibernate right outer join not supported and could not bring the required results

Hibernate right outer join not supported and could not bring the required results
My JPA/hibernate entities are,
#Entity
public class Category implements Serializable{
#ManyToMany(mappedBy="categoryList")
private Set<Coupon> coupon;
public Set<Coupon> getCoupon() {
return coupon;
}
public void setCoupon(Set<Coupon> coupon) {
this.coupon = coupon;
}
}
#Entity
public class Coupon implements Serializable{
#ManyToMany
#JsonIgnore
private Set<Category> categoryList;
public Set<Category> getCategoryList() {
return categoryList;
}
public void setCategoryList(Set<Category> categoryList) {
this.categoryList = categoryList;
}
}
Now totally 3 tables are created, those are:
coupon:
1 10% off on bus booking
4 20% off on bus booking
category:
1 bus
2 recharge
coupon_category_list:
coupon | category
1 | 1
4 | 1
I need the categories with coupon count something like,
1 bus 2
2 recharge 0
I tried below way,
#Override
public List<Object[]> searchCategoriesByParms(Category category) {
List<Category> categoryResultList = new ArrayList<Category>();
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Object[]> criteriaQuery = criteriaBuilder.createQuery(Object[].class);
Root<Category> categoryRoot = criteriaQuery.from(Category.class);
final List<Predicate> predicates = new ArrayList<Predicate>();
Join<Coupon,Category> couponEntity = categoryRoot.join("coupon", JoinType.LEFT);
criteriaQuery.multiselect(couponEntity.join("categoryList",JoinType.INNER));
criteriaQuery.groupBy(categoryRoot.get("categoryId"));
List<Object[]> categoryResultLstObjects = entityManager.createQuery(criteriaQuery).getResultList();
return categoryResultLstObjects;
}
and it generates the below query:
select category4_.category_id as category1_1_, category4_.category_desc as category2_1_, category4_.category_image as category3_1_, category4_.category_name as category4_1_, category4_.category_slug as category5_1_ from category category0_ left outer join coupon_category_list coupon1_ on category0_.category_id=coupon1_.category_list_category_id left outer join coupon coupon2_ on coupon1_.coupon_coupon_id=coupon2_.coupon_id inner join coupon_category_list categoryli3_ on coupon2_.coupon_id=categoryli3_.coupon_coupon_id inner join category category4_ on categoryli3_.category_list_category_id=category4_.category_id group by category0_.category_id
I tried different combinations of joins in both coupon and categoryList above, but nothing worked out. But the same I modified with right outer join and executed in my mysql workbench and it results the expected result, but hibernate does not support right outer join.
Working query with right outer join (but hibernate does not support this)
select category4_.category_id as category1_1_, category4_.category_desc as category2_1_, category4_.category_image as category3_1_, category4_.category_name as category4_1_, category4_.category_slug as category5_1_ from category category0_ right outer join coupon_category_list coupon1_ on category0_.category_id=coupon1_.category_list_category_id right outer join coupon coupon2_ on coupon1_.coupon_coupon_id=coupon2_.coupon_id right outer join coupon_category_list categoryli3_ on coupon2_.coupon_id=categoryli3_.coupon_coupon_id right outer join category category4_ on categoryli3_.category_list_category_id=category4_.category_id group by category0_.category_id
Can I have some help here ?
Thanks in advance. I appreciate if i get the help purely with JPA than hibernate implementations.

(Laravel) Join 3 or more tables using "Eloquent Relationships"

I'm trying to join 3 tables using eloquent relationships, but it doesn't give the expected results.
Shipment model
class Shipment extends Model
{
protected $table = 'ccctadm.Shipment';
public function customergroupcode()
{
return $this->hasMany(DocumentRuleSet::class,'customergroupcode','customergroupcode');
}
public function shipmentcategory()
{
return $this->hasMany(DocumentRuleSet::class,'shipmentcategory','shipmentcategory');
}
public function status()
{
return $this->hasMany(DocumentRuleSet::class,'status','status');
}
}
to get the data i'm using this code
$shipment_data = Shipment::With(['customergroupcode' , 'shipmentcategory','status'])->
Where('shipment_cycle','!=','closed')->get();
I'm trying to make it equivalent to this query
select B.rulesetname,B.icon ,COUNT(*)As Total from
[ccct].[ccctadm]. [Shipment] A INNER JOIN
[ccct].[ccctadm].[documentruleset] B
ON
A.customergroupcode = B.customergroupcode AND A.shipmentcategory =
B.shipmentcategory AND A.status = B.status INNER
JOIN [ccctadm].[shipassign] S ON A.id = S.shipmentid AND
A.shipment_cycle != 'closed' GROUP BY rulesetname,B.icon
The first query returns all the data in 3 tables, but when the second one returns Release only and this what I want
I only want the data that has relation among these three tables not everything
What I'm doing wrong ?
Use has() method. It limits the records based on existence of the relationship.
$shipment_data = Shipment::has('customergroupcode' , 'shipmentcategory','status')->
Where('shipment_cycle','!=','closed')->get();

hibernate optional relationship not showing data

I am using hibernate with MySQL Db. I have a table of business with some fields and relations. in relations, one relation is optional.
#ManyToOne(fetch = FetchType.LAZY)
#NotFound(action=NotFoundAction.IGNORE)
#JoinColumn(name = "modified_by", nullable = true)
public Users getModifiedBy() {
return this.modifiedBy;
}
public void setModifiedBy(Users modifiedBy) {
this.modifiedBy = modifiedBy;
}
now when I fetch data using the following hql it work fine
String hql = "from Business";
Query query = session.createQuery(hql);
list = query.list();
if i changed hql to the following then it shows 0 result.
String hql = "select new com.ba.Business(business.businessId,business.slUsersByCreatedBy.userId,business.modifiedBy.userId,business.bizType.bizTypeId) from com.ba.Business business order by business.businessName";
How to manage this as modifiedBy is null. There were different solution available which i tried like setting optional to true and setting #NotFound but nothing worked.
SQL Created by hql is following.
select business0_.business_id as col_0_0_, business0_.createdBy as col_1_0_, business0_.modified_by as col_5_0_, business0_.biz_type_id as col_9_0_ from _business business0_, _users users1_, _users users4_, _biz_type biztype7_ where business0_.createdBy= users1_.web_user_id and business0_.modified_by= users4_.web_user_id and business0_.biz_type_id= biztype7_.biz_type_id order by business0_.business_name
it is using "and" for joins. If i explicitly add joins by adding following with hql then the result remain same.
left join business.modifiedBy modifiedBy
Is there any solution available?
When you use business.modifiedBy in the query, it implicitly converts to inner join, and that's why you don't get any results. Change it to this and it should work
String hql = "select new com.ba.Business(business.businessId, business.slUsersByCreatedBy.userId, mb.userId, business.bizType.bizTypeId) from com.ba.Business business left join business.modifiedBy mb order by business.businessName";

JPA How to build a join criteria query

I have the following situation 3 tables, person, job, category.
Person has a job and Job has a category. How do I get the person records from the same category.
public List<Person> findPplByCategory(Category category) {
javax.persistence.criteria.CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
javax.persistence.criteria.Root<Person> e = cq.from(Person.class);
javax.persistence.criteria.Root<Job> a = cq.from(Job.class);
//...not sure how to create the query here..
}
This is easy to do using a JPQL query
String query = "select P from Person P join P.job J join J.category C where C = :cat"
List<Person> = entitiyManager.createQuery(query, Person.class).setParameter("cat", myCategory).getResultList();
Some assumptions:
One Person has one Job
One Job has one Category
Person's job field is named job
Job's category field is named category
haven't tested but may be something like
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Person> q = cb.createQuery(Person.class);
Root<Person> person = q.from(Person.class);
Join<Person,Job> job = person.join(Person_.job);
Predicate predicate = cb.conjunction();
Predicate p = cb.equal(job.get(Job_.category), cat);
predicate = cb.and(p);
q.where(predicate);
q.select(person);
TypedQuery<Person> tq = entityManager.createQuery(q);
List<Person> all = tq.getResultList();
return all;
javax.persistence.criteria.CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
javax.persistence.criteria.Root<Person> e = cq.from(perdon.class);
cq.where(cb.equal(e.get("idCompany").get("idCategory"), cat));
cq.orderBy(cb.desc(e.get("idPerson")));
return getEntityManager().createQuery(cq).getResultList();
my version is:
CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
CriteriaQuery<Person> cq = cb.createQuery(Person.class);
Root<Person> root = cq.from(Person.class);
Join<Person,Job> job = root.join(Person_.job);
Join<Job,Category> category =car.join(Car_.category).where(cb.equal(job.get(Job_.category).get(Category_.name),"your category"));
cq.select(root);
TypedQuery<Person> query = getEntityManager().createQuery(cq);
return query.getResultList();
Here you have that Person is one-to-one with Job and the latter is one-to-one with Category :) You will receive you all persons which is in specified category of job.

How to define a return List<T> for a LinqToSql Join?

I use Linq To Sql Join Query in DAL layer, How can I define a return List<T> automatically for the LinqToSql Join method?
Nowadays, I have to manually define a List<CustomViewType> for each LinqToSql Join method's return value.
Is that possible to define a List<T> like the following code :
public static List<T> GetJoinList()
{
List<T> list = new List<T>();
list = from c in customers
join o in orders on o.customerid equals c.customerid
select new { CustomerID = c.CustomerId, OrderDate = o.OrderDate } ;
return list.ToList() ;
}
In fact, what I mean is that how can I pass the lists of anonymous types from DAL layer to BLL layer ?
You must still create a custom class for the return type since you can't return anonymous classes from methods. You can avoid declaring and assigning the list though using the ToList() extension method:
public static List<CustomViewType> GetJoinList()
{
return (from c in customers
join o in orders on o.customerid equals c.customerid
select new CustomViewType { CustomerID = c.CustomerId, OrderDate = o.OrderDate}).ToList();
}