Hibernate Books

All times are UTC - 5 hours [ DST ]



Post new topic Reply to topic  [ 9 posts ] 
Author Message
 Post subject: Query nested objects using HQL or Criteria Builder
PostPosted: Mon Jul 03, 2017 6:48 am 
Newbie

Joined: Mon Jul 03, 2017 6:40 am
Posts: 10
Hi, I'm sorry I'm sure there was such question before. I tried to search for "query nested object" and didn't get related topic. Looks like my query in wrong.
I'm using hibernate 5.2.x and JPA 2.1, I don't understand how to query

Code:
class Parent {
  @Id 
  id:Long

  @OneToOne /** yeah, only one child is allowed **/
  @JoinColumn(name = "childId", nullable = false)
  child: Child
}


and child:
Code:
class Child{
  id:Long
  name: String
}

I'm trying to query Parent entity by child.id attribute using CriteriaQuery. Here is my code:

v
Code:
al criteriaBuilder: CriteriaBuilder = session.getCriteriaBuilder
    val criteriaQuery = criteriaBuilder.createQuery(classOf[Parent])
    val root: Root[Parent] = criteriaQuery.from(classOf[Parent])

// exception here
val restriction = criteriaBuilder.equal(root.get("child.id"), 123L)
criteriaQuery.where(restriction)


Exception is:

java.lang.IllegalArgumentException: Unable to locate Attribute with the the given name [child.id] on this ManagedType [persistence.model.Parent]


I'm now quite well understand what I do wrong.

https://docs.jboss.org/hibernate/orm/5. ... Guide.html

states: The FROM clause can only refer to a single entity, which can be aliased. If the entity name is aliased, any property references must be qualified using that alias. If the entity name is not aliased, then it is illegal for any property references to be qualified.

I don't understand what it means...

What is the idea behind?
I'm trying to expose simple API for my model defined as JPA entities.
Users makes call
Code:
search(0, 100L, filter = List(And("child.id", EqualTo, 1L), And("child.name", EqualTo, "best name in the world"))

and it returns children with id=1 and name="best name in the world"


Top
 Profile  
 
 Post subject: Re: query nested object using HQL or better criteria builder
PostPosted: Mon Jul 03, 2017 10:02 am 
Hibernate Team
Hibernate Team

Joined: Thu Sep 11, 2014 2:50 am
Posts: 1516
While HQL and JPQl support nested properties:

Code:
select p
from Parent p
where
    p.child.id = :id


With JPA Criteria, you can't use nested properties so use the Join instead:

Code:
CriteriaBuilder builder = entityManager.getCriteriaBuilder();

CriteriaQuery<Phone> criteria = builder.createQuery( Parent.class );
Root<Parent> root = criteria.from( Parent.class );

// Phone.person is a @ManyToOne
Join<Parent, Child> childJoin = root.join( "child" );

criteria.where( builder.equal( childJoin.get( "id" ), 123L ) );


P.S. - That's not really a parent-child association because, in your schema, a Child can exist even without a Parent.

_________________
If you liked my answer, you are going to love my High-Performance Java Persistence book and my blog as well.


Top
 Profile  
 
 Post subject: Re: query nested object using HQL or better criteria builder
PostPosted: Mon Jul 03, 2017 10:10 am 
Newbie

Joined: Mon Jul 03, 2017 6:40 am
Posts: 10
vlad wrote:
You can't use nested properties so use


Hi vlad, thanks for your reply. What is the limitation behind it? I can define object graph with many nested objects, I can even define graph in runtime, but I can't apply "filters" to such graph.

What is the problem behind? We can compose complex native SQL query with SQL joins for nested objects and map it on Object tree, but we ca't mix-in join predicates?

Code:
// Phone.person is a @ManyToOne
Join<Parent, Child> childJoin = root.join( "child" );


My hope was I can do it generic...

Thanks for your answer!


Top
 Profile  
 
 Post subject: Re: Query nested objects using HQL or Criteria Builder
PostPosted: Mon Jul 03, 2017 10:51 am 
Hibernate Team
Hibernate Team

Joined: Thu Sep 11, 2014 2:50 am
Posts: 1516
Quote:
Hi vlad, thanks for your reply. What is the limitation behind it? I can define object graph with many nested objects, I can even define graph in runtime, but I can't apply "filters" to such graph.


That's just the way it is. You can still achieve the same goal using chaining property calls:

Code:
criteriaBuilder.equal(rootObj.get(Parent_.child).get(Child_.id), childId));


