how to query embedded object in Hibernate? - java

I have classes A, B
class A{
#Embedded
private B objB;
}
#Embeddable
class B{
Integer x;
Integer y;
float z;
}
Now I have a bunch of class A objs Set, I want to query the database, so that rows contain same x and y in Class B (z is not important in comparison in this case) should be selected, how do I achieve that?
It's like "In" in SQL, but since I am comparing embedded objects, how should I do with it ? Many thanks!!

Given the classes:
public class RandomEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Embedded
private EmbeddableEntity embedded;
}
and
#Embeddable
public class EmbeddableEntity {
private Long valueA;
private Long valueB;
}
You can query it like:
session.createQuery( "select a from RandomEntity a where a.embedded.valueA=:value" ).setParameter( "value", 1L ).list();
Hibernate: select randomenti0_.id as id1_2_, randomenti0_.valueA as valueA2_2_, randomenti0_.valueB as valueB3_2_ from RandomEntity randomenti0_ where randomenti0_.valueA=?
or:
session.createQuery( "select a from RandomEntity a where a.embedded.valueA in (:value)" ).setParameterList( "value", Arrays.asList( 1L, 2L ) ).list();
Hibernate: select randomenti0_.id as id1_2_, randomenti0_.valueA as valueA2_2_, randomenti0_.valueB as valueB3_2_ from RandomEntity randomenti0_ where randomenti0_.valueA in (?)

Related

Spring JPA: How to join with fields that don't exist in the entity

We have 3 entities A, B, and C. We are searching in table A with fields within B and C. And the mapping is unidirectional, so B and Collection is not defined in A.
We are using Spring Specification, how can we perform join in this case without converting the mapping to bidirectional?
#Entity
public class A {
#Id
Long id
String name
}
#Entity
public class B {
#Id
Long id
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "a_id")
A a;
#Column
String country;
}
#Entity
public class C {
#Id
Long id
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "a_id")
private A a;
}
For example, if B is defined in A like that
#Entity
public class A {
#Id
Long id
String name
#OneToOne(mappedBy = "request")
private B b;
}
the join will be like that
public static Specification<A> countryEquals(String country) {
return (root, query, builder) -> builder.equal(
root.join("b", JoinType.LEFT).get("country"), country);
}
But B is not defined in A, then how to apply the join?
you can try to join it by B itself, you create a new Root and image you add a where b.a_id = a.id to your query or here, you CriteriaBuilder, then you can add more predicate to look for fields in B table. Something like this, somewhat pseudo code cause I don't have my code here atm and write it down by my memory, but I hope it can help
public static Specification<A> countryEquals(String country) {
return (root, query, builder) -> (
Root<B> b_root = query.from(B.class);
Predicate b_join = builder.equal(b_root.get("a_id"), root.get("id"))
Predicate b_country = builder.equal(b_root.get("country"), country) // or like with `%country%`
return builder.and(other_predicate,...., b_join, b_country)
)
}

how to select multiple columns in subquery(hql)

Is there a way to select multiple columns in a subquery of hql?
I want to convert the following mysql query to hql
select u.name, sub.cnt from user u
inner join (select user_id, count(user_id) cnt from user_log group by user_id order by cnt desc limit 5) sub
on u.id = sub.user_id;
But in hql, I know that can use subquery only in where clause
I'm not aware of a pure Hibernate solution. I talk about that in my Blog post.
But there is a FluentJPA solution that you may consider:
FluentQuery query = FluentJPA.SQL((User u) -> {
UserIdCount sub = subQuery((UserLog log) -> {
int count = alias(COUNT(log.getUserId()), UserIdCount::getCount);
SELECT(log.getUserId(), count);
FROM(log);
ORDER(BY(count).DESC());
LIMIT(5);
});
SELECT(u.getName(), sub.getCount());
FROM(u).JOIN(sub).ON(u.getId() == sub.getUserId());
});
return query.createQuery(em, UserNameCount.class).getSingleResult();
which produces the following SQL:
SELECT t0.name, q0.count
FROM USER t0 INNER JOIN (SELECT t1.user_id, COUNT(t1.user_id) AS count
FROM USER_LOG t1
ORDER BY COUNT(t1.user_id) DESC
LIMIT 5 ) q0 ON (t0.id = q0.user_id)
Entities I used (declared with lombok):
#Entity
#Getter
#Table(name = "USER")
class User {
private Long id;
private String name;
}
#Entity
#Getter
#Table(name = "USER_LOG")
class UserLog {
private Long userId;
}
#Tuple
#Getter
class UserIdCount {
private Long userId;
private int count;
}
#Tuple
#Data
class UserNameCount {
private int count;
private String name;
}

