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();
Related
I want to know how can I write These two Eloquent Queries into raw SQL? also Is there a way to convert the Eloquent series into raw SQL series so that I could use those?
public function items()
{
return $this->belongsToMany(Product::class, 'order_items', 'order_id', 'product_id')->withPivot('quantity', 'price');
}
public function user()
{
return $this->belongsTo(User::class);
}
If we talk about the first query used in the items method. After changing it into raw SQL it will become
DB::select('select `products`.*, `order_items`.`order_id` as `pivot_order_id`, `order_items`.`product_id` as `pivot_product_id`, `order_items`.`quantity` as `pivot_quantity`, `order_items`.`price` as `pivot_price` from `products` inner join `order_items` on `products`.`id` = `order_items`.`product_id` where `order_items`.`order_id` = `order_id`');
and the second query inside the user method will become
DB::select('select * from `users` where `users`.`id` = `id`');
I need to create a table in View by this View Model:
public class ApplicationContentViewModel
{
public BPMSPARS.Models.MySql.application application {get; set;}
public BPMSPARS.Models.MySql.content content { get; set; }
public BPMSPARS.Models.MySql.app_delegation app_delegation { get; set; }
}
But the query for creating new Table is very complex.
I use this query in MySQL, and I can get correct results by using it.
SELECT APP_UID, (SELECT CON_VALUE FROM content WHERE CON_CATEGORY = 'PRO_TITLE' AND CON_ID =
(SELECT PRO_UID from app_delegation WHERE del_thread_status='open' and USR_UID = '00000000000000000000000000000001' AND APP_UID = '9134216305aaaea1b67c4e2096663219')) AS TASK_NAME,
(SELECT CON_VALUE FROM content WHERE CON_CATEGORY = 'TAS_TITLE' AND CON_ID =
(SELECT TAS_UID from app_delegation WHERE del_thread_status='open' and USR_UID = '00000000000000000000000000000001' AND APP_UID = '9134216305aaaea1b67c4e2096663219')) AS PROCESS_NAME FROM app_delegation
WHERE del_thread_status='open' and USR_UID = '00000000000000000000000000000001' AND APP_UID = '9134216305aaaea1b67c4e2096663219'
But, I have to convert this query in linq or EF in MVC.
How Can I write This Query in Entity Framework query?
And How Can I display results in View?
Your SQL query seems (very) peculiar to me, as it is quite redundant. I am going to assume the sub-queries return a single value and enforce it with LINQ.
First I pulled out the common sub-query over app_delegation:
var USR_APP_Delegation = from a in app_delegation
where a.del_thread_status == "open" &&
a.USR_UID == "00000000000000000000000000000001" &&
a.APP_UID == "9134216305aaaea1b67c4e2096663219"
select a;
In LINQ it is easy to combine the two UID queries into one query:
var UIDs = (from a in USR_APP_Delegation
select new { a.PRO_UID, a.TAS_UID })
.Single();
Now you can do the name subqueries:
var TASK_NAME = (from c in content
where c.CON_CATEGORY == "PRO_TITLE" &&
c.CON_ID == UIDs.PRO_UID
select c.CON_VALUE)
.Single();
var PROCESS_NAME = (from c in content
where c.CON_CATEGORY == "TAS_TITLE" &&
c.CON_ID == UIDs.TAS_UID
select c.CON_VALUE)
.Single();
Then you can put all the queries together for the final result:
var ans = (from a in USR_APP_Delegation
select new {
a.APP_UID,
TASK_NAME,
PROCESS_NAME
})
.Single();
Again, this makes it obvious that your e.g. returning APP_UID when you know exactly what it is, and you are combining TASK_NAME and PROCESS_NAME into a query for no real advantage.
I would suggest using join against content makes a much more understandable query (even in SQL) and makes it clearer what is being returned:
var names = from a in app_delegation
join cpro in content on new { CON_ID = a.PRO_UID, CON_CATEGORY = "PRO_TITLE" } equals new { cpro.CON_ID, cpro.CON_CATEGORY }
join ctas in content on new { CON_ID = a.PRO_UID, CON_CATEGORY = "TAS_TITLE" } equals new { ctas.CON_ID, ctas.CON_CATEGORY }
where a.del_thread_status == "open" &&
a.USR_UID == "00000000000000000000000000000001" &&
a.APP_UID == "9134216305aaaea1b67c4e2096663219"
select new {
a.APP_UID,
Task_Name = ctas.CON_VALUE,
Process_Name = cpro.CON_VALUE
};
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.
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.
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();
}