Quote:
What is the problem behind? We can compose complex native SQL query with SQL joins for nested objects and map it on Object tree, but we ca't mix-in join predicates?


Yes, because JPQL is a static query while Criteria API is built dynamically and programatically, and since you can use the type-safe Metamodel, you could guarantee the nested call path exists even at compile time.

_________________
If you liked my answer, you are going to love my High-Performance Java Persistence book and my blog as well.


Top
 Profile  
 
 Post subject: Re: Query nested objects using HQL or Criteria Builder
PostPosted: Tue Jul 04, 2017 1:48 pm 
Newbie

Joined: Mon Jul 03, 2017 6:40 am
Posts: 10
vlad wrote:
Yes, because JPQL is a static query while Criteria API is built dynamically and programatically, and since you can use the type-safe Metamodel, you could guarantee the nested call path exists even at compile time.


What if I don't want statically compiled thing? And I don't want to generate messy JPQL on the fly. I want to reuse builder API building my expressions in runtime. Looks like it contradicts design and impossible to have, correct?
I understand downsides of my approach, I have 4 nested levels model and I don't want to pre-define / generate something static. I want to build filtering queries for my model on the fly.


Top
 Profile  
 
 Post subject: Re: Query nested objects using HQL or Criteria Builder
PostPosted: Wed Jul 05, 2017 12:39 am 
Hibernate Team
Hibernate Team

Joined: Thu Sep 11, 2014 2:50 am
Posts: 1516
Quote:
I have 4 nested levels model and I don't want to pre-define / generate something static. I want to build filtering queries for my model on the fly.


You can still do it. Just parse the nested property path, get the tokens and use them to build the Criteria API programmatically as I illustrated earlier.

_________________
If you liked my answer, you are going to love my High-Performance Java Persistence book and my blog as well.


Top
 Profile  
 
 Post subject: Re: Query nested objects using HQL or Criteria Builder
PostPosted: Wed Jul 05, 2017 4:10 am 
Newbie

Joined: Mon Jul 03, 2017 6:40 am
Posts: 10
vlad wrote:
You can still do it. Just parse the nested property path, get the tokens and use them to build the Criteria API programmatically as I illustrated earlier.


Quote:
criteriaBuilder.equal(rootObj.get(Parent_.child).get(Child_.id), childId));


Sorry, read your replies few more times, now I realize that I have to define a kind of "full path to end property" step by step:

(Parent_.child) -> (Child_.id)

I case of deep nesting in should be

(GrandParent_.parent) -> (Parent.child) -> (Child.id)

did I understand you in the right way?


Top
 Profile  
 
 Post subject: Re: Query nested objects using HQL or Criteria Builder
PostPosted: Wed Jul 05, 2017 4:28 am 
Hibernate Team
Hibernate Team

Joined: Thu Sep 11, 2014 2:50 am
Posts: 1516
That's right.

_________________
If you liked my answer, you are going to love my High-Performance Java Persistence book and my blog as well.


Top
 Profile  
 
 Post subject: Re: Query nested objects using HQL or Criteria Builder
PostPosted: Fri Jul 07, 2017 8:10 am 
Newbie

Joined: Mon Jul 03, 2017 6:40 am
Posts: 10
vlad wrote:
That's right.

Awesome, it works. Some type black magic was required since I operate on paths as strings, not as metamodel entities.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 9 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.