Reference properties of null referenced object in HQL

Here I have two Entity class.
#Table(name = "AC_ACCOUNT_MASTER")
public abstract class Account implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(name = "a_name")
private String name;
}
And
#Table(name = "AC_VOUCHER_MASTER")
public class Voucher implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private Double amt;
#ManyToOne
private Account drAc;
#ManyToOne
private Account crAc;
}
There are 10 rows in AC_VOUCHER_MASTER table, where 4 drAc data are null in AC_VOUCHER_MASTER table.
session.createQuery("select v.id, v.amount, v.drAc.id, v.crAc.id from Voucher v").list();
The above query returns me 10 result (although 4 drAc are null). But when I put name refernce (v.drAc.name), it returns only those rows (6 rows) that drAc is not null.
"select v.id, v.amount, v.drAc.id, v.drAc.name, v.crAc.id , v.crAc.name from Voucher v"
What Should I do now ? Is there to use coalesce() or something else ?
Use a left join:
select v.id, v.amount, drAc.id, drAc.name, crAc.id , crAc.name
from Voucher v
left join v.drAc drAc
left join v.crAc crAc

Hibernate generating a query from Named Query that joins on the wrong column?

I am using named query (hibernate 4).Entity defined as below.
#Entity
#NamedQuery(
name = "findAllProduct",
query = "SELECT PC.pincode,PO.description"
+" FROM PRODUCT_VENDOR_PAYMENT_OPTION_LOCATION PVPOL"
+" INNER JOIN PVPOL.paymentId PID"
+" INNER JOIN PVPOL.pincode PC"
+" INNER JOIN PVPOL.paymentOptions PO"
+" where PVPOL.id = :id"
)
public class PRODUCT_VENDOR_PAYMENT_OPTION_LOCATION extends baseEntity.Entity {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private int id;
#Column(name="Payment_Id")
#OneToMany(cascade=CascadeType.ALL,fetch=FetchType.EAGER,mappedBy="id")
private Set<Product_Catalog_Vendor> paymentId;
#Column(name="pincode_id")
#OneToMany(cascade=CascadeType.ALL,fetch=FetchType.EAGER,mappedBy="pincode_id")
private Set<Pincodes> pincode;
#Column(name = "payment_options")
#OneToMany(cascade=CascadeType.ALL,fetch=FetchType.EAGER,mappedBy="paymentOptions")
private Set<Payment_Options> paymentOptions;
//Protected setter getter here
}
Hibernate generating below sql:-
select pincode2_.pincode as col_0_0_, paymentopt3_.Description as col_1_0_
from PRODUCT_VENDOR_PAYMENT_OPTION_LOCATION product_ve0_
inner join Product_Catalog_Vendor paymentid1_
on product_ve0_.id=paymentid1_.Id
inner join Pincodes pincode2_
on product_ve0_.id=pincode2_.pincode_id
inner join payement_options paymentopt3_
on product_ve0_.id=paymentopt3_.payment_options
where product_ve0_.id=?
Instead of
select pincode2_.pincode as col_0_0_, paymentopt3_.Description as col_1_0_
from PRODUCT_VENDOR_PAYMENT_OPTION_LOCATION product_ve0_
INNER JOIN product_catalog_vendor paymentid1_
ON **product_ve0_.payment_id = paymentid1_.id**
INNER JOIN PINCODES pincode2_
ON **product_ve0_.pincode_id = pincode2_.pincode_id**
INNER JOIN payement_options paymentopt3_
ON **product_ve0_.payment_options=paymentopt3_.payment_options**
where product_ve0_.id=1;
Product_catalog_vendor class:
#Entity
public class Product_Catalog_Vendor extends baseEntity.Entity {
#Id
#Column(name="Id")
private int id ;
//Setters and getters here
}
Pincodes Entity:
#Entity
public class Pincodes extends baseEntity.Entity {
#Id
private int pincode_id;
#Column(name="pincode")
private int pincode;
//Setters and getters here
}
payment_options Entity below:
#Entity
#Table(name="payement_options")
public class Payment_Options extends baseEntity.Entity {
#Id
#Column(name="payment_options")
private int paymentOptions;
//Setter getter
}
I have searched on many sites but unable to find the cause behind the scene. Please give me suggestions if i am doing something wrong. some good references would be appreciated. Thanks
just to get your problem correcty, your query joins on paymentid1_.Id instead of paymentid1_.id? or am I missing the differenz between the expected and the real query?
I'm not a pro but just guessing I would say your query is joining to the id of the Product_Catalog_Vendor:
#Id
#Column(name="Id")
private int id ;
so because thats why its Id and not id...
I think you don't need mappedBy at all due to unidirectional mapping or,anyway ,you are using them in a weird way.
mappedBy is necessary only if association is bidirectional (not your case) and should refers to a field which type is of the same type of entity where mappedBy is declared (and not a String type like in your case).You used mappedBy in a way like referencedColumnName property
In your example:
#Entity
public class Product_Catalog_Vendor extends baseEntity.Entity {
#ManyToOne
private PRODUCT_VENDOR_PAYMENT_OPTION_LOCATION pvpol;
}
and
public class PRODUCT_VENDOR_PAYMENT_OPTION_LOCATION extends baseEntity.Entity {
#Column(name="Payment_Id")
#OneToMany(cascade=CascadeType.ALL,fetch=FetchType.EAGER,mappedBy="pvpol")
private Set<Product_Catalog_Vendor> paymentId;
}

How Join hibernate Value objects using HQL query?

Hi i'm New to write HQL Query please help me.....
my Hibernate have three ValueObjects ie.
#Entity
#Table(name="user")
public class UserVO {
#Id
#Column(name="S_ID")
private String s_id;
#Column(name="FIRSTNAME")
private String firstName;
private String email;
}
CourseVO class
#Entity
#Table(name="course")
public class CourseVO
{
#Id
#Column(name="S_ID")
public String s_id;
#Column(name="NAME")
public String name;
}
Skillset VO
#Entity
#Table(name="skillset")
public class SkillsetVO
{
#Id
#Column(name="S_ID")
public String s_id;
#Column(name="COURSE_ID")//Foreign Key "USER"
public String course_id;
#Column(name="USER_ID")//Foreign key "COURSE"
public String user_id;
#Column(name="TEACH_EXP")
public String teach_Exp;
}
Now How to get Values of FirstName,NAME,TEACH_EXP values using EMAIL of USER table using HQL query
If you want to use join syntax in HQL you must work out your mapping accordingly as joins are enabled by mapping.
#Entity class A { #OneToMany private List<B> bs; }
#Entity class B { #Basic int n; }
Enables
select b from A a inner join a.b where a = :id
But with your mapping this is not possible. Also bear in mind that in terms of efficiency most of the RDBMs will perform an inner join on a where a.id = b.id.
select u.firstName, c.name, s.teach_Exp
from UserVO u, CourseVO c, SkillsetVO s
where
u.s_id = s.user_id
and c.s_id = s.course_id
and u.email = :email
But I think that you must review you association. Since looks to me that SkillsetVO.user_id should be SkillsetVO.User (an association to a UserVO entity and same for CourseVO).

Categories